// Copyright 2016 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 params import ( "embed" "encoding/json" "fmt" "math/big" "path" "sort" "strconv" "github.com/ledgerwatch/erigon/common" "github.com/ledgerwatch/erigon/common/paths" "github.com/ledgerwatch/erigon/params/networkname" ) //go:embed chainspecs var chainspecs embed.FS func readChainSpec(filename string) *ChainConfig { f, err := chainspecs.Open(filename) if err != nil { panic(fmt.Sprintf("Could not open chainspec for %s: %v", filename, err)) } defer f.Close() decoder := json.NewDecoder(f) spec := &ChainConfig{} err = decoder.Decode(&spec) if err != nil { panic(fmt.Sprintf("Could not parse chainspec for %s: %v", filename, err)) } return spec } type ConsensusType string const ( AuRaConsensus ConsensusType = "aura" EtHashConsensus ConsensusType = "ethash" CliqueConsensus ConsensusType = "clique" ParliaConsensus ConsensusType = "parlia" BorConsensus ConsensusType = "bor" ) // Genesis hashes to enforce below configs on. var ( MainnetGenesisHash = common.HexToHash("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3") SepoliaGenesisHash = common.HexToHash("0x25a5cc106eea7138acab33231d7160d69cb777ee0c2c553fcddf5138993e6dd9") RopstenGenesisHash = common.HexToHash("0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d") RinkebyGenesisHash = common.HexToHash("0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177") GoerliGenesisHash = common.HexToHash("0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a") SokolGenesisHash = common.HexToHash("0x5b28c1bfd3a15230c9a46b399cd0f9a6920d432e85381cc6a140b06e8410112f") FermionGenesisHash = common.HexToHash("0x0658360d8680ead416900a552b67b84e6d575c7f0ecab3dbe42406f9f8c34c35") BSCGenesisHash = common.HexToHash("0x0d21840abff46b96c84b2ac9e10e4f5cdaeb5693cb665db62a2f3b02d2d57b5b") ChapelGenesisHash = common.HexToHash("0x6d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34") RialtoGenesisHash = common.HexToHash("0xee835a629f9cf5510b48b6ba41d69e0ff7d6ef10f977166ef939db41f59f5501") MumbaiGenesisHash = common.HexToHash("0x7b66506a9ebdbf30d32b43c5f15a3b1216269a1ec3a75aa3182b86176a2b1ca7") BorMainnetGenesisHash = common.HexToHash("0xa9c28ce2141b56c474f1dc504bee9b01eb1bd7d1a507580d5519d4437a97de1b") BorDevnetGenesisHash = common.HexToHash("0x5a06b25b0c6530708ea0b98a3409290e39dce6be7f558493aeb6e4b99a172a87") GnosisGenesisHash = common.HexToHash("0x4f1dd23188aab3a76b463e4af801b52b1248ef073c648cbdc4c9333d3da79756") ) var ( SokolGenesisEpochProof = common.FromHex("0xf91a8c80b91a87f91a84f9020da00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0fad4af258fd11939fae0c6c6eec9d340b1caac0b0196fd9a1bc3f489c5bf00b3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200008083663be080808080b8410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f91871b914c26060604052600436106100fc576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806303aca79214610101578063108552691461016457806340a141ff1461019d57806340c9cdeb146101d65780634110a489146101ff57806345199e0a1461025757806349285b58146102c15780634d238c8e14610316578063752862111461034f578063900eb5a8146103645780639a573786146103c7578063a26a47d21461041c578063ae4b1b5b14610449578063b3f05b971461049e578063b7ab4db5146104cb578063d3e848f114610535578063fa81b2001461058a578063facd743b146105df575b600080fd5b341561010c57600080fd5b6101226004808035906020019091905050610630565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561016f57600080fd5b61019b600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061066f565b005b34156101a857600080fd5b6101d4600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610807565b005b34156101e157600080fd5b6101e9610bb7565b6040518082815260200191505060405180910390f35b341561020a57600080fd5b610236600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610bbd565b60405180831515151581526020018281526020019250505060405180910390f35b341561026257600080fd5b61026a610bee565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156102ad578082015181840152602081019050610292565b505050509050019250505060405180910390f35b34156102cc57600080fd5b6102d4610c82565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561032157600080fd5b61034d600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610d32565b005b341561035a57600080fd5b610362610fcc565b005b341561036f57600080fd5b61038560048080359060200190919050506110fc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156103d257600080fd5b6103da61113b565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561042757600080fd5b61042f6111eb565b604051808215151515815260200191505060405180910390f35b341561045457600080fd5b61045c6111fe565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156104a957600080fd5b6104b1611224565b604051808215151515815260200191505060405180910390f35b34156104d657600080fd5b6104de611237565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610521578082015181840152602081019050610506565b505050509050019250505060405180910390f35b341561054057600080fd5b6105486112cb565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561059557600080fd5b61059d6112f1565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156105ea57600080fd5b610616600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611317565b604051808215151515815260200191505060405180910390f35b60078181548110151561063f57fe5b90600052602060002090016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156106cb57600080fd5b600460019054906101000a900460ff161515156106e757600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415151561072357600080fd5b80600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600460016101000a81548160ff0219169083151502179055507f600bcf04a13e752d1e3670a5a9f1c21177ca2a93c6f5391d4f1298d098097c22600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b600080600061081461113b565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561084d57600080fd5b83600960008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff1615156108a957600080fd5b600960008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101549350600160078054905003925060078381548110151561090857fe5b906000526020600020900160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691508160078581548110151561094657fe5b906000526020600020900160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555083600960008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055506007838154811015156109e557fe5b906000526020600020900160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556000600780549050111515610a2757600080fd5b6007805480919060019003610a3c9190611370565b506000600960008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055506000600960008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548160ff0219169083151502179055506000600460006101000a81548160ff0219169083151502179055506001430340600019167f55252fa6eee4741b4e24a74a70e9c11fd2c2281df8d6ea13126ff845f7825c89600760405180806020018281038252838181548152602001915080548015610ba257602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610b58575b50509250505060405180910390a25050505050565b60085481565b60096020528060005260406000206000915090508060000160009054906101000a900460ff16908060010154905082565b610bf661139c565b6007805480602002602001604051908101604052809291908181526020018280548015610c7857602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610c2e575b5050505050905090565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166349285b586000604051602001526040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b1515610d1257600080fd5b6102c65a03f11515610d2357600080fd5b50505060405180519050905090565b610d3a61113b565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610d7357600080fd5b80600960008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff16151515610dd057600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151515610e0c57600080fd5b6040805190810160405280600115158152602001600780549050815250600960008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015590505060078054806001018281610ea991906113b0565b9160005260206000209001600084909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550506000600460006101000a81548160ff0219169083151502179055506001430340600019167f55252fa6eee4741b4e24a74a70e9c11fd2c2281df8d6ea13126ff845f7825c89600760405180806020018281038252838181548152602001915080548015610fba57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610f70575b50509250505060405180910390a25050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480156110365750600460009054906101000a900460ff16155b151561104157600080fd5b6001600460006101000a81548160ff0219169083151502179055506007600690805461106e9291906113dc565b506006805490506008819055507f8564cd629b15f47dc310d45bcbfc9bcf5420b0d51bf0659a16c67f91d27632536110a4611237565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156110e75780820151818401526020810190506110cc565b505050509050019250505060405180910390a1565b60068181548110151561110b57fe5b90600052602060002090016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639a5737866000604051602001526040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15156111cb57600080fd5b6102c65a03f115156111dc57600080fd5b50505060405180519050905090565b600460019054906101000a900460ff1681565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460009054906101000a900460ff1681565b61123f61139c565b60068054806020026020016040519081016040528092919081815260200182805480156112c157602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311611277575b5050505050905090565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600960008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff169050919050565b81548183558181151161139757818360005260206000209182019101611396919061142e565b5b505050565b602060405190810160405280600081525090565b8154818355818115116113d7578183600052602060002091820191016113d6919061142e565b5b505050565b82805482825590600052602060002090810192821561141d5760005260206000209182015b8281111561141c578254825591600101919060010190611401565b5b50905061142a9190611453565b5090565b61145091905b8082111561144c576000816000905550600101611434565b5090565b90565b61149391905b8082111561148f57600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905550600101611459565b5090565b905600a165627a7a7230582036ea35935c8246b68074adece2eab70c40e69a0193c08a6277ce06e5b25188510029b86bf869a033aa5d69545785694b808840be50c182dad2ec3636dfccbe6572fb69828742c0b846f8440101a0663ce0d171e545a26aa67e4ca66f72ba96bb48287dbcc03beea282867f80d44ba01f0e7726926cb43c03a0abf48197dba78522ec8ba1b158e2aa30da7d2a2c6f9eb8f3f8f1a08023c0d95fc2364e0bf7593f5ff32e1db8ef9f4b41c0bd474eae62d1af896e99808080a0b47b4f0b3e73b5edc8f9a9da1cbcfed562eb06bf54619b6aefeadebf5b3604c280a0da6ec08940a924cb08c947dd56cdb40076b29a6f0ea4dba4e2d02d9a9a72431b80a030cc4138c9e74b6cf79d624b4b5612c0fd888e91f55316cfee7d1694e1a90c0b80a0c5d54b915b56a888eee4e6eeb3141e778f9b674d1d322962eed900f02c29990aa017256b36ef47f907c6b1378a2636942ce894c17075e56fc054d4283f6846659e808080a03340bbaeafcda3a8672eb83099231dbbfab8dae02a1e8ec2f7180538fac207e080b838f7a03868bdfa8727775661e4ccf117824a175a33f8703d728c04488fbfffcafda9f99594e8ddc5c7a2d2f0d7a9798459c0104fdf5e987acab853f851808080a07bb75cabebdcbd1dbb4331054636d0c6d7a2b08483b9e04df057395a7434c9e080808080808080a0e61e567237b49c44d8f906ceea49027260b4010c10a547b38d8b131b9d3b6f848080808080b853f851808080a0a87d9bb950836582673aa0eecc0ff64aac607870637a2dd2012b8b1b31981f698080a08da6d5c36a404670c553a2c9052df7cd604f04e3863c4c7b9e0027bfd54206d680808080808080808080b86bf869a02080c7b7ae81a58eb98d9c78de4a1fd7fd9535fc953ed2be602daaa41767312ab846f8448080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470b8d3f8d1a0dc277c93a9f9dcee99aac9b8ba3cfa4c51821998522469c37715644e8fbac0bfa0ab8cdb808c8303bb61fb48e276217be9770fa83ecf3f90f2234d558885f5abf1808080a0fe137c3a474fbde41d89a59dd76da4c55bf696b86d3af64a55632f76cf30786780808080a06301b39b2ea8a44df8b0356120db64b788e71f52e1d7a6309d0d2e5b86fee7cb80a0da5d8b08dea0c5a4799c0f44d8a24d7cdf209f9b7a5588c1ecafb5361f6b9f07a01b7779e149cadf24d4ffb77ca7e11314b8db7097e4d70b2a173493153ca2e5a0808080a3e2a02052222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f0180") ) var ( SokolGenesisStateRoot = common.HexToHash("0xfad4af258fd11939fae0c6c6eec9d340b1caac0b0196fd9a1bc3f489c5bf00b3") FermionGenesisStateRoot = common.HexToHash("0x08982dc16236c51b6d9aff8b76cd0faa7067eb55eba62395d5a82649d8fb73c4") GnosisGenesisStateRoot = common.HexToHash("0x40cf4430ecaa733787d1a65154a3b9efb560c95d9e324a23b97f0609b539133b") ) var ( // MainnetChainConfig is the chain parameters to run a node on the main network. MainnetChainConfig = readChainSpec("chainspecs/mainnet.json") // SepoliaChainConfig contains the chain parameters to run a node on the Sepolia test network. SepoliaChainConfig = readChainSpec("chainspecs/sepolia.json") // RopstenChainConfig contains the chain parameters to run a node on the Ropsten test network. RopstenChainConfig = readChainSpec("chainspecs/ropsten.json") // RinkebyChainConfig contains the chain parameters to run a node on the Rinkeby test network. RinkebyChainConfig = readChainSpec("chainspecs/rinkeby.json") // GoerliChainConfig contains the chain parameters to run a node on the Görli test network. GoerliChainConfig = readChainSpec("chainspecs/goerli.json") BSCChainConfig = readChainSpec("chainspecs/bsc.json") ChapelChainConfig = readChainSpec("chainspecs/chapel.json") RialtoChainConfig = readChainSpec("chainspecs/rialto.json") SokolChainConfig = readChainSpec("chainspecs/sokol.json") FermionChainConfig = readChainSpec("chainspecs/fermion.json") // AllEthashProtocolChanges contains every protocol change (EIPs) introduced // and accepted by the Ethereum core developers into the Ethash consensus. AllEthashProtocolChanges = &ChainConfig{ ChainID: big.NewInt(1337), Consensus: EtHashConsensus, HomesteadBlock: big.NewInt(0), DAOForkBlock: nil, DAOForkSupport: false, TangerineWhistleBlock: big.NewInt(0), TangerineWhistleHash: common.Hash{}, SpuriousDragonBlock: big.NewInt(0), ByzantiumBlock: big.NewInt(0), ConstantinopleBlock: big.NewInt(0), PetersburgBlock: big.NewInt(0), IstanbulBlock: big.NewInt(0), MuirGlacierBlock: big.NewInt(0), BerlinBlock: big.NewInt(0), LondonBlock: nil, ArrowGlacierBlock: nil, Ethash: new(EthashConfig), Clique: nil, } // AllCliqueProtocolChanges contains every protocol change (EIPs) introduced // and accepted by the Ethereum core developers into the Clique consensus. AllCliqueProtocolChanges = &ChainConfig{ ChainID: big.NewInt(1337), Consensus: CliqueConsensus, HomesteadBlock: big.NewInt(0), DAOForkBlock: nil, DAOForkSupport: false, TangerineWhistleBlock: big.NewInt(0), TangerineWhistleHash: common.Hash{}, SpuriousDragonBlock: big.NewInt(0), ByzantiumBlock: big.NewInt(0), ConstantinopleBlock: big.NewInt(0), PetersburgBlock: big.NewInt(0), IstanbulBlock: big.NewInt(0), MuirGlacierBlock: big.NewInt(0), BerlinBlock: big.NewInt(0), LondonBlock: big.NewInt(0), ArrowGlacierBlock: nil, Ethash: nil, Clique: &CliqueConfig{Period: 0, Epoch: 30000}, } MumbaiChainConfig = readChainSpec("chainspecs/mumbai.json") BorMainnetChainConfig = readChainSpec("chainspecs/bor-mainnet.json") BorDevnetChainConfig = readChainSpec("chainspecs/bor-devnet.json") GnosisChainConfig = readChainSpec("chainspecs/gnosis.json") CliqueSnapshot = NewSnapshotConfig(10, 1024, 16384, true, "") TestChainConfig = &ChainConfig{ ChainID: big.NewInt(1), Consensus: EtHashConsensus, HomesteadBlock: big.NewInt(0), DAOForkBlock: nil, DAOForkSupport: false, TangerineWhistleBlock: big.NewInt(0), TangerineWhistleHash: common.Hash{}, SpuriousDragonBlock: big.NewInt(0), ByzantiumBlock: big.NewInt(0), ConstantinopleBlock: big.NewInt(0), PetersburgBlock: big.NewInt(0), IstanbulBlock: big.NewInt(0), MuirGlacierBlock: big.NewInt(0), BerlinBlock: big.NewInt(0), LondonBlock: nil, ArrowGlacierBlock: nil, Ethash: new(EthashConfig), Clique: nil, } TestChainAuraConfig = &ChainConfig{ ChainID: big.NewInt(1), Consensus: AuRaConsensus, HomesteadBlock: big.NewInt(0), DAOForkBlock: nil, DAOForkSupport: false, TangerineWhistleBlock: big.NewInt(0), TangerineWhistleHash: common.Hash{}, SpuriousDragonBlock: big.NewInt(0), ByzantiumBlock: big.NewInt(0), ConstantinopleBlock: big.NewInt(0), PetersburgBlock: big.NewInt(0), IstanbulBlock: big.NewInt(0), MuirGlacierBlock: big.NewInt(0), BerlinBlock: big.NewInt(0), LondonBlock: nil, ArrowGlacierBlock: nil, Aura: &AuRaConfig{}, } TestRules = TestChainConfig.Rules(0) ) // ChainConfig is the core config which determines the blockchain settings. // // ChainConfig is stored in the database on a per block basis. This means // that any network, identified by its genesis block, can have its own // set of configuration options. type ChainConfig struct { ChainName string ChainID *big.Int `json:"chainId"` // chainId identifies the current chain and is used for replay protection Consensus ConsensusType `json:"consensus,omitempty"` // aura, ethash or clique HomesteadBlock *big.Int `json:"homesteadBlock,omitempty"` // Homestead switch block (nil = no fork, 0 = already homestead) DAOForkBlock *big.Int `json:"daoForkBlock,omitempty"` // TheDAO hard-fork switch block (nil = no fork) DAOForkSupport bool `json:"daoForkSupport,omitempty"` // Whether the nodes supports or opposes the DAO hard-fork // Tangerine Whistle (EIP150) implements the Gas price changes (https://github.com/ethereum/EIPs/issues/150) TangerineWhistleBlock *big.Int `json:"eip150Block,omitempty"` // EIP150 HF block (nil = no fork) TangerineWhistleHash common.Hash `json:"eip150Hash,omitempty"` // EIP150 HF hash (needed for header only clients as only gas pricing changed) SpuriousDragonBlock *big.Int `json:"eip155Block,omitempty"` // Spurious Dragon HF block ByzantiumBlock *big.Int `json:"byzantiumBlock,omitempty"` // Byzantium switch block (nil = no fork, 0 = already on byzantium) ConstantinopleBlock *big.Int `json:"constantinopleBlock,omitempty"` // Constantinople switch block (nil = no fork, 0 = already activated) PetersburgBlock *big.Int `json:"petersburgBlock,omitempty"` // Petersburg switch block (nil = same as Constantinople) IstanbulBlock *big.Int `json:"istanbulBlock,omitempty"` // Istanbul switch block (nil = no fork, 0 = already on istanbul) MuirGlacierBlock *big.Int `json:"muirGlacierBlock,omitempty"` // EIP-2384 (bomb delay) switch block (nil = no fork, 0 = already activated) BerlinBlock *big.Int `json:"berlinBlock,omitempty"` // Berlin switch block (nil = no fork, 0 = already on berlin) LondonBlock *big.Int `json:"londonBlock,omitempty"` // London switch block (nil = no fork, 0 = already on london) ArrowGlacierBlock *big.Int `json:"arrowGlacierBlock,omitempty"` // EIP-4345 (bomb delay) switch block (nil = no fork, 0 = already activated) GrayGlacierBlock *big.Int `json:"grayGlacierBlock,omitempty"` // EIP-5133 (bomb delay) switch block (nil = no fork, 0 = already activated) // EIP-3675: Upgrade consensus to Proof-of-Stake TerminalTotalDifficulty *big.Int `json:"terminalTotalDifficulty,omitempty"` // The merge happens when terminal total difficulty is reached TerminalTotalDifficultyPassed bool `json:"terminalTotalDifficultyPassed,omitempty"` // Disable PoW sync for networks that have already passed through the Merge MergeNetsplitBlock *big.Int `json:"mergeNetsplitBlock,omitempty"` // Virtual fork after The Merge to use as a network splitter; see FORK_NEXT_VALUE in EIP-3675 ShanghaiBlock *big.Int `json:"shanghaiBlock,omitempty"` // Shanghai switch block (nil = no fork, 0 = already activated) CancunBlock *big.Int `json:"cancunBlock,omitempty"` // Cancun switch block (nil = no fork, 0 = already activated) // Parlia fork blocks RamanujanBlock *big.Int `json:"ramanujanBlock,omitempty" toml:",omitempty"` // ramanujanBlock switch block (nil = no fork, 0 = already activated) NielsBlock *big.Int `json:"nielsBlock,omitempty" toml:",omitempty"` // nielsBlock switch block (nil = no fork, 0 = already activated) MirrorSyncBlock *big.Int `json:"mirrorSyncBlock,omitempty" toml:",omitempty"` // mirrorSyncBlock switch block (nil = no fork, 0 = already activated) BrunoBlock *big.Int `json:"brunoBlock,omitempty" toml:",omitempty"` // brunoBlock switch block (nil = no fork, 0 = already activated) EulerBlock *big.Int `json:"eulerBlock,omitempty" toml:",omitempty"` // eulerBlock switch block (nil = no fork, 0 = already activated) GibbsBlock *big.Int `json:"gibbsBlock,omitempty" toml:",omitempty"` // gibbsBlock switch block (nil = no fork, 0 = already activated) NanoBlock *big.Int `json:"nanoBlock,omitempty" toml:",omitempty"` // nanoBlock switch block (nil = no fork, 0 = already activated) MoranBlock *big.Int `json:"moranBlock,omitempty" toml:",omitempty"` // moranBlock switch block (nil = no fork, 0 = already activated) // Gnosis Chain fork blocks PosdaoBlock *big.Int `json:"posdaoBlock,omitempty"` Eip1559FeeCollector *common.Address `json:"eip1559FeeCollector,omitempty"` // (Optional) Address where burnt EIP-1559 fees go to Eip1559FeeCollectorTransition *big.Int `json:"eip1559FeeCollectorTransition,omitempty"` // (Optional) Block from which burnt EIP-1559 fees go to the Eip1559FeeCollector // Various consensus engines Ethash *EthashConfig `json:"ethash,omitempty"` Clique *CliqueConfig `json:"clique,omitempty"` Aura *AuRaConfig `json:"aura,omitempty"` Parlia *ParliaConfig `json:"parlia,omitempty" toml:",omitempty"` Bor *BorConfig `json:"bor,omitempty"` } // EthashConfig is the consensus engine configs for proof-of-work based sealing. type EthashConfig struct{} // String implements the stringer interface, returning the consensus engine details. func (c *EthashConfig) String() string { return "ethash" } // CliqueConfig is the consensus engine configs for proof-of-authority based sealing. type CliqueConfig struct { Period uint64 `json:"period"` // Number of seconds between blocks to enforce Epoch uint64 `json:"epoch"` // Epoch length to reset votes and checkpoint } // String implements the stringer interface, returning the consensus engine details. func (c *CliqueConfig) String() string { return "clique" } // AuRaConfig is the consensus engine configs for proof-of-authority based sealing. type AuRaConfig struct { DBPath string InMemory bool Etherbase common.Address // same as miner etherbase } // String implements the stringer interface, returning the consensus engine details. func (c *AuRaConfig) String() string { return "aura" } type ParliaConfig struct { DBPath string InMemory bool Period uint64 `json:"period"` // Number of seconds between blocks to enforce Epoch uint64 `json:"epoch"` // Epoch length to update validatorSet } // String implements the stringer interface, returning the consensus engine details. func (b *ParliaConfig) String() string { return "parlia" } // BorConfig is the consensus engine configs for Matic bor based sealing. type BorConfig struct { Period map[string]uint64 `json:"period"` // Number of seconds between blocks to enforce ProducerDelay uint64 `json:"producerDelay"` // Number of seconds delay between two producer interval Sprint uint64 `json:"sprint"` // Epoch length to proposer BackupMultiplier map[string]uint64 `json:"backupMultiplier"` // Backup multiplier to determine the wiggle time ValidatorContract string `json:"validatorContract"` // Validator set contract StateReceiverContract string `json:"stateReceiverContract"` // State receiver contract OverrideStateSyncRecords map[string]int `json:"overrideStateSyncRecords"` // override state records count BlockAlloc map[string]interface{} `json:"blockAlloc"` JaipurBlock uint64 `json:"jaipurBlock"` // Jaipur switch block (nil = no fork, 0 = already on jaipur) } // String implements the stringer interface, returning the consensus engine details. func (b *BorConfig) String() string { return "bor" } func (c *BorConfig) CalculateBackupMultiplier(number uint64) uint64 { return c.calculateBorConfigHelper(c.BackupMultiplier, number) } func (c *BorConfig) CalculatePeriod(number uint64) uint64 { return c.calculateBorConfigHelper(c.Period, number) } func (c *BorConfig) IsJaipur(number uint64) bool { return number >= c.JaipurBlock } func (c *BorConfig) calculateBorConfigHelper(field map[string]uint64, number uint64) uint64 { keys := make([]string, 0, len(field)) for k := range field { keys = append(keys, k) } sort.Strings(keys) for i := 0; i < len(keys)-1; i++ { valUint, _ := strconv.ParseUint(keys[i], 10, 64) valUintNext, _ := strconv.ParseUint(keys[i+1], 10, 64) if number > valUint && number < valUintNext { return field[keys[i]] } } return field[keys[len(keys)-1]] } // String implements the fmt.Stringer interface. func (c *ChainConfig) String() string { var engine interface{} switch { case c.Ethash != nil: engine = c.Ethash case c.Clique != nil: engine = c.Clique case c.Parlia != nil: engine = c.Parlia case c.Bor != nil: engine = c.Bor case c.Aura != nil: engine = c.Aura default: engine = "unknown" } // TODO Covalent: Refactor to more generic approach and potentially introduce tag for "ecosystem" field (Ethereum, BSC, etc.) if c.Consensus == ParliaConsensus { return fmt.Sprintf("{ChainID: %v Ramanujan: %v, Niels: %v, MirrorSync: %v, Bruno: %v, Euler: %v, Gibbs: %v, Nano: %v, Moran: %v, Engine: %v}", c.ChainID, c.RamanujanBlock, c.NielsBlock, c.MirrorSyncBlock, c.BrunoBlock, c.EulerBlock, c.GibbsBlock, c.NanoBlock, c.MoranBlock, engine, ) } return fmt.Sprintf("{ChainID: %v, Homestead: %v, DAO: %v, DAO Support: %v, Tangerine Whistle: %v, Spurious Dragon: %v, Byzantium: %v, Constantinople: %v, Petersburg: %v, Istanbul: %v, Muir Glacier: %v, Berlin: %v, London: %v, Arrow Glacier: %v, Gray Glacier: %v, Terminal Total Difficulty: %v, Merge Netsplit: %v, Shanghai: %v, Cancun: %v, Engine: %v}", c.ChainID, c.HomesteadBlock, c.DAOForkBlock, c.DAOForkSupport, c.TangerineWhistleBlock, c.SpuriousDragonBlock, c.ByzantiumBlock, c.ConstantinopleBlock, c.PetersburgBlock, c.IstanbulBlock, c.MuirGlacierBlock, c.BerlinBlock, c.LondonBlock, c.ArrowGlacierBlock, c.GrayGlacierBlock, c.TerminalTotalDifficulty, c.MergeNetsplitBlock, c.ShanghaiBlock, c.CancunBlock, engine, ) } func (c *ChainConfig) IsHeaderWithSeal() bool { return c.Consensus == AuRaConsensus } type ConsensusSnapshotConfig struct { CheckpointInterval uint64 // Number of blocks after which to save the vote snapshot to the database InmemorySnapshots int // Number of recent vote snapshots to keep in memory InmemorySignatures int // Number of recent block signatures to keep in memory DBPath string InMemory bool } const cliquePath = "clique" func NewSnapshotConfig(checkpointInterval uint64, inmemorySnapshots int, inmemorySignatures int, inmemory bool, dbPath string) *ConsensusSnapshotConfig { if len(dbPath) == 0 { dbPath = paths.DefaultDataDir() } return &ConsensusSnapshotConfig{ checkpointInterval, inmemorySnapshots, inmemorySignatures, path.Join(dbPath, cliquePath), inmemory, } } // IsHomestead returns whether num is either equal to the homestead block or greater. func (c *ChainConfig) IsHomestead(num uint64) bool { return isForked(c.HomesteadBlock, num) } // IsDAOFork returns whether num is either equal to the DAO fork block or greater. func (c *ChainConfig) IsDAOFork(num uint64) bool { return isForked(c.DAOForkBlock, num) } // IsTangerineWhistle returns whether num is either equal to the Tangerine Whistle (EIP150) fork block or greater. func (c *ChainConfig) IsTangerineWhistle(num uint64) bool { return isForked(c.TangerineWhistleBlock, num) } // IsSpuriousDragon returns whether num is either equal to the Spurious Dragon fork block or greater. func (c *ChainConfig) IsSpuriousDragon(num uint64) bool { return isForked(c.SpuriousDragonBlock, num) } // IsByzantium returns whether num is either equal to the Byzantium fork block or greater. func (c *ChainConfig) IsByzantium(num uint64) bool { return isForked(c.ByzantiumBlock, num) } // IsConstantinople returns whether num is either equal to the Constantinople fork block or greater. func (c *ChainConfig) IsConstantinople(num uint64) bool { return isForked(c.ConstantinopleBlock, num) } // IsRamanujan returns whether num is either equal to the IsRamanujan fork block or greater. func (c *ChainConfig) IsRamanujan(num uint64) bool { return isForked(c.RamanujanBlock, num) } // IsOnRamanujan returns whether num is equal to the Ramanujan fork block func (c *ChainConfig) IsOnRamanujan(num *big.Int) bool { return configNumEqual(c.RamanujanBlock, num) } // IsNiels returns whether num is either equal to the Niels fork block or greater. func (c *ChainConfig) IsNiels(num uint64) bool { return isForked(c.NielsBlock, num) } // IsOnNiels returns whether num is equal to the IsNiels fork block func (c *ChainConfig) IsOnNiels(num *big.Int) bool { return configNumEqual(c.NielsBlock, num) } // IsMirrorSync returns whether num is either equal to the MirrorSync fork block or greater. func (c *ChainConfig) IsMirrorSync(num uint64) bool { return isForked(c.MirrorSyncBlock, num) } // IsOnMirrorSync returns whether num is equal to the MirrorSync fork block func (c *ChainConfig) IsOnMirrorSync(num *big.Int) bool { return configNumEqual(c.MirrorSyncBlock, num) } // IsBruno returns whether num is either equal to the Burn fork block or greater. func (c *ChainConfig) IsBruno(num uint64) bool { return isForked(c.BrunoBlock, num) } // IsOnBruno returns whether num is equal to the Burn fork block func (c *ChainConfig) IsOnBruno(num *big.Int) bool { return configNumEqual(c.BrunoBlock, num) } // IsEuler returns whether num is either equal to the euler fork block or greater. func (c *ChainConfig) IsEuler(num *big.Int) bool { return isForked(c.EulerBlock, num.Uint64()) } func (c *ChainConfig) IsOnEuler(num *big.Int) bool { return configNumEqual(c.EulerBlock, num) } // IsGibbs returns whether num is either equal to the euler fork block or greater. func (c *ChainConfig) IsGibbs(num *big.Int) bool { return isForked(c.GibbsBlock, num.Uint64()) } func (c *ChainConfig) IsOnGibbs(num *big.Int) bool { return configNumEqual(c.GibbsBlock, num) } func (c *ChainConfig) IsMoran(num uint64) bool { return isForked(c.MoranBlock, num) } func (c *ChainConfig) IsOnMoran(num *big.Int) bool { return configNumEqual(c.MoranBlock, num) } // IsNano returns whether num is either equal to the euler fork block or greater. func (c *ChainConfig) IsNano(num uint64) bool { return isForked(c.NanoBlock, num) } func (c *ChainConfig) IsOnNano(num *big.Int) bool { return configNumEqual(c.NanoBlock, num) } // IsMuirGlacier returns whether num is either equal to the Muir Glacier (EIP-2384) fork block or greater. func (c *ChainConfig) IsMuirGlacier(num uint64) bool { return isForked(c.MuirGlacierBlock, num) } // IsPetersburg returns whether num is either // - equal to or greater than the PetersburgBlock fork block, // - OR is nil, and Constantinople is active func (c *ChainConfig) IsPetersburg(num uint64) bool { return isForked(c.PetersburgBlock, num) || c.PetersburgBlock == nil && isForked(c.ConstantinopleBlock, num) } // IsIstanbul returns whether num is either equal to the Istanbul fork block or greater. func (c *ChainConfig) IsIstanbul(num uint64) bool { return isForked(c.IstanbulBlock, num) } // IsBerlin returns whether num is either equal to the Berlin fork block or greater. func (c *ChainConfig) IsBerlin(num uint64) bool { return isForked(c.BerlinBlock, num) } // IsLondon returns whether num is either equal to the London fork block or greater. func (c *ChainConfig) IsLondon(num uint64) bool { return isForked(c.LondonBlock, num) } // IsArrowGlacier returns whether num is either equal to the Arrow Glacier (EIP-4345) fork block or greater. func (c *ChainConfig) IsArrowGlacier(num uint64) bool { return isForked(c.ArrowGlacierBlock, num) } // IsGrayGlacier returns whether num is either equal to the Gray Glacier (EIP-5133) fork block or greater. func (c *ChainConfig) IsGrayGlacier(num uint64) bool { return isForked(c.GrayGlacierBlock, num) } // IsShanghai returns whether num is either equal to the Shanghai fork block or greater. func (c *ChainConfig) IsShanghai(num uint64) bool { return isForked(c.ShanghaiBlock, num) } // IsCancun returns whether num is either equal to the Cancun fork block or greater. func (c *ChainConfig) IsCancun(num uint64) bool { return isForked(c.CancunBlock, num) } func (c *ChainConfig) IsEip1559FeeCollector(num uint64) bool { return c.Eip1559FeeCollector != nil && isForked(c.Eip1559FeeCollectorTransition, num) } // CheckCompatible checks whether scheduled fork transitions have been imported // with a mismatching chain configuration. func (c *ChainConfig) CheckCompatible(newcfg *ChainConfig, height uint64) *ConfigCompatError { bhead := height // Iterate checkCompatible to find the lowest conflict. var lasterr *ConfigCompatError for { err := c.checkCompatible(newcfg, bhead) if err == nil || (lasterr != nil && err.RewindTo == lasterr.RewindTo) { break } lasterr = err bhead = err.RewindTo } return lasterr } // CheckConfigForkOrder checks that we don't "skip" any forks, geth isn't pluggable enough // to guarantee that forks can be implemented in a different order than on official networks func (c *ChainConfig) CheckConfigForkOrder() error { if c != nil && c.ChainID != nil && c.ChainID.Uint64() == 77 { return nil } type fork struct { name string block *big.Int optional bool // if true, the fork may be nil and next fork is still allowed } var lastFork fork for _, cur := range []fork{ {name: "homesteadBlock", block: c.HomesteadBlock}, {name: "daoForkBlock", block: c.DAOForkBlock, optional: true}, {name: "eip150Block", block: c.TangerineWhistleBlock}, {name: "eip155Block", block: c.SpuriousDragonBlock}, {name: "byzantiumBlock", block: c.ByzantiumBlock}, {name: "constantinopleBlock", block: c.ConstantinopleBlock}, {name: "petersburgBlock", block: c.PetersburgBlock}, {name: "istanbulBlock", block: c.IstanbulBlock}, {name: "muirGlacierBlock", block: c.MuirGlacierBlock, optional: true}, {name: "eulerBlock", block: c.EulerBlock, optional: true}, {name: "gibbsBlock", block: c.GibbsBlock, optional: true}, {name: "berlinBlock", block: c.BerlinBlock}, {name: "londonBlock", block: c.LondonBlock}, {name: "arrowGlacierBlock", block: c.ArrowGlacierBlock, optional: true}, {name: "grayGlacierBlock", block: c.GrayGlacierBlock, optional: true}, {name: "mergeNetsplitBlock", block: c.MergeNetsplitBlock, optional: true}, {name: "shanghaiBlock", block: c.ShanghaiBlock}, {name: "cancunBlock", block: c.CancunBlock}, } { if lastFork.name != "" { // Next one must be higher number if lastFork.block == nil && cur.block != nil { return fmt.Errorf("unsupported fork ordering: %v not enabled, but %v enabled at %v", lastFork.name, cur.name, cur.block) } if lastFork.block != nil && cur.block != nil { if lastFork.block.Cmp(cur.block) > 0 { return fmt.Errorf("unsupported fork ordering: %v enabled at %v, but %v enabled at %v", lastFork.name, lastFork.block, cur.name, cur.block) } } // If it was optional and not set, then ignore it } if !cur.optional || cur.block != nil { lastFork = cur } } return nil } func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, head uint64) *ConfigCompatError { // Ethereum mainnet forks if isForkIncompatible(c.HomesteadBlock, newcfg.HomesteadBlock, head) { return newCompatError("Homestead fork block", c.HomesteadBlock, newcfg.HomesteadBlock) } if isForkIncompatible(c.DAOForkBlock, newcfg.DAOForkBlock, head) { return newCompatError("DAO fork block", c.DAOForkBlock, newcfg.DAOForkBlock) } if c.IsDAOFork(head) && c.DAOForkSupport != newcfg.DAOForkSupport { return newCompatError("DAO fork support flag", c.DAOForkBlock, newcfg.DAOForkBlock) } if isForkIncompatible(c.TangerineWhistleBlock, newcfg.TangerineWhistleBlock, head) { return newCompatError("Tangerine Whistle fork block", c.TangerineWhistleBlock, newcfg.TangerineWhistleBlock) } if isForkIncompatible(c.SpuriousDragonBlock, newcfg.SpuriousDragonBlock, head) { return newCompatError("Spurious Dragon fork block", c.SpuriousDragonBlock, newcfg.SpuriousDragonBlock) } if c.IsSpuriousDragon(head) && !configNumEqual(c.ChainID, newcfg.ChainID) { return newCompatError("EIP155 chain ID", c.SpuriousDragonBlock, newcfg.SpuriousDragonBlock) } if isForkIncompatible(c.ByzantiumBlock, newcfg.ByzantiumBlock, head) { return newCompatError("Byzantium fork block", c.ByzantiumBlock, newcfg.ByzantiumBlock) } if isForkIncompatible(c.ConstantinopleBlock, newcfg.ConstantinopleBlock, head) { return newCompatError("Constantinople fork block", c.ConstantinopleBlock, newcfg.ConstantinopleBlock) } if isForkIncompatible(c.PetersburgBlock, newcfg.PetersburgBlock, head) { // the only case where we allow Petersburg to be set in the past is if it is equal to Constantinople // mainly to satisfy fork ordering requirements which state that Petersburg fork be set if Constantinople fork is set if isForkIncompatible(c.ConstantinopleBlock, newcfg.PetersburgBlock, head) { return newCompatError("Petersburg fork block", c.PetersburgBlock, newcfg.PetersburgBlock) } } if isForkIncompatible(c.IstanbulBlock, newcfg.IstanbulBlock, head) { return newCompatError("Istanbul fork block", c.IstanbulBlock, newcfg.IstanbulBlock) } if isForkIncompatible(c.MuirGlacierBlock, newcfg.MuirGlacierBlock, head) { return newCompatError("Muir Glacier fork block", c.MuirGlacierBlock, newcfg.MuirGlacierBlock) } if isForkIncompatible(c.BerlinBlock, newcfg.BerlinBlock, head) { return newCompatError("Berlin fork block", c.BerlinBlock, newcfg.BerlinBlock) } if isForkIncompatible(c.LondonBlock, newcfg.LondonBlock, head) { return newCompatError("London fork block", c.LondonBlock, newcfg.LondonBlock) } if isForkIncompatible(c.ArrowGlacierBlock, newcfg.ArrowGlacierBlock, head) { return newCompatError("Arrow Glacier fork block", c.ArrowGlacierBlock, newcfg.ArrowGlacierBlock) } if isForkIncompatible(c.GrayGlacierBlock, newcfg.GrayGlacierBlock, head) { return newCompatError("Gray Glacier fork block", c.GrayGlacierBlock, newcfg.GrayGlacierBlock) } if isForkIncompatible(c.MergeNetsplitBlock, newcfg.MergeNetsplitBlock, head) { return newCompatError("Merge netsplit block", c.MergeNetsplitBlock, newcfg.MergeNetsplitBlock) } if isForkIncompatible(c.ShanghaiBlock, newcfg.ShanghaiBlock, head) { return newCompatError("Shanghai fork block", c.ShanghaiBlock, newcfg.ShanghaiBlock) } if isForkIncompatible(c.CancunBlock, newcfg.CancunBlock, head) { return newCompatError("Cancun fork block", c.CancunBlock, newcfg.CancunBlock) } // Parlia forks if isForkIncompatible(c.RamanujanBlock, newcfg.RamanujanBlock, head) { return newCompatError("Ramanujan fork block", c.RamanujanBlock, newcfg.RamanujanBlock) } if isForkIncompatible(c.NielsBlock, newcfg.NielsBlock, head) { return newCompatError("Niels fork block", c.NielsBlock, newcfg.NielsBlock) } if isForkIncompatible(c.MirrorSyncBlock, newcfg.MirrorSyncBlock, head) { return newCompatError("MirrorSync fork block", c.MirrorSyncBlock, newcfg.MirrorSyncBlock) } if isForkIncompatible(c.BrunoBlock, newcfg.BrunoBlock, head) { return newCompatError("Bruno fork block", c.BrunoBlock, newcfg.BrunoBlock) } if isForkIncompatible(c.EulerBlock, newcfg.EulerBlock, head) { return newCompatError("Euler fork block", c.EulerBlock, newcfg.EulerBlock) } if isForkIncompatible(c.GibbsBlock, newcfg.GibbsBlock, head) { return newCompatError("Gibbs fork block", c.GibbsBlock, newcfg.GibbsBlock) } if isForkIncompatible(c.NanoBlock, newcfg.NanoBlock, head) { return newCompatError("Nano fork block", c.NanoBlock, newcfg.NanoBlock) } if isForkIncompatible(c.MoranBlock, newcfg.MoranBlock, head) { return newCompatError("moran fork block", c.MoranBlock, newcfg.MoranBlock) } return nil } // isForkIncompatible returns true if a fork scheduled at s1 cannot be rescheduled to // block s2 because head is already past the fork. func isForkIncompatible(s1, s2 *big.Int, head uint64) bool { return (isForked(s1, head) || isForked(s2, head)) && !configNumEqual(s1, s2) } // isForked returns whether a fork scheduled at block s is active at the given head block. func isForked(s *big.Int, head uint64) bool { if s == nil { return false } return s.Uint64() <= head } func configNumEqual(x, y *big.Int) bool { if x == nil { return y == nil } if y == nil { return x == nil } return x.Cmp(y) == 0 } // ConfigCompatError is raised if the locally-stored blockchain is initialised with a // ChainConfig that would alter the past. type ConfigCompatError struct { What string // block numbers of the stored and new configurations StoredConfig, NewConfig *big.Int // the block number to which the local chain must be rewound to correct the error RewindTo uint64 } func newCompatError(what string, storedblock, newblock *big.Int) *ConfigCompatError { var rew *big.Int switch { case storedblock == nil: rew = newblock case newblock == nil || storedblock.Cmp(newblock) < 0: rew = storedblock default: rew = newblock } err := &ConfigCompatError{what, storedblock, newblock, 0} if rew != nil && rew.Sign() > 0 { err.RewindTo = rew.Uint64() - 1 } return err } func (err *ConfigCompatError) Error() string { return fmt.Sprintf("mismatching %s in database (have %d, want %d, rewindto %d)", err.What, err.StoredConfig, err.NewConfig, err.RewindTo) } // Rules wraps ChainConfig and is merely syntactic sugar or can be used for functions // that do not have or require information about the block. // // Rules is a one time interface meaning that it shouldn't be used in between transition // phases. type Rules struct { ChainID *big.Int IsHomestead, IsTangerineWhistle, IsSpuriousDragon bool IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool IsBerlin, IsLondon, IsShanghai, IsCancun bool IsNano, IsMoran bool IsEip1559FeeCollector bool IsParlia, IsStarknet, IsAura bool } // Rules ensures c's ChainID is not nil. func (c *ChainConfig) Rules(num uint64) *Rules { chainID := c.ChainID if chainID == nil { chainID = new(big.Int) } return &Rules{ ChainID: new(big.Int).Set(chainID), IsHomestead: c.IsHomestead(num), IsTangerineWhistle: c.IsTangerineWhistle(num), IsSpuriousDragon: c.IsSpuriousDragon(num), IsByzantium: c.IsByzantium(num), IsConstantinople: c.IsConstantinople(num), IsPetersburg: c.IsPetersburg(num), IsIstanbul: c.IsIstanbul(num), IsBerlin: c.IsBerlin(num), IsLondon: c.IsLondon(num), IsShanghai: c.IsShanghai(num), IsCancun: c.IsCancun(num), IsNano: c.IsNano(num), IsMoran: c.IsMoran(num), IsEip1559FeeCollector: c.IsEip1559FeeCollector(num), IsParlia: c.Parlia != nil, IsAura: c.Aura != nil, } } func ChainConfigByChainName(chain string) *ChainConfig { switch chain { case networkname.MainnetChainName: return MainnetChainConfig case networkname.SepoliaChainName: return SepoliaChainConfig case networkname.RopstenChainName: return RopstenChainConfig case networkname.RinkebyChainName: return RinkebyChainConfig case networkname.GoerliChainName: return GoerliChainConfig case networkname.SokolChainName: return SokolChainConfig case networkname.FermionChainName: return FermionChainConfig case networkname.BSCChainName: return BSCChainConfig case networkname.ChapelChainName: return ChapelChainConfig case networkname.RialtoChainName: return RialtoChainConfig case networkname.MumbaiChainName: return MumbaiChainConfig case networkname.BorMainnetChainName: return BorMainnetChainConfig case networkname.BorDevnetChainName: return BorDevnetChainConfig case networkname.GnosisChainName: return GnosisChainConfig default: return nil } } func GenesisHashByChainName(chain string) *common.Hash { switch chain { case networkname.MainnetChainName: return &MainnetGenesisHash case networkname.SepoliaChainName: return &SepoliaGenesisHash case networkname.RopstenChainName: return &RopstenGenesisHash case networkname.RinkebyChainName: return &RinkebyGenesisHash case networkname.GoerliChainName: return &GoerliGenesisHash case networkname.SokolChainName: return &SokolGenesisHash case networkname.FermionChainName: return &FermionGenesisHash case networkname.BSCChainName: return &BSCGenesisHash case networkname.ChapelChainName: return &ChapelGenesisHash case networkname.RialtoChainName: return &RialtoGenesisHash case networkname.MumbaiChainName: return &MumbaiGenesisHash case networkname.BorMainnetChainName: return &BorMainnetGenesisHash case networkname.BorDevnetChainName: return &BorDevnetGenesisHash case networkname.GnosisChainName: return &GnosisGenesisHash default: return nil } } func ChainConfigByGenesisHash(genesisHash common.Hash) *ChainConfig { switch { case genesisHash == MainnetGenesisHash: return MainnetChainConfig case genesisHash == SepoliaGenesisHash: return SepoliaChainConfig case genesisHash == RopstenGenesisHash: return RopstenChainConfig case genesisHash == RinkebyGenesisHash: return RinkebyChainConfig case genesisHash == GoerliGenesisHash: return GoerliChainConfig case genesisHash == SokolGenesisHash: return SokolChainConfig case genesisHash == FermionGenesisHash: return FermionChainConfig case genesisHash == BSCGenesisHash: return BSCChainConfig case genesisHash == ChapelGenesisHash: return ChapelChainConfig case genesisHash == RialtoGenesisHash: return RialtoChainConfig case genesisHash == MumbaiGenesisHash: return MumbaiChainConfig case genesisHash == BorMainnetGenesisHash: return BorMainnetChainConfig case genesisHash == GnosisGenesisHash: return GnosisChainConfig default: return nil } } func NetworkIDByChainName(chain string) uint64 { switch chain { case networkname.RialtoChainName: return 97 case networkname.DevChainName: return 1337 default: config := ChainConfigByChainName(chain) if config == nil { return 0 } return config.ChainID.Uint64() } }