diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index 1ebc998a40ed..4cd296127c1c 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -152,6 +152,16 @@ var (
Usage: "Sepolia network: pre-configured proof-of-work test network",
Category: flags.EthCategory,
}
+ GnosisChainFlag = &cli.BoolFlag{
+ Name: "gnosis",
+ Usage: "Gnosis chain network: pre-configured merged proof-of-authority test network",
+ Category: flags.EthCategory,
+ }
+ ChiadoFlag = &cli.BoolFlag{
+ Name: "chiado",
+ Usage: "Chiado network: pre-configured merged proof-of-authority test network",
+ Category: flags.EthCategory,
+ }
// Dev mode
DeveloperFlag = &cli.BoolFlag{
@@ -928,6 +938,8 @@ var (
TestnetFlags = []cli.Flag{
GoerliFlag,
SepoliaFlag,
+ GnosisChainFlag,
+ ChiadoFlag,
}
// NetworkFlags is the flag group of all built-in supported networks.
NetworkFlags = append([]cli.Flag{MainnetFlag}, TestnetFlags...)
@@ -958,6 +970,12 @@ func MakeDataDir(ctx *cli.Context) string {
if ctx.Bool(SepoliaFlag.Name) {
return filepath.Join(path, "sepolia")
}
+ if ctx.Bool(GnosisChainFlag.Name) {
+ return filepath.Join(path, "gnosis")
+ }
+ if ctx.Bool(ChiadoFlag.Name) {
+ return filepath.Join(path, "chiado")
+ }
return path
}
Fatalf("Cannot determine default data directory, please set manually (--datadir)")
@@ -1008,6 +1026,10 @@ func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
urls = params.SepoliaBootnodes
case ctx.Bool(GoerliFlag.Name):
urls = params.GoerliBootnodes
+ case ctx.Bool(GnosisChainFlag.Name):
+ urls = params.GnosisBootnodes
+ case ctx.Bool(ChiadoFlag.Name):
+ urls = params.ChiadoBootnodes
}
// don't apply defaults if BootstrapNodes is already set
@@ -1457,6 +1479,10 @@ func SetDataDir(ctx *cli.Context, cfg *node.Config) {
cfg.DataDir = filepath.Join(node.DefaultDataDir(), "goerli")
case ctx.Bool(SepoliaFlag.Name) && cfg.DataDir == node.DefaultDataDir():
cfg.DataDir = filepath.Join(node.DefaultDataDir(), "sepolia")
+ case ctx.Bool(GnosisChainFlag.Name) && cfg.DataDir == node.DefaultDataDir():
+ cfg.DataDir = filepath.Join(node.DefaultDataDir(), "gnosis")
+ case ctx.Bool(ChiadoFlag.Name) && cfg.DataDir == node.DefaultDataDir():
+ cfg.DataDir = filepath.Join(node.DefaultDataDir(), "chiado")
}
}
@@ -1613,7 +1639,7 @@ func CheckExclusive(ctx *cli.Context, args ...interface{}) {
// SetEthConfig applies eth-related command line flags to the config.
func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
// Avoid conflicting network flags
- CheckExclusive(ctx, MainnetFlag, DeveloperFlag, GoerliFlag, SepoliaFlag)
+ CheckExclusive(ctx, MainnetFlag, DeveloperFlag, GoerliFlag, SepoliaFlag, GnosisChainFlag, ChiadoFlag)
CheckExclusive(ctx, LightServeFlag, SyncModeFlag, "light")
CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer
if ctx.String(GCModeFlag.Name) == "archive" && ctx.Uint64(TxLookupLimitFlag.Name) != 0 {
@@ -1761,6 +1787,18 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
}
cfg.Genesis = core.DefaultGoerliGenesisBlock()
SetDNSDiscoveryDefaults(cfg, params.GoerliGenesisHash)
+ case ctx.Bool(GnosisChainFlag.Name):
+ if !ctx.IsSet(NetworkIdFlag.Name) {
+ cfg.NetworkId = 100
+ }
+ cfg.Genesis = core.DefaultGnosisGenesisBlock()
+ SetDNSDiscoveryDefaults(cfg, params.GnosisChainHash)
+ case ctx.Bool(ChiadoFlag.Name):
+ if !ctx.IsSet(NetworkIdFlag.Name) {
+ cfg.NetworkId = 10200
+ }
+ cfg.Genesis = core.DefaultChiadoGenesisBlock()
+ SetDNSDiscoveryDefaults(cfg, params.ChiadoGenesisHash)
case ctx.Bool(DeveloperFlag.Name):
if !ctx.IsSet(NetworkIdFlag.Name) {
cfg.NetworkId = 1337
@@ -2087,6 +2125,10 @@ func MakeGenesis(ctx *cli.Context) *core.Genesis {
genesis = core.DefaultSepoliaGenesisBlock()
case ctx.Bool(GoerliFlag.Name):
genesis = core.DefaultGoerliGenesisBlock()
+ case ctx.Bool(GnosisChainFlag.Name):
+ genesis = core.DefaultGnosisGenesisBlock()
+ case ctx.Bool(ChiadoFlag.Name):
+ genesis = core.DefaultChiadoGenesisBlock()
case ctx.Bool(DeveloperFlag.Name):
Fatalf("Developer chains are ephemeral")
}
diff --git a/consensus/aura/api.go b/consensus/aura/api.go
new file mode 100644
index 000000000000..89e17d579967
--- /dev/null
+++ b/consensus/aura/api.go
@@ -0,0 +1,32 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package aura
+
+import (
+ "github.com/ethereum/go-ethereum/consensus"
+)
+
+// API is a user facing RPC API to allow controlling the signer and voting
+// mechanisms of the proof-of-authority scheme.
+type API struct {
+ chain consensus.ChainHeaderReader
+ aura *Aura
+}
+
+func (api *API) Version() string {
+ return "0.1"
+}
diff --git a/consensus/aura/aura.go b/consensus/aura/aura.go
new file mode 100644
index 000000000000..ae190737b9e8
--- /dev/null
+++ b/consensus/aura/aura.go
@@ -0,0 +1,591 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package aura
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "math"
+ "math/big"
+ "sync"
+ "time"
+
+ "github.com/ethereum/go-ethereum/accounts"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/consensus"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/log"
+ "github.com/ethereum/go-ethereum/params"
+ "github.com/ethereum/go-ethereum/rlp"
+ "github.com/ethereum/go-ethereum/rpc"
+ "github.com/ethereum/go-ethereum/trie"
+ lru "github.com/hashicorp/golang-lru"
+ "github.com/holiman/uint256"
+ "golang.org/x/crypto/sha3"
+)
+
+const (
+ checkpointInterval = 1024 // Number of blocks after which to save the vote snapshot to the database
+ inmemorySnapshots = 128 // Number of recent vote snapshots to keep in memory
+ inmemorySignatures = 4096 // Number of recent block signatures to keep in memory
+
+ wiggleTime = 500 * time.Millisecond // Random delay (per signer) to allow concurrent signers
+)
+
+// Clique proof-of-authority protocol constants.
+var (
+ epochLength = uint64(30000) // Default number of blocks after which to checkpoint and reset the pending votes
+
+ extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity
+ extraSeal = 65 // Fixed number of extra-data suffix bytes reserved for signer seal
+
+ uncleHash = types.CalcUncleHash(nil) // Always Keccak256(RLP([])) as uncles are meaningless outside of PoW.
+)
+
+// Various error messages to mark blocks invalid. These should be private to
+// prevent engine specific errors from being referenced in the remainder of the
+// codebase, inherently breaking if the engine is swapped out. Please put common
+// error types into the consensus package.
+var (
+ // errUnknownBlock is returned when the list of signers is requested for a block
+ // that is not part of the local blockchain.
+ errUnknownBlock = errors.New("unknown block")
+
+ // errInvalidCheckpointBeneficiary is returned if a checkpoint/epoch transition
+ // block has a beneficiary set to non-zeroes.
+ errInvalidCheckpointBeneficiary = errors.New("beneficiary in checkpoint block non-zero")
+
+ // errInvalidVote is returned if a nonce value is something else that the two
+ // allowed constants of 0x00..0 or 0xff..f.
+ errInvalidVote = errors.New("vote nonce not 0x00..0 or 0xff..f")
+
+ // errInvalidCheckpointVote is returned if a checkpoint/epoch transition block
+ // has a vote nonce set to non-zeroes.
+ errInvalidCheckpointVote = errors.New("vote nonce in checkpoint block non-zero")
+
+ // errMissingVanity is returned if a block's extra-data section is shorter than
+ // 32 bytes, which is required to store the signer vanity.
+ errMissingVanity = errors.New("extra-data 32 byte vanity prefix missing")
+
+ // errMissingSignature is returned if a block's extra-data section doesn't seem
+ // to contain a 65 byte secp256k1 signature.
+ errMissingSignature = errors.New("extra-data 65 byte suffix signature missing")
+
+ // errExtraSigners is returned if non-checkpoint block contain signer data in
+ // their extra-data fields.
+ errExtraSigners = errors.New("non-checkpoint block contains extra signer list")
+
+ // errInvalidValidatorSeal is returned if the extra data field length is not
+ // equal to the length of a seal
+ errInvalidExtraData = errors.New("extra data field in block header is invalid")
+
+ // errInvalidCheckpointSigners is returned if a checkpoint block contains an
+ // invalid list of signers (i.e. non divisible by 20 bytes, or not the correct
+ // ones).
+ errInvalidCheckpointSigners = errors.New("invalid signer list on checkpoint block")
+
+ // errInvalidMixDigest is returned if a block's mix digest is non-zero.
+ errInvalidMixDigest = errors.New("non-zero mix digest")
+
+ // errInvalidUncleHash is returned if a block contains an non-empty uncle list.
+ errInvalidUncleHash = errors.New("non empty uncle hash")
+
+ // errInvalidDifficulty is returned if the difficulty of a block is not either
+ // of 1 or 2, or if the value does not match the turn of the signer.
+ errInvalidDifficulty = errors.New("invalid difficulty")
+
+ // ErrInvalidTimestamp is returned if the timestamp of a block is lower than
+ // the previous block's timestamp + the minimum block period.
+ ErrInvalidTimestamp = errors.New("invalid timestamp")
+
+ // errInvalidVotingChain is returned if an authorization list is attempted to
+ // be modified via out-of-range or non-contiguous headers.
+ errInvalidVotingChain = errors.New("invalid voting chain")
+
+ // errUnauthorized is returned if a header is signed by a non-authorized entity.
+ errUnauthorized = errors.New("unauthorized")
+
+ // errWaitTransactions is returned if an empty block is attempted to be sealed
+ // on an instant chain (0 second period). It's important to refuse these as the
+ // block reward is zero, so an empty block just bloats the chain... fast.
+ errWaitTransactions = errors.New("waiting for transactions")
+)
+
+// SignerFn is a signer callback function to request a hash to be signed by a
+// backing account.
+type SignerFn func(accounts.Account, []byte) ([]byte, error)
+
+// sigHash returns the hash which is used as input for the proof-of-authority
+// signing. It is the hash of the entire header apart from the 65 byte signature
+// contained at the end of the extra data.
+//
+// Note, the method requires the extra data to be at least 65 bytes, otherwise it
+// panics. This is done to avoid accidentally using both forms (signature present
+// or not), which could be abused to produce different hashes for the same header.
+func sigHash(header *types.Header) (hash common.Hash) {
+ hasher := sha3.NewLegacyKeccak256()
+
+ rlp.Encode(hasher, []interface{}{
+ header.ParentHash,
+ header.UncleHash,
+ header.Coinbase,
+ header.Root,
+ header.TxHash,
+ header.ReceiptHash,
+ header.Bloom,
+ header.Difficulty,
+ header.Number,
+ header.GasLimit,
+ header.GasUsed,
+ header.Time,
+ header.Extra[:len(header.Extra)-65], // Yes, this will panic if extra is too short
+ header.MixDigest,
+ header.Nonce,
+ })
+ hasher.Sum(hash[:0])
+ return hash
+}
+
+// ecrecover extracts the Ethereum account address from a signed header.
+func ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, error) {
+ // If the signature's already cached, return that
+ hash := header.Hash()
+ if address, known := sigcache.Get(hash); known {
+ return address.(common.Address), nil
+ }
+ // Retrieve the signature from the header extra-data
+ if len(header.Extra) < extraSeal {
+ return common.Address{}, errMissingSignature
+ }
+ signature := header.Extra[len(header.Extra)-extraSeal:]
+
+ // Recover the public key and the Ethereum address
+ pubkey, err := crypto.Ecrecover(sigHash(header).Bytes(), signature)
+ if err != nil {
+ return common.Address{}, err
+ }
+ var signer common.Address
+ copy(signer[:], crypto.Keccak256(pubkey[1:])[12:])
+
+ sigcache.Add(hash, signer)
+ return signer, nil
+}
+
+// Clique is the proof-of-authority consensus engine proposed to support the
+// Ethereum testnet following the Ropsten attacks.
+type Aura struct {
+ config *params.AuthorityRoundParams // Consensus engine configuration parameters
+ db ethdb.Database // Database to store and retrieve snapshot checkpoints
+
+ recents *lru.ARCCache // Snapshots for recent block to speed up reorgs
+ signatures *lru.ARCCache // Signatures of recent blocks to speed up mining
+
+ proposals map[common.Address]bool // Current list of proposals we are pushing
+
+ signer common.Address // Ethereum address of the signing key
+ signFn SignerFn // Signer function to authorize hashes with
+ lock sync.RWMutex // Protects the signer fields
+}
+
+// New creates a Aura proof-of-authority consensus engine with the initial
+// signers set to the ones provided by the user.
+func New(config *params.AuthorityRoundParams, db ethdb.Database) *Aura {
+ // Set any missing consensus parameters to their defaults
+ conf := *config
+ // Allocate the snapshot caches and create the engine
+ recents, _ := lru.NewARC(inmemorySnapshots)
+ signatures, _ := lru.NewARC(inmemorySignatures)
+
+ return &Aura{
+ config: &conf,
+ db: db,
+ recents: recents,
+ signatures: signatures,
+ proposals: make(map[common.Address]bool),
+ }
+}
+
+// Author implements consensus.Engine, returning the Ethereum address recovered
+// from the signature in the header's extra-data section.
+func (a *Aura) Author(header *types.Header) (common.Address, error) {
+ return ecrecover(header, a.signatures)
+}
+
+// VerifyHeader checks whether a header conforms to the consensus rules.
+func (a *Aura) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header) error {
+ return a.verifyHeader(chain, header, nil)
+}
+
+// VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers. The
+// method returns a quit channel to abort the operations and a results channel to
+// retrieve the async verifications (the order is that of the input slice).
+func (a *Aura) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header) (chan<- struct{}, <-chan error) {
+ abort := make(chan struct{})
+ results := make(chan error, len(headers))
+
+ go func() {
+ for i, header := range headers {
+ err := a.verifyHeader(chain, header, headers[:i])
+
+ select {
+ case <-abort:
+ return
+ case results <- err:
+ }
+ }
+ }()
+ return abort, results
+}
+
+// verifyHeader checks whether a header conforms to the consensus rules.The
+// caller may optionally pass in a batch of parents (ascending order) to avoid
+// looking those up from the database. This is useful for concurrently verifying
+// a batch of new headers.
+func (a *Aura) verifyHeader(chain consensus.ChainHeaderReader, header *types.Header, parents []*types.Header) error {
+ // accept all blocks
+ return nil
+}
+
+// VerifyUncles implements consensus.Engine, always returning an error for any
+// uncles as this consensus mechanism doesn't permit uncles.
+func (a *Aura) VerifyUncles(chain consensus.ChainReader, block *types.Block) error {
+ if len(block.Uncles()) > 0 {
+ return errors.New("uncles not allowed")
+ }
+ return nil
+}
+
+// VerifySeal implements consensus.Engine, checking whether the signature contained
+// in the header satisfies the consensus protocol requirements.
+func (a *Aura) VerifySeal(chain consensus.ChainHeaderReader, header *types.Header) error {
+ return a.verifySeal(chain, header, nil)
+}
+
+// verifySeal checks whether the signature contained in the header satisfies the
+// consensus protocol requirements. The method accepts an optional list of parent
+// headers that aren't yet part of the local blockchain to generate the snapshots
+// from.
+func (a *Aura) verifySeal(chain consensus.ChainHeaderReader, header *types.Header, parents []*types.Header) error {
+ // Verifying the genesis block is not supported
+ number := header.Number.Uint64()
+ if number == 0 {
+ return errUnknownBlock
+ }
+ return nil
+}
+
+// Prepare implements consensus.Engine, preparing all the consensus fields of the
+// header for running the transactions on top.
+func (a *Aura) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error {
+ return nil
+}
+
+// RewardKind - The kind of block reward.
+// Depending on the consensus engine the allocated block reward might have
+// different semantics which could lead e.g. to different reward values.
+type RewardKind uint16
+
+const (
+ // RewardAuthor - attributed to the block author.
+ RewardAuthor RewardKind = 0
+ // RewardEmptyStep - attributed to the author(s) of empty step(s) included in the block (AuthorityRound engine).
+ RewardEmptyStep RewardKind = 1
+ // RewardExternal - attributed by an external protocol (e.g. block reward contract).
+ RewardExternal RewardKind = 2
+ // RewardUncle - attributed to the block uncle(s) with given difference.
+ RewardUncle RewardKind = 3
+)
+
+type Reward struct {
+ Beneficiary common.Address
+ Kind RewardKind
+ Amount uint256.Int
+}
+
+type BlockRewardContract struct {
+ blockNum uint64
+ address common.Address // On-chain address.
+}
+
+type BlockRewardContractList []BlockRewardContract
+
+func (r BlockRewardContractList) Less(i, j int) bool { return r[i].blockNum < r[j].blockNum }
+func (r BlockRewardContractList) Len() int { return len(r) }
+func (r BlockRewardContractList) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
+
+type BlockReward struct {
+ blockNum uint64
+ amount *uint256.Int
+}
+
+type BlockRewardList []BlockReward
+
+func (a *Aura) CalculateRewards(header *types.Header, _ []*types.Header, chain consensus.ChainHeaderReader, statedb *state.StateDB) ([]Reward, error) {
+ var rewardContractAddress BlockRewardContract
+ rewardContractAddress = BlockRewardContract{
+ blockNum: 9186425,
+ address: common.HexToAddress("0x481c034c6d9441db23ea48de68bcae812c5d39ba"),
+ }
+ if /*foundContract */ true {
+ beneficiaries := []common.Address{header.Coinbase}
+ rewardKind := []RewardKind{RewardAuthor}
+ var amounts []*uint256.Int
+ beneficiaries, amounts = callBlockRewardAbi(rewardContractAddress.address, beneficiaries, rewardKind, chain, header, statedb)
+ rewards := make([]Reward, len(amounts))
+ for i, amount := range amounts {
+ rewards[i].Beneficiary = beneficiaries[i]
+ rewards[i].Kind = RewardExternal
+ rewards[i].Amount = *amount
+ }
+ return rewards, nil
+ }
+
+ r := Reward{Beneficiary: header.Coinbase, Kind: RewardAuthor, Amount: *uint256.NewInt(0)}
+ return []Reward{r}, nil
+}
+func callBlockRewardAbi(contractAddr common.Address, beneficiaries []common.Address, rewardKind []RewardKind, chain consensus.ChainHeaderReader, header *types.Header, statedb *state.StateDB) ([]common.Address, []*uint256.Int) {
+ castedKind := make([]uint16, len(rewardKind))
+ for i := range rewardKind {
+ castedKind[i] = uint16(rewardKind[i])
+ }
+ packed, err := blockRewardAbi().Pack("reward", beneficiaries, castedKind)
+ if err != nil {
+ panic(err)
+ }
+ out, err := syscall(contractAddr, packed, chain, header, statedb)
+ if err != nil {
+ panic(err)
+ }
+ if len(out) == 0 {
+ return nil, nil
+ }
+ res, err := blockRewardAbi().Unpack("reward", out)
+ if err != nil {
+ panic(err)
+ }
+ beneficiariesRes := res[0].([]common.Address)
+ rewardsBig := res[1].([]*big.Int)
+ rewardsU256 := make([]*uint256.Int, len(rewardsBig))
+ for i := 0; i < len(rewardsBig); i++ {
+ var overflow bool
+ rewardsU256[i], overflow = uint256.FromBig(rewardsBig[i])
+ if overflow {
+ panic("Overflow in callBlockRewardAbi")
+ }
+ }
+ return beneficiariesRes, rewardsU256
+}
+
+var (
+ blockRewardABIJSON = `[
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "benefactors",
+ "type": "address[]"
+ },
+ {
+ "name": "kind",
+ "type": "uint16[]"
+ }
+ ],
+ "name": "reward",
+ "outputs": [
+ {
+ "name": "",
+ "type": "address[]"
+ },
+ {
+ "name": "",
+ "type": "uint256[]"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ }
+]`
+
+ withdrawalABIJSON = `[
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "maxNumberOfFailedWithdrawalsToProcess",
+ "type": "uint256"
+ },
+ {
+ "name": "amounts",
+ "type": "uint64[]"
+ },
+ {
+ "name": "addresses",
+ "type": "address[]"
+ }
+ ],
+ "name": "executeSystemWithdrawals",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ }
+]`
+)
+
+func blockRewardAbi() abi.ABI {
+ a, err := abi.JSON(bytes.NewReader([]byte(blockRewardABIJSON)))
+ if err != nil {
+ panic(err)
+ }
+ return a
+}
+
+func (a *Aura) applyRewards(header *types.Header, state *state.StateDB, chain consensus.ChainHeaderReader) error {
+ rewards, err := a.CalculateRewards(header, nil, chain, state)
+ if err != nil {
+ return err
+ }
+ for _, r := range rewards {
+ state.AddBalance(r.Beneficiary, r.Amount.ToBig())
+ }
+ return nil
+}
+
+func withdrawalAbi() abi.ABI {
+ a, err := abi.JSON(bytes.NewReader([]byte(withdrawalABIJSON)))
+ if err != nil {
+ panic(err)
+ }
+ return a
+}
+
+func syscall(contractaddr common.Address, data []byte, chain consensus.ChainHeaderReader, header *types.Header, statedb *state.StateDB) ([]byte, error) {
+ sysaddr := common.HexToAddress("fffffffffffffffffffffffffffffffffffffffe")
+ msg := &core.Message{
+ To: &contractaddr,
+ From: sysaddr,
+ Nonce: 0,
+ Value: big.NewInt(0),
+ GasLimit: math.MaxUint64,
+ GasPrice: big.NewInt(0),
+ GasFeeCap: nil,
+ GasTipCap: nil,
+ Data: data,
+ AccessList: nil,
+ BlobHashes: nil,
+ SkipAccountChecks: false,
+ }
+ txctx := core.NewEVMTxContext(msg)
+ blkctx := core.NewEVMBlockContext(header, chain.(*core.BlockChain), nil)
+ evm := vm.NewEVM(blkctx, txctx, statedb, chain.Config(), vm.Config{ /*Debug: true, Tracer: logger.NewJSONLogger(nil, os.Stdout)*/ })
+ ret, _, err := evm.Call(vm.AccountRef(sysaddr), contractaddr, data, math.MaxUint64, new(big.Int))
+ if err != nil {
+ panic(err)
+ }
+ statedb.Finalise(true)
+ return ret, err
+}
+
+// Finalize implements consensus.Engine, ensuring no uncles are set, nor block
+// rewards given, and returns the final block.
+func (a *Aura) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) {
+ if err := a.applyRewards(header, state, chain); err != nil {
+ panic(fmt.Sprintf("error applying reward %v", err))
+ }
+
+ // No block rewards in PoA, so the state remains as is and uncles are dropped
+ header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
+ header.UncleHash = types.CalcUncleHash(nil)
+}
+
+func (a *Aura) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) {
+ a.Finalize(chain, header, state, txs, uncles, withdrawals)
+
+ // Assemble and return the final block for sealing
+ return types.NewBlock(header, txs, nil, receipts, trie.NewStackTrie(nil)), nil
+}
+
+// Authorize injects a private key into the consensus engine to mint new blocks
+// with.
+func (a *Aura) Authorize(signer common.Address, signFn SignerFn) {
+ a.lock.Lock()
+ defer a.lock.Unlock()
+
+ a.signer = signer
+ a.signFn = signFn
+}
+
+// Seal implements consensus.Engine, attempting to create a sealed block using
+// the local signing credentials.
+func (a *Aura) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error {
+ return nil
+}
+
+// Returns difficulty constant from config
+func (a *Aura) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int {
+ return big.NewInt(0)
+}
+
+// SealHash returns the hash of a block prior to it being sealed.
+func (a *Aura) SealHash(header *types.Header) common.Hash {
+ return sigHash(header)
+}
+
+// Close implements consensus.Engine. It's a noop for clique as there is are no background threads.
+func (a *Aura) Close() error {
+ return nil
+}
+
+// APIs implements consensus.Engine, returning the user facing RPC API to allow
+// controlling the signer voting.
+func (a *Aura) APIs(chain consensus.ChainHeaderReader) []rpc.API {
+ return []rpc.API{{
+ Namespace: "aura",
+ Version: "1.0",
+ Service: &API{chain: chain, aura: a},
+ Public: false,
+ }}
+}
+
+func (a *Aura) ExecuteSystemWithdrawals(withdrawals []*types.Withdrawal, chain consensus.ChainHeaderReader, header *types.Header, statedb *state.StateDB) error {
+ withdrawalContactAddress := common.HexToAddress("0x0B98057eA310F4d31F2a452B414647007d1645d9")
+ maxFailedWithdrawalsToProcess := big.NewInt(4)
+ amounts := make([]uint64, 0, len(withdrawals))
+ addresses := make([]common.Address, 0, len(withdrawals))
+ for _, w := range withdrawals {
+ amounts = append(amounts, w.Amount)
+ addresses = append(addresses, w.Address)
+ }
+
+ packed, err := withdrawalAbi().Pack("executeSystemWithdrawals", maxFailedWithdrawalsToProcess, amounts, addresses)
+ if err != nil {
+ return err
+ }
+
+ _, err = syscall(withdrawalContactAddress, packed, chain, header, statedb)
+ if err != nil {
+ log.Warn("ExecuteSystemWithdrawals", "err", err)
+ }
+ return err
+}
diff --git a/consensus/aura/auraabi/gen_block_reward.go b/consensus/aura/auraabi/gen_block_reward.go
new file mode 100644
index 000000000000..ab8577b63e24
--- /dev/null
+++ b/consensus/aura/auraabi/gen_block_reward.go
@@ -0,0 +1,193 @@
+// Code generated - DO NOT EDIT.
+// This file is a generated binding and any manual changes will be lost.
+
+package auraabi
+
+import (
+ "math/big"
+ "strings"
+
+ ethereum "github.com/ethereum/go-ethereum"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/accounts/abi/bind"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/event"
+ "github.com/ethereum/go-ethereum/common"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var (
+ _ = big.NewInt
+ _ = strings.NewReader
+ _ = ethereum.NotFound
+ _ = bind.Bind
+ _ = common.Big1
+ _ = types.BloomLookup
+ _ = event.NewSubscription
+)
+
+// BlockRewardABI is the input ABI used to generate the binding from.
+const BlockRewardABI = "[{\"constant\":false,\"inputs\":[{\"name\":\"benefactors\",\"type\":\"address[]\"},{\"name\":\"kind\",\"type\":\"uint16[]\"}],\"name\":\"reward\",\"outputs\":[{\"name\":\"\",\"type\":\"address[]\"},{\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"
+
+// BlockReward is an auto generated Go binding around an Ethereum contract.
+type BlockReward struct {
+ BlockRewardCaller // Read-only binding to the contract
+ BlockRewardTransactor // Write-only binding to the contract
+ BlockRewardFilterer // Log filterer for contract events
+}
+
+// BlockRewardCaller is an auto generated read-only Go binding around an Ethereum contract.
+type BlockRewardCaller struct {
+ contract *bind.BoundContract // Generic contract wrapper for the low level calls
+}
+
+// BlockRewardTransactor is an auto generated write-only Go binding around an Ethereum contract.
+type BlockRewardTransactor struct {
+ contract *bind.BoundContract // Generic contract wrapper for the low level calls
+}
+
+// BlockRewardFilterer is an auto generated log filtering Go binding around an Ethereum contract events.
+type BlockRewardFilterer struct {
+ contract *bind.BoundContract // Generic contract wrapper for the low level calls
+}
+
+// BlockRewardSession is an auto generated Go binding around an Ethereum contract,
+// with pre-set call and transact options.
+type BlockRewardSession struct {
+ Contract *BlockReward // Generic contract binding to set the session for
+ CallOpts bind.CallOpts // Call options to use throughout this session
+ TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
+}
+
+// BlockRewardCallerSession is an auto generated read-only Go binding around an Ethereum contract,
+// with pre-set call options.
+type BlockRewardCallerSession struct {
+ Contract *BlockRewardCaller // Generic contract caller binding to set the session for
+ CallOpts bind.CallOpts // Call options to use throughout this session
+}
+
+// BlockRewardTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
+// with pre-set transact options.
+type BlockRewardTransactorSession struct {
+ Contract *BlockRewardTransactor // Generic contract transactor binding to set the session for
+ TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
+}
+
+// BlockRewardRaw is an auto generated low-level Go binding around an Ethereum contract.
+type BlockRewardRaw struct {
+ Contract *BlockReward // Generic contract binding to access the raw methods on
+}
+
+// BlockRewardCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
+type BlockRewardCallerRaw struct {
+ Contract *BlockRewardCaller // Generic read-only contract binding to access the raw methods on
+}
+
+// BlockRewardTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
+type BlockRewardTransactorRaw struct {
+ Contract *BlockRewardTransactor // Generic write-only contract binding to access the raw methods on
+}
+
+// NewBlockReward creates a new instance of BlockReward, bound to a specific deployed contract.
+func NewBlockReward(address common.Address, backend bind.ContractBackend) (*BlockReward, error) {
+ contract, err := bindBlockReward(address, backend, backend, backend)
+ if err != nil {
+ return nil, err
+ }
+ return &BlockReward{BlockRewardCaller: BlockRewardCaller{contract: contract}, BlockRewardTransactor: BlockRewardTransactor{contract: contract}, BlockRewardFilterer: BlockRewardFilterer{contract: contract}}, nil
+}
+
+// NewBlockRewardCaller creates a new read-only instance of BlockReward, bound to a specific deployed contract.
+func NewBlockRewardCaller(address common.Address, caller bind.ContractCaller) (*BlockRewardCaller, error) {
+ contract, err := bindBlockReward(address, caller, nil, nil)
+ if err != nil {
+ return nil, err
+ }
+ return &BlockRewardCaller{contract: contract}, nil
+}
+
+// NewBlockRewardTransactor creates a new write-only instance of BlockReward, bound to a specific deployed contract.
+func NewBlockRewardTransactor(address common.Address, transactor bind.ContractTransactor) (*BlockRewardTransactor, error) {
+ contract, err := bindBlockReward(address, nil, transactor, nil)
+ if err != nil {
+ return nil, err
+ }
+ return &BlockRewardTransactor{contract: contract}, nil
+}
+
+// NewBlockRewardFilterer creates a new log filterer instance of BlockReward, bound to a specific deployed contract.
+func NewBlockRewardFilterer(address common.Address, filterer bind.ContractFilterer) (*BlockRewardFilterer, error) {
+ contract, err := bindBlockReward(address, nil, nil, filterer)
+ if err != nil {
+ return nil, err
+ }
+ return &BlockRewardFilterer{contract: contract}, nil
+}
+
+// bindBlockReward binds a generic wrapper to an already deployed contract.
+func bindBlockReward(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
+ parsed, err := abi.JSON(strings.NewReader(BlockRewardABI))
+ if err != nil {
+ return nil, err
+ }
+ return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil
+}
+
+// Call invokes the (constant) contract method with params as input values and
+// sets the output to result. The result type might be a single field for simple
+// returns, a slice of interfaces for anonymous returns and a struct for named
+// returns.
+func (_BlockReward *BlockRewardRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
+ return _BlockReward.Contract.BlockRewardCaller.contract.Call(opts, result, method, params...)
+}
+
+// Transfer initiates a plain transaction to move funds to the contract, calling
+// its default method if one is available.
+func (_BlockReward *BlockRewardRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
+ return _BlockReward.Contract.BlockRewardTransactor.contract.Transfer(opts)
+}
+
+// Transact invokes the (paid) contract method with params as input values.
+func (_BlockReward *BlockRewardRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
+ return _BlockReward.Contract.BlockRewardTransactor.contract.Transact(opts, method, params...)
+}
+
+// Call invokes the (constant) contract method with params as input values and
+// sets the output to result. The result type might be a single field for simple
+// returns, a slice of interfaces for anonymous returns and a struct for named
+// returns.
+func (_BlockReward *BlockRewardCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
+ return _BlockReward.Contract.contract.Call(opts, result, method, params...)
+}
+
+// Transfer initiates a plain transaction to move funds to the contract, calling
+// its default method if one is available.
+func (_BlockReward *BlockRewardTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
+ return _BlockReward.Contract.contract.Transfer(opts)
+}
+
+// Transact invokes the (paid) contract method with params as input values.
+func (_BlockReward *BlockRewardTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
+ return _BlockReward.Contract.contract.Transact(opts, method, params...)
+}
+
+// Reward is a paid mutator transaction binding the contract method 0xf91c2898.
+//
+// Solidity: function reward(address[] benefactors, uint16[] kind) returns(address[], uint256[])
+func (_BlockReward *BlockRewardTransactor) Reward(opts *bind.TransactOpts, benefactors []common.Address, kind []uint16) (*types.Transaction, error) {
+ return _BlockReward.contract.Transact(opts, "reward", benefactors, kind)
+}
+
+// Reward is a paid mutator transaction binding the contract method 0xf91c2898.
+//
+// Solidity: function reward(address[] benefactors, uint16[] kind) returns(address[], uint256[])
+func (_BlockReward *BlockRewardSession) Reward(benefactors []common.Address, kind []uint16) (*types.Transaction, error) {
+ return _BlockReward.Contract.Reward(&_BlockReward.TransactOpts, benefactors, kind)
+}
+
+// Reward is a paid mutator transaction binding the contract method 0xf91c2898.
+//
+// Solidity: function reward(address[] benefactors, uint16[] kind) returns(address[], uint256[])
+func (_BlockReward *BlockRewardTransactorSession) Reward(benefactors []common.Address, kind []uint16) (*types.Transaction, error) {
+ return _BlockReward.Contract.Reward(&_BlockReward.TransactOpts, benefactors, kind)
+}
diff --git a/consensus/beacon/consensus.go b/consensus/beacon/consensus.go
index c5d2a12a7b26..10539e2ad9bb 100644
--- a/consensus/beacon/consensus.go
+++ b/consensus/beacon/consensus.go
@@ -23,6 +23,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
+ "github.com/ethereum/go-ethereum/consensus/aura"
"github.com/ethereum/go-ethereum/consensus/misc"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
@@ -341,18 +342,19 @@ func (beacon *Beacon) Prepare(chain consensus.ChainHeaderReader, header *types.H
// Finalize implements consensus.Engine and processes withdrawals on top.
func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) {
- if !beacon.IsPoSHeader(header) {
- beacon.ethone.Finalize(chain, header, state, txs, uncles, nil)
- return
- }
- // Withdrawals processing.
- for _, w := range withdrawals {
- // Convert amount from gwei to wei.
- amount := new(big.Int).SetUint64(w.Amount)
- amount = amount.Mul(amount, big.NewInt(params.GWei))
- state.AddBalance(w.Address, amount)
+ // GNOSIS: force calling the underlying consensus engine since
+ // it only calls the reward contract. A cleaner approach would
+ // be to add the call to the reward contract here.
+ beacon.ethone.Finalize(chain, header, state, txs, uncles, nil)
+
+ // withdrawals processing.
+ if withdrawals != nil {
+ if auraEngine, ok := beacon.ethone.(*aura.Aura); ok {
+ if err := auraEngine.ExecuteSystemWithdrawals(withdrawals, chain, header, state); err != nil {
+ panic(err)
+ }
+ }
}
- // No block reward which is issued by consensus layer instead.
}
// FinalizeAndAssemble implements consensus.Engine, setting the final state and
diff --git a/core/blockchain.go b/core/blockchain.go
index c9b80bc2fffb..be3afcd85d2a 100644
--- a/core/blockchain.go
+++ b/core/blockchain.go
@@ -957,7 +957,7 @@ func (bc *BlockChain) Stop() {
// - HEAD: So we don't need to reprocess any blocks in the general case
// - HEAD-1: So we don't do large reorgs if our HEAD becomes an uncle
// - HEAD-127: So we have a hard limit on the number of blocks reexecuted
- if !bc.cacheConfig.TrieDirtyDisabled {
+ if /* !bc.cacheConfig.TrieDirtyDisabled */ false {
triedb := bc.triedb
for _, offset := range []uint64{0, 1, TriesInMemory - 1} {
diff --git a/core/forkid/forkid.go b/core/forkid/forkid.go
index f536019dac12..36820b951f79 100644
--- a/core/forkid/forkid.go
+++ b/core/forkid/forkid.go
@@ -293,5 +293,13 @@ func gatherForks(config *params.ChainConfig) ([]uint64, []uint64) {
if len(forksByTime) > 0 && forksByTime[0] == 0 {
forksByTime = forksByTime[1:]
}
- return forksByBlock, forksByTime
+ // hack-insert the poa reward contract block
+ var hackedForksByBlock []uint64
+ for i := range forksByBlock {
+ if i > 0 && forksByBlock[i-1] < 9186425 && forksByBlock[i] > 9186425 {
+ hackedForksByBlock = append(hackedForksByBlock, 9186425)
+ }
+ hackedForksByBlock = append(hackedForksByBlock, forksByBlock[i])
+ }
+ return hackedForksByBlock, forksByTime
}
diff --git a/core/genesis.go b/core/genesis.go
index 1e56845d8ad3..c5d604b64a88 100644
--- a/core/genesis.go
+++ b/core/genesis.go
@@ -23,6 +23,7 @@ import (
"errors"
"fmt"
"math/big"
+ "os"
"strings"
"github.com/ethereum/go-ethereum/common"
@@ -63,6 +64,7 @@ type Genesis struct {
GasUsed uint64 `json:"gasUsed"`
ParentHash common.Hash `json:"parentHash"`
BaseFee *big.Int `json:"baseFeePerGas"`
+ Signature []byte `json:"signature,omitempty"`
}
func ReadGenesis(db ethdb.Database) (*Genesis, error) {
@@ -193,6 +195,11 @@ func CommitGenesisState(db ethdb.Database, triedb *trie.Database, blockhash comm
genesis = DefaultGoerliGenesisBlock()
case params.SepoliaGenesisHash:
genesis = DefaultSepoliaGenesisBlock()
+ case params.GnosisChainHash:
+ genesis = DefaultGnosisGenesisBlock()
+ case params.ChiadoGenesisHash:
+ genesis = DefaultChiadoGenesisBlock()
+
}
if genesis != nil {
alloc = genesis.Alloc
@@ -205,11 +212,12 @@ func CommitGenesisState(db ethdb.Database, triedb *trie.Database, blockhash comm
// GenesisAccount is an account in the state of the genesis block.
type GenesisAccount struct {
- Code []byte `json:"code,omitempty"`
- Storage map[common.Hash]common.Hash `json:"storage,omitempty"`
- Balance *big.Int `json:"balance" gencodec:"required"`
- Nonce uint64 `json:"nonce,omitempty"`
- PrivateKey []byte `json:"secretKey,omitempty"` // for tests
+ Constructor []byte `json:"constructor,omitempty"`
+ Code []byte `json:"code,omitempty"`
+ Storage map[common.Hash]common.Hash `json:"storage,omitempty"`
+ Balance *big.Int `json:"balance" gencodec:"required"`
+ Nonce uint64 `json:"nonce,omitempty"`
+ PrivateKey []byte `json:"secretKey,omitempty"` // for tests
}
// field type overrides for gencodec
@@ -387,6 +395,7 @@ func LoadChainConfig(db ethdb.Database, genesis *Genesis) (*params.ChainConfig,
if stored != (common.Hash{}) {
storedcfg := rawdb.ReadChainConfig(db, stored)
if storedcfg != nil {
+ storedcfg.TerminalTotalDifficultyPassed = true
return storedcfg, nil
}
}
@@ -420,6 +429,24 @@ func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig {
return params.SepoliaChainConfig
case ghash == params.GoerliGenesisHash:
return params.GoerliChainConfig
+ case ghash == params.GnosisChainHash:
+ // Load the config from the chainspec
+ params.GnosisChainConfig.Aura = new(params.AuthorityRoundParams)
+ data, err := os.ReadFile("xdai.json")
+ if err != nil {
+ panic(fmt.Sprintf("could not find the gnosis chain spec file: %v", err))
+ }
+ json.Unmarshal(data, params.GnosisChainConfig.Aura)
+ return params.GnosisChainConfig
+ case ghash == params.ChiadoGenesisHash:
+ // Load the config from the chainspec
+ params.GnosisChainConfig.Aura = new(params.AuthorityRoundParams)
+ data, err := os.ReadFile("chiado.json")
+ if err != nil {
+ panic(fmt.Sprintf("could not find the chiado spec file: %v", err))
+ }
+ json.Unmarshal(data, params.ChiadoConfig.Aura)
+ return params.GnosisChainConfig
default:
return params.AllEthashProtocolChanges
}
@@ -443,6 +470,7 @@ func (g *Genesis) ToBlock() *types.Block {
Difficulty: g.Difficulty,
MixDigest: g.Mixhash,
Coinbase: g.Coinbase,
+ Signature: g.Signature,
Root: root,
}
if g.GasLimit == 0 {
@@ -549,6 +577,59 @@ func DefaultSepoliaGenesisBlock() *Genesis {
}
}
+// DefaultSepoliaGenesisBlock returns the Sepolia network genesis block.
+func DefaultGnosisGenesisBlock() *Genesis {
+ return &Genesis{
+ Config: params.GnosisChainConfig,
+ Nonce: 0,
+ GasLimit: 0x989680,
+ Difficulty: big.NewInt(0x20000),
+ Timestamp: 0,
+ Signature: make([]byte, 65),
+ Alloc: GenesisAlloc{
+ common.HexToAddress("0x0000000000000000000000000000000000000001"): GenesisAccount{
+ Balance: big.NewInt(1),
+ },
+ common.HexToAddress("0x0000000000000000000000000000000000000002"): GenesisAccount{
+ Balance: big.NewInt(1),
+ },
+ common.HexToAddress("0x0000000000000000000000000000000000000003"): GenesisAccount{
+ Balance: big.NewInt(1),
+ },
+ common.HexToAddress("0x0000000000000000000000000000000000000004"): GenesisAccount{
+ Balance: big.NewInt(1),
+ },
+ },
+ }
+}
+
+// DefaultSepoliaGenesisBlock returns the Sepolia network genesis block.
+func DefaultChiadoGenesisBlock() *Genesis {
+ // TODO incorrect
+ return &Genesis{
+ Config: params.GnosisChainConfig,
+ Nonce: 0,
+ GasLimit: 0x989680,
+ Difficulty: big.NewInt(0x20000),
+ Timestamp: 0,
+ Signature: make([]byte, 65),
+ Alloc: GenesisAlloc{
+ common.HexToAddress("0x0000000000000000000000000000000000000001"): GenesisAccount{
+ Balance: big.NewInt(1),
+ },
+ common.HexToAddress("0x0000000000000000000000000000000000000002"): GenesisAccount{
+ Balance: big.NewInt(1),
+ },
+ common.HexToAddress("0x0000000000000000000000000000000000000003"): GenesisAccount{
+ Balance: big.NewInt(1),
+ },
+ common.HexToAddress("0x0000000000000000000000000000000000000004"): GenesisAccount{
+ Balance: big.NewInt(1),
+ },
+ },
+ }
+}
+
// DeveloperGenesisBlock returns the 'geth --dev' genesis block.
func DeveloperGenesisBlock(period uint64, gasLimit uint64, faucet common.Address) *Genesis {
// Override the default period to the user requested one
diff --git a/core/rawdb/database.go b/core/rawdb/database.go
index e864bcb2e88e..eb7a7eba11e4 100644
--- a/core/rawdb/database.go
+++ b/core/rawdb/database.go
@@ -204,6 +204,8 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st
printChainMetadata(db)
return nil, err
}
+ // GNOSIS deactivate the freezer in this branch, it missing a lot of data and
+ // this branch is only meant for "normal" geths to snap sync from it.
// Since the freezer can be stored separately from the user's key-value database,
// there's a fairly high probability that the user requests invalid combinations
// of the freezer and database. Ensure that we don't shoot ourselves in the foot
@@ -226,70 +228,70 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st
// If the genesis hash is empty, we have a new key-value store, so nothing to
// validate in this method. If, however, the genesis hash is not nil, compare
// it to the freezer content.
- if kvgenesis, _ := db.Get(headerHashKey(0)); len(kvgenesis) > 0 {
- if frozen, _ := frdb.Ancients(); frozen > 0 {
- // If the freezer already contains something, ensure that the genesis blocks
- // match, otherwise we might mix up freezers across chains and destroy both
- // the freezer and the key-value store.
- frgenesis, err := frdb.Ancient(ChainFreezerHashTable, 0)
- if err != nil {
- printChainMetadata(db)
- return nil, fmt.Errorf("failed to retrieve genesis from ancient %v", err)
- } else if !bytes.Equal(kvgenesis, frgenesis) {
- printChainMetadata(db)
- return nil, fmt.Errorf("genesis mismatch: %#x (leveldb) != %#x (ancients)", kvgenesis, frgenesis)
- }
- // Key-value store and freezer belong to the same network. Ensure that they
- // are contiguous, otherwise we might end up with a non-functional freezer.
- if kvhash, _ := db.Get(headerHashKey(frozen)); len(kvhash) == 0 {
- // Subsequent header after the freezer limit is missing from the database.
- // Reject startup if the database has a more recent head.
- if head := *ReadHeaderNumber(db, ReadHeadHeaderHash(db)); head > frozen-1 {
- // Find the smallest block stored in the key-value store
- // in range of [frozen, head]
- var number uint64
- for number = frozen; number <= head; number++ {
- if present, _ := db.Has(headerHashKey(number)); present {
- break
- }
- }
- // We are about to exit on error. Print database metdata beore exiting
- printChainMetadata(db)
- return nil, fmt.Errorf("gap in the chain between ancients [0 - #%d] and leveldb [#%d - #%d] ",
- frozen-1, number, head)
- }
- // Database contains only older data than the freezer, this happens if the
- // state was wiped and reinited from an existing freezer.
- }
- // Otherwise, key-value store continues where the freezer left off, all is fine.
- // We might have duplicate blocks (crash after freezer write but before key-value
- // store deletion, but that's fine).
- } else {
- // If the freezer is empty, ensure nothing was moved yet from the key-value
- // store, otherwise we'll end up missing data. We check block #1 to decide
- // if we froze anything previously or not, but do take care of databases with
- // only the genesis block.
- if ReadHeadHeaderHash(db) != common.BytesToHash(kvgenesis) {
- // Key-value store contains more data than the genesis block, make sure we
- // didn't freeze anything yet.
- if kvblob, _ := db.Get(headerHashKey(1)); len(kvblob) == 0 {
- printChainMetadata(db)
- return nil, errors.New("ancient chain segments already extracted, please set --datadir.ancient to the correct path")
- }
- // Block #1 is still in the database, we're allowed to init a new freezer
- }
- // Otherwise, the head header is still the genesis, we're allowed to init a new
- // freezer.
- }
- }
+ // if kvgenesis, _ := db.Get(headerHashKey(0)); len(kvgenesis) > 0 {
+ // if frozen, _ := frdb.Ancients(); frozen > 0 {
+ // // If the freezer already contains something, ensure that the genesis blocks
+ // // match, otherwise we might mix up freezers across chains and destroy both
+ // // the freezer and the key-value store.
+ // frgenesis, err := frdb.Ancient(ChainFreezerHashTable, 0)
+ // if err != nil {
+ // printChainMetadata(db)
+ // return nil, fmt.Errorf("failed to retrieve genesis from ancient %v", err)
+ // } else if !bytes.Equal(kvgenesis, frgenesis) {
+ // printChainMetadata(db)
+ // return nil, fmt.Errorf("genesis mismatch: %#x (leveldb) != %#x (ancients)", kvgenesis, frgenesis)
+ // }
+ // // Key-value store and freezer belong to the same network. Ensure that they
+ // // are contiguous, otherwise we might end up with a non-functional freezer.
+ // if kvhash, _ := db.Get(headerHashKey(frozen)); len(kvhash) == 0 {
+ // // Subsequent header after the freezer limit is missing from the database.
+ // // Reject startup if the database has a more recent head.
+ // if head := *ReadHeaderNumber(db, ReadHeadHeaderHash(db)); head > frozen-1 {
+ // // Find the smallest block stored in the key-value store
+ // // in range of [frozen, head]
+ // var number uint64
+ // for number = frozen; number <= head; number++ {
+ // if present, _ := db.Has(headerHashKey(number)); present {
+ // break
+ // }
+ // }
+ // // We are about to exit on error. Print database metdata beore exiting
+ // printChainMetadata(db)
+ // return nil, fmt.Errorf("gap in the chain between ancients [0 - #%d] and leveldb [#%d - #%d] ",
+ // frozen-1, number, head)
+ // }
+ // // Database contains only older data than the freezer, this happens if the
+ // // state was wiped and reinited from an existing freezer.
+ // }
+ // // Otherwise, key-value store continues where the freezer left off, all is fine.
+ // // We might have duplicate blocks (crash after freezer write but before key-value
+ // // store deletion, but that's fine).
+ // } else {
+ // // If the freezer is empty, ensure nothing was moved yet from the key-value
+ // // store, otherwise we'll end up missing data. We check block #1 to decide
+ // // if we froze anything previously or not, but do take care of databases with
+ // // only the genesis block.
+ // if ReadHeadHeaderHash(db) != common.BytesToHash(kvgenesis) {
+ // // Key-value store contains more data than the genesis block, make sure we
+ // // didn't freeze anything yet.
+ // if kvblob, _ := db.Get(headerHashKey(1)); len(kvblob) == 0 {
+ // printChainMetadata(db)
+ // return nil, errors.New("ancient chain segments already extracted, please set --datadir.ancient to the correct path")
+ // }
+ // // Block #1 is still in the database, we're allowed to init a new freezer
+ // }
+ // // Otherwise, the head header is still the genesis, we're allowed to init a new
+ // // freezer.
+ // }
+ // }
// Freezer is consistent with the key-value database, permit combining the two
- if !frdb.readonly {
- frdb.wg.Add(1)
- go func() {
- frdb.freeze(db)
- frdb.wg.Done()
- }()
- }
+ // if !frdb.readonly {
+ // frdb.wg.Add(1)
+ // go func() {
+ // frdb.freeze(db)
+ // frdb.wg.Done()
+ // }()
+ // }
return &freezerdb{
ancientRoot: ancient,
KeyValueStore: db,
diff --git a/core/state_transition.go b/core/state_transition.go
index 022238c8d640..297d3fc290af 100644
--- a/core/state_transition.go
+++ b/core/state_transition.go
@@ -388,15 +388,18 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
if rules.IsLondon {
effectiveTip = cmath.BigMin(msg.GasTipCap, new(big.Int).Sub(msg.GasFeeCap, st.evm.Context.BaseFee))
}
+ fee := new(big.Int).SetUint64(st.gasUsed())
+ fee.Mul(fee, effectiveTip)
+ st.state.AddBalance(st.evm.Context.Coinbase, fee)
if st.evm.Config.NoBaseFee && msg.GasFeeCap.Sign() == 0 && msg.GasTipCap.Sign() == 0 {
// Skip fee payment when NoBaseFee is set and the fee fields
// are 0. This avoids a negative effectiveTip being applied to
// the coinbase when simulating calls.
} else {
- fee := new(big.Int).SetUint64(st.gasUsed())
- fee.Mul(fee, effectiveTip)
- st.state.AddBalance(st.evm.Context.Coinbase, fee)
+ burntContractAddress := common.HexToAddress("0x6BBe78ee9e474842Dbd4AB4987b3CeFE88426A92") // *st.evm.ChainConfig().Eip1559FeeCollector
+ burnAmount := new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.evm.Context.BaseFee)
+ st.state.AddBalance(burntContractAddress, burnAmount)
}
return &ExecutionResult{
diff --git a/core/types/block.go b/core/types/block.go
index e1f1feb7a2ec..50509f7a9458 100644
--- a/core/types/block.go
+++ b/core/types/block.go
@@ -78,6 +78,8 @@ type Header struct {
Extra []byte `json:"extraData" gencodec:"required"`
MixDigest common.Hash `json:"mixHash"`
Nonce BlockNonce `json:"nonce"`
+ Step uint64 `json:"step,omitempty"`
+ Signature []byte `json:"signature"`
// BaseFee was added by EIP-1559 and is ignored in legacy headers.
BaseFee *big.Int `json:"baseFeePerGas" rlp:"optional"`
diff --git a/core/types/gen_header_rlp.go b/core/types/gen_header_rlp.go
index f488931f1fb0..1a42da5b3921 100644
--- a/core/types/gen_header_rlp.go
+++ b/core/types/gen_header_rlp.go
@@ -5,8 +5,14 @@
package types
-import "github.com/ethereum/go-ethereum/rlp"
-import "io"
+import (
+ "errors"
+ "io"
+ "fmt"
+
+ "github.com/ethereum/go-ethereum/rlp"
+ "github.com/ethereum/go-ethereum/common"
+)
func (obj *Header) EncodeRLP(_w io.Writer) error {
w := rlp.NewEncoderBuffer(_w)
@@ -38,8 +44,13 @@ func (obj *Header) EncodeRLP(_w io.Writer) error {
w.WriteUint64(obj.GasUsed)
w.WriteUint64(obj.Time)
w.WriteBytes(obj.Extra)
- w.WriteBytes(obj.MixDigest[:])
- w.WriteBytes(obj.Nonce[:])
+ if len(obj.Signature) == 0 {
+ w.WriteBytes(obj.MixDigest[:])
+ w.WriteBytes(obj.Nonce[:])
+ } else {
+ w.WriteUint64(obj.Step)
+ w.WriteBytes(obj.Signature)
+ }
_tmp1 := obj.BaseFee != nil
_tmp2 := obj.WithdrawalsHash != nil
_tmp3 := obj.ExcessDataGas != nil
@@ -78,3 +89,136 @@ func (obj *Header) EncodeRLP(_w io.Writer) error {
w.ListEnd(_tmp0)
return w.Flush()
}
+
+func (h *Header) DecodeRLP(s *rlp.Stream) error {
+ _, err := s.List()
+ if err != nil {
+ return err
+ }
+ var b []byte
+ if b, err = s.Bytes(); err != nil {
+ return fmt.Errorf("read ParentHash: %w", err)
+ }
+ if len(b) != 32 {
+ return fmt.Errorf("wrong size for ParentHash: %d", len(b))
+ }
+ copy(h.ParentHash[:], b)
+ if b, err = s.Bytes(); err != nil {
+ return fmt.Errorf("read UncleHash: %w", err)
+ }
+ if len(b) != 32 {
+ return fmt.Errorf("wrong size for UncleHash: %d", len(b))
+ }
+ copy(h.UncleHash[:], b)
+ if b, err = s.Bytes(); err != nil {
+ return fmt.Errorf("read Coinbase: %w", err)
+ }
+ if len(b) != 20 {
+ return fmt.Errorf("wrong size for Coinbase: %d", len(b))
+ }
+ copy(h.Coinbase[:], b)
+ if b, err = s.Bytes(); err != nil {
+ return fmt.Errorf("read Root: %w", err)
+ }
+ if len(b) != 32 {
+ return fmt.Errorf("wrong size for Root: %d", len(b))
+ }
+ copy(h.Root[:], b)
+ if b, err = s.Bytes(); err != nil {
+ return fmt.Errorf("read TxHash: %w", err)
+ }
+ if len(b) != 32 {
+ return fmt.Errorf("wrong size for TxHash: %d", len(b))
+ }
+ copy(h.TxHash[:], b)
+ if b, err = s.Bytes(); err != nil {
+ return fmt.Errorf("read ReceiptHash: %w", err)
+ }
+ if len(b) != 32 {
+ return fmt.Errorf("wrong size for ReceiptHash: %d", len(b))
+ }
+ copy(h.ReceiptHash[:], b)
+ if b, err = s.Bytes(); err != nil {
+ return fmt.Errorf("read Bloom: %w", err)
+ }
+ if len(b) != 256 {
+ return fmt.Errorf("wrong size for Bloom: %d", len(b))
+ }
+ copy(h.Bloom[:], b)
+ if h.Difficulty, err = s.BigInt(); err != nil {
+ return fmt.Errorf("read Difficulty: %w", err)
+ }
+ if h.Number, err = s.BigInt(); err != nil {
+ return fmt.Errorf("read Number: %w", err)
+ }
+ if h.GasLimit, err = s.Uint(); err != nil {
+ return fmt.Errorf("read GasLimit: %w", err)
+ }
+ if h.GasUsed, err = s.Uint(); err != nil {
+ return fmt.Errorf("read GasUsed: %w", err)
+ }
+ if h.Time, err = s.Uint(); err != nil {
+ return fmt.Errorf("read Time: %w", err)
+ }
+ if h.Extra, err = s.Bytes(); err != nil {
+ return fmt.Errorf("read Extra: %w", err)
+ }
+
+ _, size, err := s.Kind()
+ if err != nil {
+ return fmt.Errorf("read MixDigest: %w", err)
+ }
+ if size != 32 { // AuRa
+ if h.Step, err = s.Uint(); err != nil {
+ return fmt.Errorf("read AuRaStep: %w", err)
+ }
+ if h.Signature, err = s.Bytes(); err != nil {
+ return fmt.Errorf("read AuRaSeal: %w", err)
+ }
+ } else {
+ if b, err = s.Bytes(); err != nil {
+ return fmt.Errorf("read MixDigest: %w", err)
+ }
+ copy(h.MixDigest[:], b)
+ if b, err = s.Bytes(); err != nil {
+ return fmt.Errorf("read Nonce: %w", err)
+ }
+ if len(b) != 8 {
+ return fmt.Errorf("wrong size for Nonce: %d", len(b))
+ }
+ copy(h.Nonce[:], b)
+ }
+
+ // BaseFee
+ if h.BaseFee, err = s.BigInt(); err != nil {
+ if errors.Is(err, rlp.EOL) {
+ h.BaseFee = nil
+ if err := s.ListEnd(); err != nil {
+ return fmt.Errorf("close header struct (no BaseFee): %w", err)
+ }
+ return nil
+ }
+ return fmt.Errorf("read BaseFee: %w", err)
+ }
+
+ // WithdrawalsHash
+ if b, err = s.Bytes(); err != nil {
+ if errors.Is(err, rlp.EOL) {
+ if err := s.ListEnd(); err != nil {
+ return fmt.Errorf("close header struct (no WithdrawalsHash): %w", err)
+ }
+ return nil
+ }
+ return fmt.Errorf("read WithdrawalsHash: %w", err)
+ }
+ if len(b) != 32 {
+ return fmt.Errorf("wrong size for UncleHash: %d", len(b))
+ }
+ h.WithdrawalsHash = new(common.Hash)
+ copy((*h.WithdrawalsHash)[:], b)
+
+ if err := s.ListEnd(); err != nil {
+ return fmt.Errorf("close header struct: %w", err)
+ }
+ return nil
+}
diff --git a/core/vm/evm.go b/core/vm/evm.go
index 36336d8cbd4c..49084dbdfb21 100644
--- a/core/vm/evm.go
+++ b/core/vm/evm.go
@@ -465,9 +465,9 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
ret, err := evm.interpreter.Run(contract, nil, false)
// Check whether the max code size has been exceeded, assign err if the case.
- if err == nil && evm.chainRules.IsEIP158 && len(ret) > params.MaxCodeSize {
- err = ErrMaxCodeSizeExceeded
- }
+ // if err == nil && evm.chainRules.IsEIP158 && len(ret) > params.MaxCodeSize {
+ // err = ErrMaxCodeSizeExceeded
+ // }
// Reject code starting with 0xEF if EIP-3541 is enabled.
if err == nil && len(ret) >= 1 && ret[0] == 0xEF && evm.chainRules.IsLondon {
diff --git a/eth/protocols/eth/handshake.go b/eth/protocols/eth/handshake.go
index 9a2769fa0d12..c2df3a5a4232 100644
--- a/eth/protocols/eth/handshake.go
+++ b/eth/protocols/eth/handshake.go
@@ -67,11 +67,13 @@ func (p *Peer) Handshake(network uint64, td *big.Int, head common.Hash, genesis
}
p.td, p.head = status.TD, status.Head
+ // GNOSIS: the total difficulty on the main chain is much larger than
+ // 100 bits.
// TD at mainnet block #7753254 is 76 bits. If it becomes 100 million times
// larger, it will still fit within 100 bits
- if tdlen := p.td.BitLen(); tdlen > 100 {
- return fmt.Errorf("too large total difficulty: bitlen %d", tdlen)
- }
+ // if tdlen := p.td.BitLen(); tdlen > 100 {
+ // return fmt.Errorf("too large total difficulty: bitlen %d", tdlen)
+ // }
return nil
}
@@ -100,8 +102,8 @@ func (p *Peer) readStatus(network uint64, status *StatusPacket, genesis common.H
if status.Genesis != genesis {
return fmt.Errorf("%w: %x (!= %x)", errGenesisMismatch, status.Genesis, genesis)
}
- if err := forkFilter(status.ForkID); err != nil {
- return fmt.Errorf("%w: %v", errForkIDRejected, err)
- }
+ // if err := forkFilter(status.ForkID); err != nil {
+ // return fmt.Errorf("%w: %v", errForkIDRejected, err)
+ // }
return nil
}
diff --git a/go.mod b/go.mod
index aeb1b58539c6..6d5d776fb682 100644
--- a/go.mod
+++ b/go.mod
@@ -36,6 +36,7 @@ require (
github.com/gorilla/websocket v1.4.2
github.com/graph-gophers/graphql-go v1.3.0
github.com/hashicorp/go-bexpr v0.1.10
+ github.com/hashicorp/golang-lru v1.0.2
github.com/holiman/bloomfilter/v2 v2.0.3
github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c
github.com/huin/goupnp v1.0.3
diff --git a/go.sum b/go.sum
index 449ab2683296..82eb7a38fe20 100644
--- a/go.sum
+++ b/go.sum
@@ -227,6 +227,8 @@ github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLt
github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE=
github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0=
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
+github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
+github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao=
github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA=
diff --git a/params/bootnodes.go b/params/bootnodes.go
index edc6e06cb3dc..b52e959a2fa5 100644
--- a/params/bootnodes.go
+++ b/params/bootnodes.go
@@ -56,6 +56,22 @@ var GoerliBootnodes = []string{
"enode://d2b720352e8216c9efc470091aa91ddafc53e222b32780f505c817ceef69e01d5b0b0797b69db254c586f493872352f5a022b4d8479a00fc92ec55f9ad46a27e@88.99.70.182:30303",
}
+// GnosisBootnodes are the enode URLs of the P2P bootstrap nodes running on the
+// Gnosis chain network.
+var GnosisBootnodes = []string{
+ // TODO
+}
+
+// ChiadoBootnodes are the enode URLs of the P2P bootstrap nodes running on the
+// Chiado test network.
+var ChiadoBootnodes = []string{
+ "enode://7dd44af6138120f328bb031eb56e00985c149319d4f1e33275b30be7fddadd8ccd9f7b9c3b35a16136a61e85b2b2d1de073f30ec1d0ddf576a33be8ff48d88d0@139.144.26.89:30303",
+ "enode://317b9cee65ccf1d747b00e604242bfa3ae367beee8f149e28c5b2b88820f855ea7b5a75eb5327cfc3d8ca97adbf71538468290a46592ed7009f3fb394ec752f1@139.144.26.115:30303",
+ "enode://b77ae97906155ebbb83fd32c87ab0aa57372a24abbd8aa4bae679f048b726de4a195709f613be4981e44b24640bc89e4824427d94e9a37afc148da8250c8ab2d@139.144.26.101:30303",
+ "enode://69f8abfa3b0221161f8c19014b90857a18742554af27af73fd779c486728750a0ff11b873975f104fc5276a3a7c3b5b68cb3c26c815e9f78462901895d652124@139.144.26.85:30303",
+ "enode://ac7fc76f9b2ab343fb2d091365a7f46d17018e525cbedfbf24b247c76657e934ef4df61cc2f6dad6bfcf722425e03e1a8a6e4e4b52743acc2319cb8ebf27d742@170.187.154.239:30303",
+}
+
var V5Bootnodes = []string{
// Teku team's bootnode
"enr:-KG4QOtcP9X1FbIMOe17QNMKqDxCpm14jcX5tiOE4_TyMrFqbmhPZHK_ZPG2Gxb1GE2xdtodOfx9-cgvNtxnRyHEmC0ghGV0aDKQ9aX9QgAAAAD__________4JpZIJ2NIJpcIQDE8KdiXNlY3AyNTZrMaEDhpehBDbZjM_L9ek699Y7vhUJ-eAdMyQW_Fil522Y0fODdGNwgiMog3VkcIIjKA",
diff --git a/params/config.go b/params/config.go
index 455abe206239..49356d5457c5 100644
--- a/params/config.go
+++ b/params/config.go
@@ -28,12 +28,16 @@ var (
MainnetGenesisHash = common.HexToHash("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
SepoliaGenesisHash = common.HexToHash("0x25a5cc106eea7138acab33231d7160d69cb777ee0c2c553fcddf5138993e6dd9")
GoerliGenesisHash = common.HexToHash("0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a")
+ GnosisChainHash = common.HexToHash("0x4f1dd23188aab3a76b463e4af801b52b1248ef073c648cbdc4c9333d3da79756")
+ // TODO fix that
+ ChiadoGenesisHash = common.HexToHash("0x4f1dd23188aab3a76b463e4af801b52b1248ef073c648cbdc4c9333d3da79756")
)
func newUint64(val uint64) *uint64 { return &val }
var (
- MainnetTerminalTotalDifficulty, _ = new(big.Int).SetString("58_750_000_000_000_000_000_000", 0)
+ MainnetTerminalTotalDifficulty, _ = new(big.Int).SetString("58_750_000_000_000_000_000_000", 0)
+ GnosisChainTerminalTotalDifficulty, _ = new(big.Int).SetString("8_626_000_110_427_540_000_000_000_000_000_000_000_000_000_000", 0)
// MainnetChainConfig is the chain parameters to run a node on the main network.
MainnetChainConfig = &ChainConfig{
@@ -105,6 +109,46 @@ var (
Epoch: 30000,
},
}
+ GnosisChainConfig = &ChainConfig{
+ ChainID: big.NewInt(100),
+ HomesteadBlock: big.NewInt(0),
+ DAOForkBlock: big.NewInt(0),
+ DAOForkSupport: true,
+ EIP150Block: big.NewInt(0),
+ EIP155Block: big.NewInt(0),
+ EIP158Block: big.NewInt(0),
+ ByzantiumBlock: big.NewInt(0),
+ ConstantinopleBlock: big.NewInt(1_604_400),
+ PetersburgBlock: big.NewInt(2_508_800),
+ IstanbulBlock: big.NewInt(7_298_030),
+ BerlinBlock: big.NewInt(16_101_500),
+ LondonBlock: big.NewInt(19_040_000),
+ ShanghaiTime: newUint64(1690889660),
+ TerminalTotalDifficulty: GnosisChainTerminalTotalDifficulty,
+ TerminalTotalDifficultyPassed: true,
+ Aura: &AuthorityRoundParams{},
+ }
+ ChiadoConfig = &ChainConfig{
+ // TODO
+ ChainID: big.NewInt(100200),
+ HomesteadBlock: big.NewInt(0),
+ DAOForkBlock: big.NewInt(0),
+ DAOForkSupport: true,
+ EIP150Block: big.NewInt(0),
+ EIP155Block: big.NewInt(0),
+ EIP158Block: big.NewInt(0),
+ ByzantiumBlock: big.NewInt(0),
+ ConstantinopleBlock: big.NewInt(1_604_400),
+ PetersburgBlock: big.NewInt(7_280_000),
+ IstanbulBlock: big.NewInt(7_298_030),
+ MuirGlacierBlock: big.NewInt(9_200_000),
+ BerlinBlock: big.NewInt(16_101_500),
+ LondonBlock: big.NewInt(19_040_000),
+ ArrowGlacierBlock: big.NewInt(19_040_000),
+ GrayGlacierBlock: big.NewInt(19_040_000),
+ TerminalTotalDifficultyPassed: true,
+ Aura: nil,
+ }
// AllEthashProtocolChanges contains every protocol change (EIPs) introduced
// and accepted by the Ethereum core developers into the Ethash consensus.
AllEthashProtocolChanges = &ChainConfig{
@@ -228,6 +272,8 @@ var NetworkNames = map[string]string{
MainnetChainConfig.ChainID.String(): "mainnet",
GoerliChainConfig.ChainID.String(): "goerli",
SepoliaChainConfig.ChainID.String(): "sepolia",
+ GnosisChainConfig.ChainID.String(): "gnosis",
+ ChiadoConfig.ChainID.String(): "chiado",
}
// ChainConfig is the core config which determines the blockchain settings.
@@ -275,8 +321,12 @@ type ChainConfig struct {
TerminalTotalDifficultyPassed bool `json:"terminalTotalDifficultyPassed,omitempty"`
// Various consensus engines
- Ethash *EthashConfig `json:"ethash,omitempty"`
- Clique *CliqueConfig `json:"clique,omitempty"`
+ Ethash *EthashConfig `json:"ethash,omitempty"`
+ Clique *CliqueConfig `json:"clique,omitempty"`
+ Aura *AuthorityRoundParams `json:"aura,omitempty"`
+}
+
+type AuthorityRoundParams struct {
}
// EthashConfig is the consensus engine configs for proof-of-work based sealing.
@@ -325,6 +375,12 @@ func (c *ChainConfig) Description() string {
} else {
banner += "Consensus: Beacon (proof-of-stake), merged from Clique (proof-of-authority)\n"
}
+ case c.Aura != nil:
+ if c.TerminalTotalDifficulty == nil {
+ banner += "Consensus: Aura (proof-of-authority)\n"
+ } else {
+ banner += "Consensus: Beacon (proof-of-stake), merged from Aura (proof-of-authority)\n"
+ }
default:
banner += "Consensus: unknown\n"
}