github.com/ethereum/go-ethereum@v1.14.4-0.20240516095835-473ee8fc07a3/params/config.go (about) 1 // Copyright 2016 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package params 18 19 import ( 20 "fmt" 21 "math/big" 22 23 "github.com/ethereum/go-ethereum/common" 24 "github.com/ethereum/go-ethereum/params/forks" 25 ) 26 27 // Genesis hashes to enforce below configs on. 28 var ( 29 MainnetGenesisHash = common.HexToHash("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3") 30 HoleskyGenesisHash = common.HexToHash("0xb5f7f912443c940f21fd611f12828d75b534364ed9e95ca4e307729a4661bde4") 31 SepoliaGenesisHash = common.HexToHash("0x25a5cc106eea7138acab33231d7160d69cb777ee0c2c553fcddf5138993e6dd9") 32 GoerliGenesisHash = common.HexToHash("0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a") 33 ) 34 35 func newUint64(val uint64) *uint64 { return &val } 36 37 var ( 38 MainnetTerminalTotalDifficulty, _ = new(big.Int).SetString("58_750_000_000_000_000_000_000", 0) 39 40 // MainnetChainConfig is the chain parameters to run a node on the main network. 41 MainnetChainConfig = &ChainConfig{ 42 ChainID: big.NewInt(1), 43 HomesteadBlock: big.NewInt(1_150_000), 44 DAOForkBlock: big.NewInt(1_920_000), 45 DAOForkSupport: true, 46 EIP150Block: big.NewInt(2_463_000), 47 EIP155Block: big.NewInt(2_675_000), 48 EIP158Block: big.NewInt(2_675_000), 49 ByzantiumBlock: big.NewInt(4_370_000), 50 ConstantinopleBlock: big.NewInt(7_280_000), 51 PetersburgBlock: big.NewInt(7_280_000), 52 IstanbulBlock: big.NewInt(9_069_000), 53 MuirGlacierBlock: big.NewInt(9_200_000), 54 BerlinBlock: big.NewInt(12_244_000), 55 LondonBlock: big.NewInt(12_965_000), 56 ArrowGlacierBlock: big.NewInt(13_773_000), 57 GrayGlacierBlock: big.NewInt(15_050_000), 58 TerminalTotalDifficulty: MainnetTerminalTotalDifficulty, // 58_750_000_000_000_000_000_000 59 TerminalTotalDifficultyPassed: true, 60 ShanghaiTime: newUint64(1681338455), 61 CancunTime: newUint64(1710338135), 62 Ethash: new(EthashConfig), 63 } 64 // HoleskyChainConfig contains the chain parameters to run a node on the Holesky test network. 65 HoleskyChainConfig = &ChainConfig{ 66 ChainID: big.NewInt(17000), 67 HomesteadBlock: big.NewInt(0), 68 DAOForkBlock: nil, 69 DAOForkSupport: true, 70 EIP150Block: big.NewInt(0), 71 EIP155Block: big.NewInt(0), 72 EIP158Block: big.NewInt(0), 73 ByzantiumBlock: big.NewInt(0), 74 ConstantinopleBlock: big.NewInt(0), 75 PetersburgBlock: big.NewInt(0), 76 IstanbulBlock: big.NewInt(0), 77 MuirGlacierBlock: nil, 78 BerlinBlock: big.NewInt(0), 79 LondonBlock: big.NewInt(0), 80 ArrowGlacierBlock: nil, 81 GrayGlacierBlock: nil, 82 TerminalTotalDifficulty: big.NewInt(0), 83 TerminalTotalDifficultyPassed: true, 84 MergeNetsplitBlock: nil, 85 ShanghaiTime: newUint64(1696000704), 86 CancunTime: newUint64(1707305664), 87 Ethash: new(EthashConfig), 88 } 89 // SepoliaChainConfig contains the chain parameters to run a node on the Sepolia test network. 90 SepoliaChainConfig = &ChainConfig{ 91 ChainID: big.NewInt(11155111), 92 HomesteadBlock: big.NewInt(0), 93 DAOForkBlock: nil, 94 DAOForkSupport: true, 95 EIP150Block: big.NewInt(0), 96 EIP155Block: big.NewInt(0), 97 EIP158Block: big.NewInt(0), 98 ByzantiumBlock: big.NewInt(0), 99 ConstantinopleBlock: big.NewInt(0), 100 PetersburgBlock: big.NewInt(0), 101 IstanbulBlock: big.NewInt(0), 102 MuirGlacierBlock: big.NewInt(0), 103 BerlinBlock: big.NewInt(0), 104 LondonBlock: big.NewInt(0), 105 ArrowGlacierBlock: nil, 106 GrayGlacierBlock: nil, 107 TerminalTotalDifficulty: big.NewInt(17_000_000_000_000_000), 108 TerminalTotalDifficultyPassed: true, 109 MergeNetsplitBlock: big.NewInt(1735371), 110 ShanghaiTime: newUint64(1677557088), 111 CancunTime: newUint64(1706655072), 112 Ethash: new(EthashConfig), 113 } 114 // GoerliChainConfig contains the chain parameters to run a node on the Görli test network. 115 GoerliChainConfig = &ChainConfig{ 116 ChainID: big.NewInt(5), 117 HomesteadBlock: big.NewInt(0), 118 DAOForkBlock: nil, 119 DAOForkSupport: true, 120 EIP150Block: big.NewInt(0), 121 EIP155Block: big.NewInt(0), 122 EIP158Block: big.NewInt(0), 123 ByzantiumBlock: big.NewInt(0), 124 ConstantinopleBlock: big.NewInt(0), 125 PetersburgBlock: big.NewInt(0), 126 IstanbulBlock: big.NewInt(1_561_651), 127 MuirGlacierBlock: nil, 128 BerlinBlock: big.NewInt(4_460_644), 129 LondonBlock: big.NewInt(5_062_605), 130 ArrowGlacierBlock: nil, 131 TerminalTotalDifficulty: big.NewInt(10_790_000), 132 TerminalTotalDifficultyPassed: true, 133 ShanghaiTime: newUint64(1678832736), 134 CancunTime: newUint64(1705473120), 135 Clique: &CliqueConfig{ 136 Period: 15, 137 Epoch: 30000, 138 }, 139 } 140 // AllEthashProtocolChanges contains every protocol change (EIPs) introduced 141 // and accepted by the Ethereum core developers into the Ethash consensus. 142 AllEthashProtocolChanges = &ChainConfig{ 143 ChainID: big.NewInt(1337), 144 HomesteadBlock: big.NewInt(0), 145 DAOForkBlock: nil, 146 DAOForkSupport: false, 147 EIP150Block: big.NewInt(0), 148 EIP155Block: big.NewInt(0), 149 EIP158Block: big.NewInt(0), 150 ByzantiumBlock: big.NewInt(0), 151 ConstantinopleBlock: big.NewInt(0), 152 PetersburgBlock: big.NewInt(0), 153 IstanbulBlock: big.NewInt(0), 154 MuirGlacierBlock: big.NewInt(0), 155 BerlinBlock: big.NewInt(0), 156 LondonBlock: big.NewInt(0), 157 ArrowGlacierBlock: big.NewInt(0), 158 GrayGlacierBlock: big.NewInt(0), 159 MergeNetsplitBlock: nil, 160 ShanghaiTime: nil, 161 CancunTime: nil, 162 PragueTime: nil, 163 VerkleTime: nil, 164 TerminalTotalDifficulty: nil, 165 TerminalTotalDifficultyPassed: true, 166 Ethash: new(EthashConfig), 167 Clique: nil, 168 } 169 170 AllDevChainProtocolChanges = &ChainConfig{ 171 ChainID: big.NewInt(1337), 172 HomesteadBlock: big.NewInt(0), 173 EIP150Block: big.NewInt(0), 174 EIP155Block: big.NewInt(0), 175 EIP158Block: big.NewInt(0), 176 ByzantiumBlock: big.NewInt(0), 177 ConstantinopleBlock: big.NewInt(0), 178 PetersburgBlock: big.NewInt(0), 179 IstanbulBlock: big.NewInt(0), 180 MuirGlacierBlock: big.NewInt(0), 181 BerlinBlock: big.NewInt(0), 182 LondonBlock: big.NewInt(0), 183 ArrowGlacierBlock: big.NewInt(0), 184 GrayGlacierBlock: big.NewInt(0), 185 ShanghaiTime: newUint64(0), 186 CancunTime: newUint64(0), 187 TerminalTotalDifficulty: big.NewInt(0), 188 TerminalTotalDifficultyPassed: true, 189 } 190 191 // AllCliqueProtocolChanges contains every protocol change (EIPs) introduced 192 // and accepted by the Ethereum core developers into the Clique consensus. 193 AllCliqueProtocolChanges = &ChainConfig{ 194 ChainID: big.NewInt(1337), 195 HomesteadBlock: big.NewInt(0), 196 DAOForkBlock: nil, 197 DAOForkSupport: false, 198 EIP150Block: big.NewInt(0), 199 EIP155Block: big.NewInt(0), 200 EIP158Block: big.NewInt(0), 201 ByzantiumBlock: big.NewInt(0), 202 ConstantinopleBlock: big.NewInt(0), 203 PetersburgBlock: big.NewInt(0), 204 IstanbulBlock: big.NewInt(0), 205 MuirGlacierBlock: big.NewInt(0), 206 BerlinBlock: big.NewInt(0), 207 LondonBlock: big.NewInt(0), 208 ArrowGlacierBlock: nil, 209 GrayGlacierBlock: nil, 210 MergeNetsplitBlock: nil, 211 ShanghaiTime: nil, 212 CancunTime: nil, 213 PragueTime: nil, 214 VerkleTime: nil, 215 TerminalTotalDifficulty: nil, 216 TerminalTotalDifficultyPassed: false, 217 Ethash: nil, 218 Clique: &CliqueConfig{Period: 0, Epoch: 30000}, 219 } 220 221 // TestChainConfig contains every protocol change (EIPs) introduced 222 // and accepted by the Ethereum core developers for testing purposes. 223 TestChainConfig = &ChainConfig{ 224 ChainID: big.NewInt(1), 225 HomesteadBlock: big.NewInt(0), 226 DAOForkBlock: nil, 227 DAOForkSupport: false, 228 EIP150Block: big.NewInt(0), 229 EIP155Block: big.NewInt(0), 230 EIP158Block: big.NewInt(0), 231 ByzantiumBlock: big.NewInt(0), 232 ConstantinopleBlock: big.NewInt(0), 233 PetersburgBlock: big.NewInt(0), 234 IstanbulBlock: big.NewInt(0), 235 MuirGlacierBlock: big.NewInt(0), 236 BerlinBlock: big.NewInt(0), 237 LondonBlock: big.NewInt(0), 238 ArrowGlacierBlock: big.NewInt(0), 239 GrayGlacierBlock: big.NewInt(0), 240 MergeNetsplitBlock: nil, 241 ShanghaiTime: nil, 242 CancunTime: nil, 243 PragueTime: nil, 244 VerkleTime: nil, 245 TerminalTotalDifficulty: nil, 246 TerminalTotalDifficultyPassed: false, 247 Ethash: new(EthashConfig), 248 Clique: nil, 249 } 250 251 // MergedTestChainConfig contains every protocol change (EIPs) introduced 252 // and accepted by the Ethereum core developers for testing purposes. 253 MergedTestChainConfig = &ChainConfig{ 254 ChainID: big.NewInt(1), 255 HomesteadBlock: big.NewInt(0), 256 DAOForkBlock: nil, 257 DAOForkSupport: false, 258 EIP150Block: big.NewInt(0), 259 EIP155Block: big.NewInt(0), 260 EIP158Block: big.NewInt(0), 261 ByzantiumBlock: big.NewInt(0), 262 ConstantinopleBlock: big.NewInt(0), 263 PetersburgBlock: big.NewInt(0), 264 IstanbulBlock: big.NewInt(0), 265 MuirGlacierBlock: big.NewInt(0), 266 BerlinBlock: big.NewInt(0), 267 LondonBlock: big.NewInt(0), 268 ArrowGlacierBlock: big.NewInt(0), 269 GrayGlacierBlock: big.NewInt(0), 270 MergeNetsplitBlock: big.NewInt(0), 271 ShanghaiTime: newUint64(0), 272 CancunTime: newUint64(0), 273 PragueTime: nil, 274 VerkleTime: nil, 275 TerminalTotalDifficulty: big.NewInt(0), 276 TerminalTotalDifficultyPassed: true, 277 Ethash: new(EthashConfig), 278 Clique: nil, 279 } 280 281 // NonActivatedConfig defines the chain configuration without activating 282 // any protocol change (EIPs). 283 NonActivatedConfig = &ChainConfig{ 284 ChainID: big.NewInt(1), 285 HomesteadBlock: nil, 286 DAOForkBlock: nil, 287 DAOForkSupport: false, 288 EIP150Block: nil, 289 EIP155Block: nil, 290 EIP158Block: nil, 291 ByzantiumBlock: nil, 292 ConstantinopleBlock: nil, 293 PetersburgBlock: nil, 294 IstanbulBlock: nil, 295 MuirGlacierBlock: nil, 296 BerlinBlock: nil, 297 LondonBlock: nil, 298 ArrowGlacierBlock: nil, 299 GrayGlacierBlock: nil, 300 MergeNetsplitBlock: nil, 301 ShanghaiTime: nil, 302 CancunTime: nil, 303 PragueTime: nil, 304 VerkleTime: nil, 305 TerminalTotalDifficulty: nil, 306 TerminalTotalDifficultyPassed: false, 307 Ethash: new(EthashConfig), 308 Clique: nil, 309 } 310 TestRules = TestChainConfig.Rules(new(big.Int), false, 0) 311 ) 312 313 // NetworkNames are user friendly names to use in the chain spec banner. 314 var NetworkNames = map[string]string{ 315 MainnetChainConfig.ChainID.String(): "mainnet", 316 GoerliChainConfig.ChainID.String(): "goerli", 317 SepoliaChainConfig.ChainID.String(): "sepolia", 318 HoleskyChainConfig.ChainID.String(): "holesky", 319 } 320 321 // ChainConfig is the core config which determines the blockchain settings. 322 // 323 // ChainConfig is stored in the database on a per block basis. This means 324 // that any network, identified by its genesis block, can have its own 325 // set of configuration options. 326 type ChainConfig struct { 327 ChainID *big.Int `json:"chainId"` // chainId identifies the current chain and is used for replay protection 328 329 HomesteadBlock *big.Int `json:"homesteadBlock,omitempty"` // Homestead switch block (nil = no fork, 0 = already homestead) 330 331 DAOForkBlock *big.Int `json:"daoForkBlock,omitempty"` // TheDAO hard-fork switch block (nil = no fork) 332 DAOForkSupport bool `json:"daoForkSupport,omitempty"` // Whether the nodes supports or opposes the DAO hard-fork 333 334 // EIP150 implements the Gas price changes (https://github.com/ethereum/EIPs/issues/150) 335 EIP150Block *big.Int `json:"eip150Block,omitempty"` // EIP150 HF block (nil = no fork) 336 EIP155Block *big.Int `json:"eip155Block,omitempty"` // EIP155 HF block 337 EIP158Block *big.Int `json:"eip158Block,omitempty"` // EIP158 HF block 338 339 ByzantiumBlock *big.Int `json:"byzantiumBlock,omitempty"` // Byzantium switch block (nil = no fork, 0 = already on byzantium) 340 ConstantinopleBlock *big.Int `json:"constantinopleBlock,omitempty"` // Constantinople switch block (nil = no fork, 0 = already activated) 341 PetersburgBlock *big.Int `json:"petersburgBlock,omitempty"` // Petersburg switch block (nil = same as Constantinople) 342 IstanbulBlock *big.Int `json:"istanbulBlock,omitempty"` // Istanbul switch block (nil = no fork, 0 = already on istanbul) 343 MuirGlacierBlock *big.Int `json:"muirGlacierBlock,omitempty"` // Eip-2384 (bomb delay) switch block (nil = no fork, 0 = already activated) 344 BerlinBlock *big.Int `json:"berlinBlock,omitempty"` // Berlin switch block (nil = no fork, 0 = already on berlin) 345 LondonBlock *big.Int `json:"londonBlock,omitempty"` // London switch block (nil = no fork, 0 = already on london) 346 ArrowGlacierBlock *big.Int `json:"arrowGlacierBlock,omitempty"` // Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already activated) 347 GrayGlacierBlock *big.Int `json:"grayGlacierBlock,omitempty"` // Eip-5133 (bomb delay) switch block (nil = no fork, 0 = already activated) 348 MergeNetsplitBlock *big.Int `json:"mergeNetsplitBlock,omitempty"` // Virtual fork after The Merge to use as a network splitter 349 350 // Fork scheduling was switched from blocks to timestamps here 351 352 ShanghaiTime *uint64 `json:"shanghaiTime,omitempty"` // Shanghai switch time (nil = no fork, 0 = already on shanghai) 353 CancunTime *uint64 `json:"cancunTime,omitempty"` // Cancun switch time (nil = no fork, 0 = already on cancun) 354 PragueTime *uint64 `json:"pragueTime,omitempty"` // Prague switch time (nil = no fork, 0 = already on prague) 355 VerkleTime *uint64 `json:"verkleTime,omitempty"` // Verkle switch time (nil = no fork, 0 = already on verkle) 356 357 // TerminalTotalDifficulty is the amount of total difficulty reached by 358 // the network that triggers the consensus upgrade. 359 TerminalTotalDifficulty *big.Int `json:"terminalTotalDifficulty,omitempty"` 360 361 // TerminalTotalDifficultyPassed is a flag specifying that the network already 362 // passed the terminal total difficulty. Its purpose is to disable legacy sync 363 // even without having seen the TTD locally (safer long term). 364 // 365 // TODO(karalabe): Drop this field eventually (always assuming PoS mode) 366 TerminalTotalDifficultyPassed bool `json:"terminalTotalDifficultyPassed,omitempty"` 367 368 // Various consensus engines 369 Ethash *EthashConfig `json:"ethash,omitempty"` 370 Clique *CliqueConfig `json:"clique,omitempty"` 371 } 372 373 // EthashConfig is the consensus engine configs for proof-of-work based sealing. 374 type EthashConfig struct{} 375 376 // String implements the stringer interface, returning the consensus engine details. 377 func (c EthashConfig) String() string { 378 return "ethash" 379 } 380 381 // CliqueConfig is the consensus engine configs for proof-of-authority based sealing. 382 type CliqueConfig struct { 383 Period uint64 `json:"period"` // Number of seconds between blocks to enforce 384 Epoch uint64 `json:"epoch"` // Epoch length to reset votes and checkpoint 385 } 386 387 // String implements the stringer interface, returning the consensus engine details. 388 func (c CliqueConfig) String() string { 389 return fmt.Sprintf("clique(period: %d, epoch: %d)", c.Period, c.Epoch) 390 } 391 392 // Description returns a human-readable description of ChainConfig. 393 func (c *ChainConfig) Description() string { 394 var banner string 395 396 // Create some basic network config output 397 network := NetworkNames[c.ChainID.String()] 398 if network == "" { 399 network = "unknown" 400 } 401 banner += fmt.Sprintf("Chain ID: %v (%s)\n", c.ChainID, network) 402 switch { 403 case c.Ethash != nil: 404 if c.TerminalTotalDifficulty == nil { 405 banner += "Consensus: Ethash (proof-of-work)\n" 406 } else if !c.TerminalTotalDifficultyPassed { 407 banner += "Consensus: Beacon (proof-of-stake), merging from Ethash (proof-of-work)\n" 408 } else { 409 banner += "Consensus: Beacon (proof-of-stake), merged from Ethash (proof-of-work)\n" 410 } 411 case c.Clique != nil: 412 if c.TerminalTotalDifficulty == nil { 413 banner += "Consensus: Clique (proof-of-authority)\n" 414 } else if !c.TerminalTotalDifficultyPassed { 415 banner += "Consensus: Beacon (proof-of-stake), merging from Clique (proof-of-authority)\n" 416 } else { 417 banner += "Consensus: Beacon (proof-of-stake), merged from Clique (proof-of-authority)\n" 418 } 419 default: 420 banner += "Consensus: unknown\n" 421 } 422 banner += "\n" 423 424 // Create a list of forks with a short description of them. Forks that only 425 // makes sense for mainnet should be optional at printing to avoid bloating 426 // the output for testnets and private networks. 427 banner += "Pre-Merge hard forks (block based):\n" 428 banner += fmt.Sprintf(" - Homestead: #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/homestead.md)\n", c.HomesteadBlock) 429 if c.DAOForkBlock != nil { 430 banner += fmt.Sprintf(" - DAO Fork: #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/dao-fork.md)\n", c.DAOForkBlock) 431 } 432 banner += fmt.Sprintf(" - Tangerine Whistle (EIP 150): #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/tangerine-whistle.md)\n", c.EIP150Block) 433 banner += fmt.Sprintf(" - Spurious Dragon/1 (EIP 155): #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/spurious-dragon.md)\n", c.EIP155Block) 434 banner += fmt.Sprintf(" - Spurious Dragon/2 (EIP 158): #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/spurious-dragon.md)\n", c.EIP155Block) 435 banner += fmt.Sprintf(" - Byzantium: #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/byzantium.md)\n", c.ByzantiumBlock) 436 banner += fmt.Sprintf(" - Constantinople: #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/constantinople.md)\n", c.ConstantinopleBlock) 437 banner += fmt.Sprintf(" - Petersburg: #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/petersburg.md)\n", c.PetersburgBlock) 438 banner += fmt.Sprintf(" - Istanbul: #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/istanbul.md)\n", c.IstanbulBlock) 439 if c.MuirGlacierBlock != nil { 440 banner += fmt.Sprintf(" - Muir Glacier: #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/muir-glacier.md)\n", c.MuirGlacierBlock) 441 } 442 banner += fmt.Sprintf(" - Berlin: #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/berlin.md)\n", c.BerlinBlock) 443 banner += fmt.Sprintf(" - London: #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/london.md)\n", c.LondonBlock) 444 if c.ArrowGlacierBlock != nil { 445 banner += fmt.Sprintf(" - Arrow Glacier: #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/arrow-glacier.md)\n", c.ArrowGlacierBlock) 446 } 447 if c.GrayGlacierBlock != nil { 448 banner += fmt.Sprintf(" - Gray Glacier: #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/gray-glacier.md)\n", c.GrayGlacierBlock) 449 } 450 banner += "\n" 451 452 // Add a special section for the merge as it's non-obvious 453 if c.TerminalTotalDifficulty == nil { 454 banner += "The Merge is not yet available for this network!\n" 455 banner += " - Hard-fork specification: https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/paris.md\n" 456 } else { 457 banner += "Merge configured:\n" 458 banner += " - Hard-fork specification: https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/paris.md\n" 459 banner += fmt.Sprintf(" - Network known to be merged: %v\n", c.TerminalTotalDifficultyPassed) 460 banner += fmt.Sprintf(" - Total terminal difficulty: %v\n", c.TerminalTotalDifficulty) 461 if c.MergeNetsplitBlock != nil { 462 banner += fmt.Sprintf(" - Merge netsplit block: #%-8v\n", c.MergeNetsplitBlock) 463 } 464 } 465 banner += "\n" 466 467 // Create a list of forks post-merge 468 banner += "Post-Merge hard forks (timestamp based):\n" 469 if c.ShanghaiTime != nil { 470 banner += fmt.Sprintf(" - Shanghai: @%-10v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/shanghai.md)\n", *c.ShanghaiTime) 471 } 472 if c.CancunTime != nil { 473 banner += fmt.Sprintf(" - Cancun: @%-10v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/cancun.md)\n", *c.CancunTime) 474 } 475 if c.PragueTime != nil { 476 banner += fmt.Sprintf(" - Prague: @%-10v\n", *c.PragueTime) 477 } 478 if c.VerkleTime != nil { 479 banner += fmt.Sprintf(" - Verkle: @%-10v\n", *c.VerkleTime) 480 } 481 return banner 482 } 483 484 // IsHomestead returns whether num is either equal to the homestead block or greater. 485 func (c *ChainConfig) IsHomestead(num *big.Int) bool { 486 return isBlockForked(c.HomesteadBlock, num) 487 } 488 489 // IsDAOFork returns whether num is either equal to the DAO fork block or greater. 490 func (c *ChainConfig) IsDAOFork(num *big.Int) bool { 491 return isBlockForked(c.DAOForkBlock, num) 492 } 493 494 // IsEIP150 returns whether num is either equal to the EIP150 fork block or greater. 495 func (c *ChainConfig) IsEIP150(num *big.Int) bool { 496 return isBlockForked(c.EIP150Block, num) 497 } 498 499 // IsEIP155 returns whether num is either equal to the EIP155 fork block or greater. 500 func (c *ChainConfig) IsEIP155(num *big.Int) bool { 501 return isBlockForked(c.EIP155Block, num) 502 } 503 504 // IsEIP158 returns whether num is either equal to the EIP158 fork block or greater. 505 func (c *ChainConfig) IsEIP158(num *big.Int) bool { 506 return isBlockForked(c.EIP158Block, num) 507 } 508 509 // IsByzantium returns whether num is either equal to the Byzantium fork block or greater. 510 func (c *ChainConfig) IsByzantium(num *big.Int) bool { 511 return isBlockForked(c.ByzantiumBlock, num) 512 } 513 514 // IsConstantinople returns whether num is either equal to the Constantinople fork block or greater. 515 func (c *ChainConfig) IsConstantinople(num *big.Int) bool { 516 return isBlockForked(c.ConstantinopleBlock, num) 517 } 518 519 // IsMuirGlacier returns whether num is either equal to the Muir Glacier (EIP-2384) fork block or greater. 520 func (c *ChainConfig) IsMuirGlacier(num *big.Int) bool { 521 return isBlockForked(c.MuirGlacierBlock, num) 522 } 523 524 // IsPetersburg returns whether num is either 525 // - equal to or greater than the PetersburgBlock fork block, 526 // - OR is nil, and Constantinople is active 527 func (c *ChainConfig) IsPetersburg(num *big.Int) bool { 528 return isBlockForked(c.PetersburgBlock, num) || c.PetersburgBlock == nil && isBlockForked(c.ConstantinopleBlock, num) 529 } 530 531 // IsIstanbul returns whether num is either equal to the Istanbul fork block or greater. 532 func (c *ChainConfig) IsIstanbul(num *big.Int) bool { 533 return isBlockForked(c.IstanbulBlock, num) 534 } 535 536 // IsBerlin returns whether num is either equal to the Berlin fork block or greater. 537 func (c *ChainConfig) IsBerlin(num *big.Int) bool { 538 return isBlockForked(c.BerlinBlock, num) 539 } 540 541 // IsLondon returns whether num is either equal to the London fork block or greater. 542 func (c *ChainConfig) IsLondon(num *big.Int) bool { 543 return isBlockForked(c.LondonBlock, num) 544 } 545 546 // IsArrowGlacier returns whether num is either equal to the Arrow Glacier (EIP-4345) fork block or greater. 547 func (c *ChainConfig) IsArrowGlacier(num *big.Int) bool { 548 return isBlockForked(c.ArrowGlacierBlock, num) 549 } 550 551 // IsGrayGlacier returns whether num is either equal to the Gray Glacier (EIP-5133) fork block or greater. 552 func (c *ChainConfig) IsGrayGlacier(num *big.Int) bool { 553 return isBlockForked(c.GrayGlacierBlock, num) 554 } 555 556 // IsTerminalPoWBlock returns whether the given block is the last block of PoW stage. 557 func (c *ChainConfig) IsTerminalPoWBlock(parentTotalDiff *big.Int, totalDiff *big.Int) bool { 558 if c.TerminalTotalDifficulty == nil { 559 return false 560 } 561 return parentTotalDiff.Cmp(c.TerminalTotalDifficulty) < 0 && totalDiff.Cmp(c.TerminalTotalDifficulty) >= 0 562 } 563 564 // IsShanghai returns whether time is either equal to the Shanghai fork time or greater. 565 func (c *ChainConfig) IsShanghai(num *big.Int, time uint64) bool { 566 return c.IsLondon(num) && isTimestampForked(c.ShanghaiTime, time) 567 } 568 569 // IsCancun returns whether time is either equal to the Cancun fork time or greater. 570 func (c *ChainConfig) IsCancun(num *big.Int, time uint64) bool { 571 return c.IsLondon(num) && isTimestampForked(c.CancunTime, time) 572 } 573 574 // IsPrague returns whether time is either equal to the Prague fork time or greater. 575 func (c *ChainConfig) IsPrague(num *big.Int, time uint64) bool { 576 return c.IsLondon(num) && isTimestampForked(c.PragueTime, time) 577 } 578 579 // IsVerkle returns whether time is either equal to the Verkle fork time or greater. 580 func (c *ChainConfig) IsVerkle(num *big.Int, time uint64) bool { 581 return c.IsLondon(num) && isTimestampForked(c.VerkleTime, time) 582 } 583 584 // IsEIP4762 returns whether eip 4762 has been activated at given block. 585 func (c *ChainConfig) IsEIP4762(num *big.Int, time uint64) bool { 586 return c.IsVerkle(num, time) 587 } 588 589 // CheckCompatible checks whether scheduled fork transitions have been imported 590 // with a mismatching chain configuration. 591 func (c *ChainConfig) CheckCompatible(newcfg *ChainConfig, height uint64, time uint64) *ConfigCompatError { 592 var ( 593 bhead = new(big.Int).SetUint64(height) 594 btime = time 595 ) 596 // Iterate checkCompatible to find the lowest conflict. 597 var lasterr *ConfigCompatError 598 for { 599 err := c.checkCompatible(newcfg, bhead, btime) 600 if err == nil || (lasterr != nil && err.RewindToBlock == lasterr.RewindToBlock && err.RewindToTime == lasterr.RewindToTime) { 601 break 602 } 603 lasterr = err 604 605 if err.RewindToTime > 0 { 606 btime = err.RewindToTime 607 } else { 608 bhead.SetUint64(err.RewindToBlock) 609 } 610 } 611 return lasterr 612 } 613 614 // CheckConfigForkOrder checks that we don't "skip" any forks, geth isn't pluggable enough 615 // to guarantee that forks can be implemented in a different order than on official networks 616 func (c *ChainConfig) CheckConfigForkOrder() error { 617 type fork struct { 618 name string 619 block *big.Int // forks up to - and including the merge - were defined with block numbers 620 timestamp *uint64 // forks after the merge are scheduled using timestamps 621 optional bool // if true, the fork may be nil and next fork is still allowed 622 } 623 var lastFork fork 624 for _, cur := range []fork{ 625 {name: "homesteadBlock", block: c.HomesteadBlock}, 626 {name: "daoForkBlock", block: c.DAOForkBlock, optional: true}, 627 {name: "eip150Block", block: c.EIP150Block}, 628 {name: "eip155Block", block: c.EIP155Block}, 629 {name: "eip158Block", block: c.EIP158Block}, 630 {name: "byzantiumBlock", block: c.ByzantiumBlock}, 631 {name: "constantinopleBlock", block: c.ConstantinopleBlock}, 632 {name: "petersburgBlock", block: c.PetersburgBlock}, 633 {name: "istanbulBlock", block: c.IstanbulBlock}, 634 {name: "muirGlacierBlock", block: c.MuirGlacierBlock, optional: true}, 635 {name: "berlinBlock", block: c.BerlinBlock}, 636 {name: "londonBlock", block: c.LondonBlock}, 637 {name: "arrowGlacierBlock", block: c.ArrowGlacierBlock, optional: true}, 638 {name: "grayGlacierBlock", block: c.GrayGlacierBlock, optional: true}, 639 {name: "mergeNetsplitBlock", block: c.MergeNetsplitBlock, optional: true}, 640 {name: "shanghaiTime", timestamp: c.ShanghaiTime}, 641 {name: "cancunTime", timestamp: c.CancunTime, optional: true}, 642 {name: "pragueTime", timestamp: c.PragueTime, optional: true}, 643 {name: "verkleTime", timestamp: c.VerkleTime, optional: true}, 644 } { 645 if lastFork.name != "" { 646 switch { 647 // Non-optional forks must all be present in the chain config up to the last defined fork 648 case lastFork.block == nil && lastFork.timestamp == nil && (cur.block != nil || cur.timestamp != nil): 649 if cur.block != nil { 650 return fmt.Errorf("unsupported fork ordering: %v not enabled, but %v enabled at block %v", 651 lastFork.name, cur.name, cur.block) 652 } else { 653 return fmt.Errorf("unsupported fork ordering: %v not enabled, but %v enabled at timestamp %v", 654 lastFork.name, cur.name, *cur.timestamp) 655 } 656 657 // Fork (whether defined by block or timestamp) must follow the fork definition sequence 658 case (lastFork.block != nil && cur.block != nil) || (lastFork.timestamp != nil && cur.timestamp != nil): 659 if lastFork.block != nil && lastFork.block.Cmp(cur.block) > 0 { 660 return fmt.Errorf("unsupported fork ordering: %v enabled at block %v, but %v enabled at block %v", 661 lastFork.name, lastFork.block, cur.name, cur.block) 662 } else if lastFork.timestamp != nil && *lastFork.timestamp > *cur.timestamp { 663 return fmt.Errorf("unsupported fork ordering: %v enabled at timestamp %v, but %v enabled at timestamp %v", 664 lastFork.name, *lastFork.timestamp, cur.name, *cur.timestamp) 665 } 666 667 // Timestamp based forks can follow block based ones, but not the other way around 668 if lastFork.timestamp != nil && cur.block != nil { 669 return fmt.Errorf("unsupported fork ordering: %v used timestamp ordering, but %v reverted to block ordering", 670 lastFork.name, cur.name) 671 } 672 } 673 } 674 // If it was optional and not set, then ignore it 675 if !cur.optional || (cur.block != nil || cur.timestamp != nil) { 676 lastFork = cur 677 } 678 } 679 return nil 680 } 681 682 func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, headNumber *big.Int, headTimestamp uint64) *ConfigCompatError { 683 if isForkBlockIncompatible(c.HomesteadBlock, newcfg.HomesteadBlock, headNumber) { 684 return newBlockCompatError("Homestead fork block", c.HomesteadBlock, newcfg.HomesteadBlock) 685 } 686 if isForkBlockIncompatible(c.DAOForkBlock, newcfg.DAOForkBlock, headNumber) { 687 return newBlockCompatError("DAO fork block", c.DAOForkBlock, newcfg.DAOForkBlock) 688 } 689 if c.IsDAOFork(headNumber) && c.DAOForkSupport != newcfg.DAOForkSupport { 690 return newBlockCompatError("DAO fork support flag", c.DAOForkBlock, newcfg.DAOForkBlock) 691 } 692 if isForkBlockIncompatible(c.EIP150Block, newcfg.EIP150Block, headNumber) { 693 return newBlockCompatError("EIP150 fork block", c.EIP150Block, newcfg.EIP150Block) 694 } 695 if isForkBlockIncompatible(c.EIP155Block, newcfg.EIP155Block, headNumber) { 696 return newBlockCompatError("EIP155 fork block", c.EIP155Block, newcfg.EIP155Block) 697 } 698 if isForkBlockIncompatible(c.EIP158Block, newcfg.EIP158Block, headNumber) { 699 return newBlockCompatError("EIP158 fork block", c.EIP158Block, newcfg.EIP158Block) 700 } 701 if c.IsEIP158(headNumber) && !configBlockEqual(c.ChainID, newcfg.ChainID) { 702 return newBlockCompatError("EIP158 chain ID", c.EIP158Block, newcfg.EIP158Block) 703 } 704 if isForkBlockIncompatible(c.ByzantiumBlock, newcfg.ByzantiumBlock, headNumber) { 705 return newBlockCompatError("Byzantium fork block", c.ByzantiumBlock, newcfg.ByzantiumBlock) 706 } 707 if isForkBlockIncompatible(c.ConstantinopleBlock, newcfg.ConstantinopleBlock, headNumber) { 708 return newBlockCompatError("Constantinople fork block", c.ConstantinopleBlock, newcfg.ConstantinopleBlock) 709 } 710 if isForkBlockIncompatible(c.PetersburgBlock, newcfg.PetersburgBlock, headNumber) { 711 // the only case where we allow Petersburg to be set in the past is if it is equal to Constantinople 712 // mainly to satisfy fork ordering requirements which state that Petersburg fork be set if Constantinople fork is set 713 if isForkBlockIncompatible(c.ConstantinopleBlock, newcfg.PetersburgBlock, headNumber) { 714 return newBlockCompatError("Petersburg fork block", c.PetersburgBlock, newcfg.PetersburgBlock) 715 } 716 } 717 if isForkBlockIncompatible(c.IstanbulBlock, newcfg.IstanbulBlock, headNumber) { 718 return newBlockCompatError("Istanbul fork block", c.IstanbulBlock, newcfg.IstanbulBlock) 719 } 720 if isForkBlockIncompatible(c.MuirGlacierBlock, newcfg.MuirGlacierBlock, headNumber) { 721 return newBlockCompatError("Muir Glacier fork block", c.MuirGlacierBlock, newcfg.MuirGlacierBlock) 722 } 723 if isForkBlockIncompatible(c.BerlinBlock, newcfg.BerlinBlock, headNumber) { 724 return newBlockCompatError("Berlin fork block", c.BerlinBlock, newcfg.BerlinBlock) 725 } 726 if isForkBlockIncompatible(c.LondonBlock, newcfg.LondonBlock, headNumber) { 727 return newBlockCompatError("London fork block", c.LondonBlock, newcfg.LondonBlock) 728 } 729 if isForkBlockIncompatible(c.ArrowGlacierBlock, newcfg.ArrowGlacierBlock, headNumber) { 730 return newBlockCompatError("Arrow Glacier fork block", c.ArrowGlacierBlock, newcfg.ArrowGlacierBlock) 731 } 732 if isForkBlockIncompatible(c.GrayGlacierBlock, newcfg.GrayGlacierBlock, headNumber) { 733 return newBlockCompatError("Gray Glacier fork block", c.GrayGlacierBlock, newcfg.GrayGlacierBlock) 734 } 735 if isForkBlockIncompatible(c.MergeNetsplitBlock, newcfg.MergeNetsplitBlock, headNumber) { 736 return newBlockCompatError("Merge netsplit fork block", c.MergeNetsplitBlock, newcfg.MergeNetsplitBlock) 737 } 738 if isForkTimestampIncompatible(c.ShanghaiTime, newcfg.ShanghaiTime, headTimestamp) { 739 return newTimestampCompatError("Shanghai fork timestamp", c.ShanghaiTime, newcfg.ShanghaiTime) 740 } 741 if isForkTimestampIncompatible(c.CancunTime, newcfg.CancunTime, headTimestamp) { 742 return newTimestampCompatError("Cancun fork timestamp", c.CancunTime, newcfg.CancunTime) 743 } 744 if isForkTimestampIncompatible(c.PragueTime, newcfg.PragueTime, headTimestamp) { 745 return newTimestampCompatError("Prague fork timestamp", c.PragueTime, newcfg.PragueTime) 746 } 747 if isForkTimestampIncompatible(c.VerkleTime, newcfg.VerkleTime, headTimestamp) { 748 return newTimestampCompatError("Verkle fork timestamp", c.VerkleTime, newcfg.VerkleTime) 749 } 750 return nil 751 } 752 753 // BaseFeeChangeDenominator bounds the amount the base fee can change between blocks. 754 func (c *ChainConfig) BaseFeeChangeDenominator() uint64 { 755 return DefaultBaseFeeChangeDenominator 756 } 757 758 // ElasticityMultiplier bounds the maximum gas limit an EIP-1559 block may have. 759 func (c *ChainConfig) ElasticityMultiplier() uint64 { 760 return DefaultElasticityMultiplier 761 } 762 763 // LatestFork returns the latest time-based fork that would be active for the given time. 764 func (c *ChainConfig) LatestFork(time uint64) forks.Fork { 765 // Assume last non-time-based fork has passed. 766 london := c.LondonBlock 767 768 switch { 769 case c.IsPrague(london, time): 770 return forks.Prague 771 case c.IsCancun(london, time): 772 return forks.Cancun 773 case c.IsShanghai(london, time): 774 return forks.Shanghai 775 default: 776 return forks.Paris 777 } 778 } 779 780 // isForkBlockIncompatible returns true if a fork scheduled at block s1 cannot be 781 // rescheduled to block s2 because head is already past the fork. 782 func isForkBlockIncompatible(s1, s2, head *big.Int) bool { 783 return (isBlockForked(s1, head) || isBlockForked(s2, head)) && !configBlockEqual(s1, s2) 784 } 785 786 // isBlockForked returns whether a fork scheduled at block s is active at the 787 // given head block. Whilst this method is the same as isTimestampForked, they 788 // are explicitly separate for clearer reading. 789 func isBlockForked(s, head *big.Int) bool { 790 if s == nil || head == nil { 791 return false 792 } 793 return s.Cmp(head) <= 0 794 } 795 796 func configBlockEqual(x, y *big.Int) bool { 797 if x == nil { 798 return y == nil 799 } 800 if y == nil { 801 return x == nil 802 } 803 return x.Cmp(y) == 0 804 } 805 806 // isForkTimestampIncompatible returns true if a fork scheduled at timestamp s1 807 // cannot be rescheduled to timestamp s2 because head is already past the fork. 808 func isForkTimestampIncompatible(s1, s2 *uint64, head uint64) bool { 809 return (isTimestampForked(s1, head) || isTimestampForked(s2, head)) && !configTimestampEqual(s1, s2) 810 } 811 812 // isTimestampForked returns whether a fork scheduled at timestamp s is active 813 // at the given head timestamp. Whilst this method is the same as isBlockForked, 814 // they are explicitly separate for clearer reading. 815 func isTimestampForked(s *uint64, head uint64) bool { 816 if s == nil { 817 return false 818 } 819 return *s <= head 820 } 821 822 func configTimestampEqual(x, y *uint64) bool { 823 if x == nil { 824 return y == nil 825 } 826 if y == nil { 827 return x == nil 828 } 829 return *x == *y 830 } 831 832 // ConfigCompatError is raised if the locally-stored blockchain is initialised with a 833 // ChainConfig that would alter the past. 834 type ConfigCompatError struct { 835 What string 836 837 // block numbers of the stored and new configurations if block based forking 838 StoredBlock, NewBlock *big.Int 839 840 // timestamps of the stored and new configurations if time based forking 841 StoredTime, NewTime *uint64 842 843 // the block number to which the local chain must be rewound to correct the error 844 RewindToBlock uint64 845 846 // the timestamp to which the local chain must be rewound to correct the error 847 RewindToTime uint64 848 } 849 850 func newBlockCompatError(what string, storedblock, newblock *big.Int) *ConfigCompatError { 851 var rew *big.Int 852 switch { 853 case storedblock == nil: 854 rew = newblock 855 case newblock == nil || storedblock.Cmp(newblock) < 0: 856 rew = storedblock 857 default: 858 rew = newblock 859 } 860 err := &ConfigCompatError{ 861 What: what, 862 StoredBlock: storedblock, 863 NewBlock: newblock, 864 RewindToBlock: 0, 865 } 866 if rew != nil && rew.Sign() > 0 { 867 err.RewindToBlock = rew.Uint64() - 1 868 } 869 return err 870 } 871 872 func newTimestampCompatError(what string, storedtime, newtime *uint64) *ConfigCompatError { 873 var rew *uint64 874 switch { 875 case storedtime == nil: 876 rew = newtime 877 case newtime == nil || *storedtime < *newtime: 878 rew = storedtime 879 default: 880 rew = newtime 881 } 882 err := &ConfigCompatError{ 883 What: what, 884 StoredTime: storedtime, 885 NewTime: newtime, 886 RewindToTime: 0, 887 } 888 if rew != nil && *rew != 0 { 889 err.RewindToTime = *rew - 1 890 } 891 return err 892 } 893 894 func (err *ConfigCompatError) Error() string { 895 if err.StoredBlock != nil { 896 return fmt.Sprintf("mismatching %s in database (have block %d, want block %d, rewindto block %d)", err.What, err.StoredBlock, err.NewBlock, err.RewindToBlock) 897 } 898 899 if err.StoredTime == nil && err.NewTime == nil { 900 return "" 901 } else if err.StoredTime == nil && err.NewTime != nil { 902 return fmt.Sprintf("mismatching %s in database (have timestamp nil, want timestamp %d, rewindto timestamp %d)", err.What, *err.NewTime, err.RewindToTime) 903 } else if err.StoredTime != nil && err.NewTime == nil { 904 return fmt.Sprintf("mismatching %s in database (have timestamp %d, want timestamp nil, rewindto timestamp %d)", err.What, *err.StoredTime, err.RewindToTime) 905 } 906 return fmt.Sprintf("mismatching %s in database (have timestamp %d, want timestamp %d, rewindto timestamp %d)", err.What, *err.StoredTime, *err.NewTime, err.RewindToTime) 907 } 908 909 // Rules wraps ChainConfig and is merely syntactic sugar or can be used for functions 910 // that do not have or require information about the block. 911 // 912 // Rules is a one time interface meaning that it shouldn't be used in between transition 913 // phases. 914 type Rules struct { 915 ChainID *big.Int 916 IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool 917 IsEIP2929, IsEIP4762 bool 918 IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool 919 IsBerlin, IsLondon bool 920 IsMerge, IsShanghai, IsCancun, IsPrague bool 921 IsVerkle bool 922 } 923 924 // Rules ensures c's ChainID is not nil. 925 func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64) Rules { 926 chainID := c.ChainID 927 if chainID == nil { 928 chainID = new(big.Int) 929 } 930 // disallow setting Merge out of order 931 isMerge = isMerge && c.IsLondon(num) 932 isVerkle := isMerge && c.IsVerkle(num, timestamp) 933 return Rules{ 934 ChainID: new(big.Int).Set(chainID), 935 IsHomestead: c.IsHomestead(num), 936 IsEIP150: c.IsEIP150(num), 937 IsEIP155: c.IsEIP155(num), 938 IsEIP158: c.IsEIP158(num), 939 IsByzantium: c.IsByzantium(num), 940 IsConstantinople: c.IsConstantinople(num), 941 IsPetersburg: c.IsPetersburg(num), 942 IsIstanbul: c.IsIstanbul(num), 943 IsBerlin: c.IsBerlin(num), 944 IsEIP2929: c.IsBerlin(num) && !isVerkle, 945 IsLondon: c.IsLondon(num), 946 IsMerge: isMerge, 947 IsShanghai: isMerge && c.IsShanghai(num, timestamp), 948 IsCancun: isMerge && c.IsCancun(num, timestamp), 949 IsPrague: isMerge && c.IsPrague(num, timestamp), 950 IsVerkle: isVerkle, 951 IsEIP4762: isVerkle, 952 } 953 }