github.com/ledgerwatch/erigon-lib@v1.0.0/chain/chain_config.go (about) 1 /* 2 Copyright 2021 Erigon contributors 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package chain 18 19 import ( 20 "fmt" 21 "math/big" 22 "sort" 23 "strconv" 24 25 "github.com/ledgerwatch/erigon-lib/common" 26 ) 27 28 // Config is the core config which determines the blockchain settings. 29 // 30 // Config is stored in the database on a per block basis. This means 31 // that any network, identified by its genesis block, can have its own 32 // set of configuration options. 33 type Config struct { 34 ChainName string 35 ChainID *big.Int `json:"chainId"` // chainId identifies the current chain and is used for replay protection 36 37 Consensus ConsensusName `json:"consensus,omitempty"` // aura, ethash or clique 38 39 // *Block fields activate the corresponding hard fork at a certain block number, 40 // while *Time fields do so based on the block's time stamp. 41 // nil means that the hard-fork is not scheduled, 42 // while 0 means that it's already activated from genesis. 43 44 // ETH mainnet upgrades 45 // See https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades 46 HomesteadBlock *big.Int `json:"homesteadBlock,omitempty"` 47 DAOForkBlock *big.Int `json:"daoForkBlock,omitempty"` 48 TangerineWhistleBlock *big.Int `json:"eip150Block,omitempty"` 49 SpuriousDragonBlock *big.Int `json:"eip155Block,omitempty"` 50 ByzantiumBlock *big.Int `json:"byzantiumBlock,omitempty"` 51 ConstantinopleBlock *big.Int `json:"constantinopleBlock,omitempty"` 52 PetersburgBlock *big.Int `json:"petersburgBlock,omitempty"` 53 IstanbulBlock *big.Int `json:"istanbulBlock,omitempty"` 54 MuirGlacierBlock *big.Int `json:"muirGlacierBlock,omitempty"` 55 BerlinBlock *big.Int `json:"berlinBlock,omitempty"` 56 LondonBlock *big.Int `json:"londonBlock,omitempty"` 57 ArrowGlacierBlock *big.Int `json:"arrowGlacierBlock,omitempty"` 58 GrayGlacierBlock *big.Int `json:"grayGlacierBlock,omitempty"` 59 60 // EIP-3675: Upgrade consensus to Proof-of-Stake (a.k.a. "Paris", "The Merge") 61 TerminalTotalDifficulty *big.Int `json:"terminalTotalDifficulty,omitempty"` // The merge happens when terminal total difficulty is reached 62 TerminalTotalDifficultyPassed bool `json:"terminalTotalDifficultyPassed,omitempty"` // Disable PoW sync for networks that have already passed through the Merge 63 MergeNetsplitBlock *big.Int `json:"mergeNetsplitBlock,omitempty"` // Virtual fork after The Merge to use as a network splitter; see FORK_NEXT_VALUE in EIP-3675 64 65 // Mainnet fork scheduling switched from block numbers to timestamps after The Merge 66 ShanghaiTime *big.Int `json:"shanghaiTime,omitempty"` 67 CancunTime *big.Int `json:"cancunTime,omitempty"` 68 PragueTime *big.Int `json:"pragueTime,omitempty"` 69 70 Eip1559FeeCollector *common.Address `json:"eip1559FeeCollector,omitempty"` // (Optional) Address where burnt EIP-1559 fees go to 71 Eip1559FeeCollectorTransition *big.Int `json:"eip1559FeeCollectorTransition,omitempty"` // (Optional) Block from which burnt EIP-1559 fees go to the Eip1559FeeCollector 72 73 // Various consensus engines 74 Ethash *EthashConfig `json:"ethash,omitempty"` 75 Clique *CliqueConfig `json:"clique,omitempty"` 76 Aura *AuRaConfig `json:"aura,omitempty"` 77 Bor *BorConfig `json:"bor,omitempty"` 78 } 79 80 func (c *Config) String() string { 81 engine := c.getEngine() 82 83 return fmt.Sprintf("{ChainID: %v, Homestead: %v, DAO: %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, Prague: %v, Engine: %v}", 84 c.ChainID, 85 c.HomesteadBlock, 86 c.DAOForkBlock, 87 c.TangerineWhistleBlock, 88 c.SpuriousDragonBlock, 89 c.ByzantiumBlock, 90 c.ConstantinopleBlock, 91 c.PetersburgBlock, 92 c.IstanbulBlock, 93 c.MuirGlacierBlock, 94 c.BerlinBlock, 95 c.LondonBlock, 96 c.ArrowGlacierBlock, 97 c.GrayGlacierBlock, 98 c.TerminalTotalDifficulty, 99 c.MergeNetsplitBlock, 100 c.ShanghaiTime, 101 c.CancunTime, 102 c.PragueTime, 103 engine, 104 ) 105 } 106 107 func (c *Config) getEngine() string { 108 switch { 109 case c.Ethash != nil: 110 return c.Ethash.String() 111 case c.Clique != nil: 112 return c.Clique.String() 113 case c.Bor != nil: 114 return c.Bor.String() 115 case c.Aura != nil: 116 return c.Aura.String() 117 default: 118 return "unknown" 119 } 120 } 121 122 // IsHomestead returns whether num is either equal to the homestead block or greater. 123 func (c *Config) IsHomestead(num uint64) bool { 124 return isForked(c.HomesteadBlock, num) 125 } 126 127 // IsDAOFork returns whether num is either equal to the DAO fork block or greater. 128 func (c *Config) IsDAOFork(num uint64) bool { 129 return isForked(c.DAOForkBlock, num) 130 } 131 132 // IsTangerineWhistle returns whether num is either equal to the Tangerine Whistle (EIP150) fork block or greater. 133 func (c *Config) IsTangerineWhistle(num uint64) bool { 134 return isForked(c.TangerineWhistleBlock, num) 135 } 136 137 // IsSpuriousDragon returns whether num is either equal to the Spurious Dragon fork block or greater. 138 func (c *Config) IsSpuriousDragon(num uint64) bool { 139 return isForked(c.SpuriousDragonBlock, num) 140 } 141 142 // IsByzantium returns whether num is either equal to the Byzantium fork block or greater. 143 func (c *Config) IsByzantium(num uint64) bool { 144 return isForked(c.ByzantiumBlock, num) 145 } 146 147 // IsConstantinople returns whether num is either equal to the Constantinople fork block or greater. 148 func (c *Config) IsConstantinople(num uint64) bool { 149 return isForked(c.ConstantinopleBlock, num) 150 } 151 152 // IsMuirGlacier returns whether num is either equal to the Muir Glacier (EIP-2384) fork block or greater. 153 func (c *Config) IsMuirGlacier(num uint64) bool { 154 return isForked(c.MuirGlacierBlock, num) 155 } 156 157 // IsPetersburg returns whether num is either 158 // - equal to or greater than the PetersburgBlock fork block, 159 // - OR is nil, and Constantinople is active 160 func (c *Config) IsPetersburg(num uint64) bool { 161 return isForked(c.PetersburgBlock, num) || c.PetersburgBlock == nil && isForked(c.ConstantinopleBlock, num) 162 } 163 164 // IsIstanbul returns whether num is either equal to the Istanbul fork block or greater. 165 func (c *Config) IsIstanbul(num uint64) bool { 166 return isForked(c.IstanbulBlock, num) 167 } 168 169 // IsBerlin returns whether num is either equal to the Berlin fork block or greater. 170 func (c *Config) IsBerlin(num uint64) bool { 171 return isForked(c.BerlinBlock, num) 172 } 173 174 // IsLondon returns whether num is either equal to the London fork block or greater. 175 func (c *Config) IsLondon(num uint64) bool { 176 return isForked(c.LondonBlock, num) 177 } 178 179 // IsArrowGlacier returns whether num is either equal to the Arrow Glacier (EIP-4345) fork block or greater. 180 func (c *Config) IsArrowGlacier(num uint64) bool { 181 return isForked(c.ArrowGlacierBlock, num) 182 } 183 184 // IsGrayGlacier returns whether num is either equal to the Gray Glacier (EIP-5133) fork block or greater. 185 func (c *Config) IsGrayGlacier(num uint64) bool { 186 return isForked(c.GrayGlacierBlock, num) 187 } 188 189 // IsShanghai returns whether time is either equal to the Shanghai fork time or greater. 190 func (c *Config) IsShanghai(time uint64) bool { 191 return isForked(c.ShanghaiTime, time) 192 } 193 194 // IsCancun returns whether time is either equal to the Cancun fork time or greater. 195 func (c *Config) IsCancun(time uint64) bool { 196 return isForked(c.CancunTime, time) 197 } 198 199 // IsPrague returns whether time is either equal to the Prague fork time or greater. 200 func (c *Config) IsPrague(time uint64) bool { 201 return isForked(c.PragueTime, time) 202 } 203 204 func (c *Config) IsEip1559FeeCollector(num uint64) bool { 205 return c.Eip1559FeeCollector != nil && isForked(c.Eip1559FeeCollectorTransition, num) 206 } 207 208 // CheckCompatible checks whether scheduled fork transitions have been imported 209 // with a mismatching chain configuration. 210 func (c *Config) CheckCompatible(newcfg *Config, height uint64) *ConfigCompatError { 211 bhead := height 212 213 // Iterate checkCompatible to find the lowest conflict. 214 var lasterr *ConfigCompatError 215 for { 216 err := c.checkCompatible(newcfg, bhead) 217 if err == nil || (lasterr != nil && err.RewindTo == lasterr.RewindTo) { 218 break 219 } 220 lasterr = err 221 bhead = err.RewindTo 222 } 223 return lasterr 224 } 225 226 type forkBlockNumber struct { 227 name string 228 blockNumber *big.Int 229 optional bool // if true, the fork may be nil and next fork is still allowed 230 } 231 232 func (c *Config) forkBlockNumbers() []forkBlockNumber { 233 return []forkBlockNumber{ 234 {name: "homesteadBlock", blockNumber: c.HomesteadBlock}, 235 {name: "daoForkBlock", blockNumber: c.DAOForkBlock, optional: true}, 236 {name: "eip150Block", blockNumber: c.TangerineWhistleBlock}, 237 {name: "eip155Block", blockNumber: c.SpuriousDragonBlock}, 238 {name: "byzantiumBlock", blockNumber: c.ByzantiumBlock}, 239 {name: "constantinopleBlock", blockNumber: c.ConstantinopleBlock}, 240 {name: "petersburgBlock", blockNumber: c.PetersburgBlock}, 241 {name: "istanbulBlock", blockNumber: c.IstanbulBlock}, 242 {name: "muirGlacierBlock", blockNumber: c.MuirGlacierBlock, optional: true}, 243 {name: "berlinBlock", blockNumber: c.BerlinBlock}, 244 {name: "londonBlock", blockNumber: c.LondonBlock}, 245 {name: "arrowGlacierBlock", blockNumber: c.ArrowGlacierBlock, optional: true}, 246 {name: "grayGlacierBlock", blockNumber: c.GrayGlacierBlock, optional: true}, 247 {name: "mergeNetsplitBlock", blockNumber: c.MergeNetsplitBlock, optional: true}, 248 } 249 } 250 251 // CheckConfigForkOrder checks that we don't "skip" any forks 252 func (c *Config) CheckConfigForkOrder() error { 253 if c != nil && c.ChainID != nil && c.ChainID.Uint64() == 77 { 254 return nil 255 } 256 257 var lastFork forkBlockNumber 258 259 for _, fork := range c.forkBlockNumbers() { 260 if lastFork.name != "" { 261 // Next one must be higher number 262 if lastFork.blockNumber == nil && fork.blockNumber != nil { 263 return fmt.Errorf("unsupported fork ordering: %v not enabled, but %v enabled at %v", 264 lastFork.name, fork.name, fork.blockNumber) 265 } 266 if lastFork.blockNumber != nil && fork.blockNumber != nil { 267 if lastFork.blockNumber.Cmp(fork.blockNumber) > 0 { 268 return fmt.Errorf("unsupported fork ordering: %v enabled at %v, but %v enabled at %v", 269 lastFork.name, lastFork.blockNumber, fork.name, fork.blockNumber) 270 } 271 } 272 // If it was optional and not set, then ignore it 273 } 274 if !fork.optional || fork.blockNumber != nil { 275 lastFork = fork 276 } 277 } 278 return nil 279 } 280 281 func (c *Config) checkCompatible(newcfg *Config, head uint64) *ConfigCompatError { 282 // returns true if a fork scheduled at s1 cannot be rescheduled to block s2 because head is already past the fork. 283 incompatible := func(s1, s2 *big.Int, head uint64) bool { 284 return (isForked(s1, head) || isForked(s2, head)) && !numEqual(s1, s2) 285 } 286 287 // Ethereum mainnet forks 288 if incompatible(c.HomesteadBlock, newcfg.HomesteadBlock, head) { 289 return newCompatError("Homestead fork block", c.HomesteadBlock, newcfg.HomesteadBlock) 290 } 291 if incompatible(c.DAOForkBlock, newcfg.DAOForkBlock, head) { 292 return newCompatError("DAO fork block", c.DAOForkBlock, newcfg.DAOForkBlock) 293 } 294 if incompatible(c.TangerineWhistleBlock, newcfg.TangerineWhistleBlock, head) { 295 return newCompatError("Tangerine Whistle fork block", c.TangerineWhistleBlock, newcfg.TangerineWhistleBlock) 296 } 297 if incompatible(c.SpuriousDragonBlock, newcfg.SpuriousDragonBlock, head) { 298 return newCompatError("Spurious Dragon fork block", c.SpuriousDragonBlock, newcfg.SpuriousDragonBlock) 299 } 300 if c.IsSpuriousDragon(head) && !numEqual(c.ChainID, newcfg.ChainID) { 301 return newCompatError("EIP155 chain ID", c.SpuriousDragonBlock, newcfg.SpuriousDragonBlock) 302 } 303 if incompatible(c.ByzantiumBlock, newcfg.ByzantiumBlock, head) { 304 return newCompatError("Byzantium fork block", c.ByzantiumBlock, newcfg.ByzantiumBlock) 305 } 306 if incompatible(c.ConstantinopleBlock, newcfg.ConstantinopleBlock, head) { 307 return newCompatError("Constantinople fork block", c.ConstantinopleBlock, newcfg.ConstantinopleBlock) 308 } 309 if incompatible(c.PetersburgBlock, newcfg.PetersburgBlock, head) { 310 // the only case where we allow Petersburg to be set in the past is if it is equal to Constantinople 311 // mainly to satisfy fork ordering requirements which state that Petersburg fork be set if Constantinople fork is set 312 if incompatible(c.ConstantinopleBlock, newcfg.PetersburgBlock, head) { 313 return newCompatError("Petersburg fork block", c.PetersburgBlock, newcfg.PetersburgBlock) 314 } 315 } 316 if incompatible(c.IstanbulBlock, newcfg.IstanbulBlock, head) { 317 return newCompatError("Istanbul fork block", c.IstanbulBlock, newcfg.IstanbulBlock) 318 } 319 if incompatible(c.MuirGlacierBlock, newcfg.MuirGlacierBlock, head) { 320 return newCompatError("Muir Glacier fork block", c.MuirGlacierBlock, newcfg.MuirGlacierBlock) 321 } 322 if incompatible(c.BerlinBlock, newcfg.BerlinBlock, head) { 323 return newCompatError("Berlin fork block", c.BerlinBlock, newcfg.BerlinBlock) 324 } 325 if incompatible(c.LondonBlock, newcfg.LondonBlock, head) { 326 return newCompatError("London fork block", c.LondonBlock, newcfg.LondonBlock) 327 } 328 if incompatible(c.ArrowGlacierBlock, newcfg.ArrowGlacierBlock, head) { 329 return newCompatError("Arrow Glacier fork block", c.ArrowGlacierBlock, newcfg.ArrowGlacierBlock) 330 } 331 if incompatible(c.GrayGlacierBlock, newcfg.GrayGlacierBlock, head) { 332 return newCompatError("Gray Glacier fork block", c.GrayGlacierBlock, newcfg.GrayGlacierBlock) 333 } 334 if incompatible(c.MergeNetsplitBlock, newcfg.MergeNetsplitBlock, head) { 335 return newCompatError("Merge netsplit block", c.MergeNetsplitBlock, newcfg.MergeNetsplitBlock) 336 } 337 338 return nil 339 } 340 341 func numEqual(x, y *big.Int) bool { 342 if x == nil { 343 return y == nil 344 } 345 if y == nil { 346 return x == nil 347 } 348 return x.Cmp(y) == 0 349 } 350 351 // ConfigCompatError is raised if the locally-stored blockchain is initialised with a 352 // ChainConfig that would alter the past. 353 type ConfigCompatError struct { 354 What string 355 // block numbers of the stored and new configurations 356 StoredConfig, NewConfig *big.Int 357 // the block number to which the local chain must be rewound to correct the error 358 RewindTo uint64 359 } 360 361 func newCompatError(what string, storedblock, newblock *big.Int) *ConfigCompatError { 362 var rew *big.Int 363 switch { 364 case storedblock == nil: 365 rew = newblock 366 case newblock == nil || storedblock.Cmp(newblock) < 0: 367 rew = storedblock 368 default: 369 rew = newblock 370 } 371 err := &ConfigCompatError{what, storedblock, newblock, 0} 372 if rew != nil && rew.Sign() > 0 { 373 err.RewindTo = rew.Uint64() - 1 374 } 375 return err 376 } 377 378 func (err *ConfigCompatError) Error() string { 379 return fmt.Sprintf("mismatching %s in database (have %d, want %d, rewindto %d)", err.What, err.StoredConfig, err.NewConfig, err.RewindTo) 380 } 381 382 // EthashConfig is the consensus engine configs for proof-of-work based sealing. 383 type EthashConfig struct{} 384 385 // String implements the stringer interface, returning the consensus engine details. 386 func (c *EthashConfig) String() string { 387 return "ethash" 388 } 389 390 // CliqueConfig is the consensus engine configs for proof-of-authority based sealing. 391 type CliqueConfig struct { 392 Period uint64 `json:"period"` // Number of seconds between blocks to enforce 393 Epoch uint64 `json:"epoch"` // Epoch length to reset votes and checkpoint 394 } 395 396 // String implements the stringer interface, returning the consensus engine details. 397 func (c *CliqueConfig) String() string { 398 return "clique" 399 } 400 401 // BorConfig is the consensus engine configs for Matic bor based sealing. 402 type BorConfig struct { 403 Period map[string]uint64 `json:"period"` // Number of seconds between blocks to enforce 404 ProducerDelay map[string]uint64 `json:"producerDelay"` // Number of seconds delay between two producer interval 405 Sprint map[string]uint64 `json:"sprint"` // Epoch length to proposer 406 BackupMultiplier map[string]uint64 `json:"backupMultiplier"` // Backup multiplier to determine the wiggle time 407 ValidatorContract string `json:"validatorContract"` // Validator set contract 408 StateReceiverContract string `json:"stateReceiverContract"` // State receiver contract 409 410 OverrideStateSyncRecords map[string]int `json:"overrideStateSyncRecords"` // override state records count 411 BlockAlloc map[string]interface{} `json:"blockAlloc"` 412 413 CalcuttaBlock *big.Int `json:"calcuttaBlock"` // Calcutta switch block (nil = no fork, 0 = already on calcutta) 414 JaipurBlock *big.Int `json:"jaipurBlock"` // Jaipur switch block (nil = no fork, 0 = already on jaipur) 415 DelhiBlock *big.Int `json:"delhiBlock"` // Delhi switch block (nil = no fork, 0 = already on delhi) 416 417 IndoreBlock *big.Int `json:"indoreBlock"` // Indore switch block (nil = no fork, 0 = already on indore) 418 StateSyncConfirmationDelay map[string]uint64 `json:"stateSyncConfirmationDelay"` // StateSync Confirmation Delay, in seconds, to calculate `to` 419 420 sprints sprints 421 } 422 423 // String implements the stringer interface, returning the consensus engine details. 424 func (b *BorConfig) String() string { 425 return "bor" 426 } 427 428 func (c *BorConfig) CalculateProducerDelay(number uint64) uint64 { 429 return borKeyValueConfigHelper(c.ProducerDelay, number) 430 } 431 432 func (c *BorConfig) CalculateSprint(number uint64) uint64 { 433 if c.sprints == nil { 434 c.sprints = asSprints(c.Sprint) 435 } 436 437 for i := 0; i < len(c.sprints)-1; i++ { 438 if number >= c.sprints[i].from && number < c.sprints[i+1].from { 439 return c.sprints[i].size 440 } 441 } 442 443 return c.sprints[len(c.sprints)-1].size 444 } 445 446 func (c *BorConfig) CalculateSprintCount(from, to uint64) int { 447 switch { 448 case from > to: 449 return 0 450 case from < to: 451 to-- 452 } 453 454 if c.sprints == nil { 455 c.sprints = asSprints(c.Sprint) 456 } 457 458 count := uint64(0) 459 startCalc := from 460 461 zeroth := func(boundary uint64, size uint64) uint64 { 462 if boundary%size == 0 { 463 return 1 464 } 465 466 return 0 467 } 468 469 for i := 0; i < len(c.sprints)-1; i++ { 470 if startCalc >= c.sprints[i].from && startCalc < c.sprints[i+1].from { 471 if to >= c.sprints[i].from && to < c.sprints[i+1].from { 472 if startCalc == to { 473 return int(count + zeroth(startCalc, c.sprints[i].size)) 474 } 475 return int(count + zeroth(startCalc, c.sprints[i].size) + (to-startCalc)/c.sprints[i].size) 476 } else { 477 endCalc := c.sprints[i+1].from - 1 478 count += zeroth(startCalc, c.sprints[i].size) + (endCalc-startCalc)/c.sprints[i].size 479 startCalc = endCalc + 1 480 } 481 } 482 } 483 484 if startCalc == to { 485 return int(count + zeroth(startCalc, c.sprints[len(c.sprints)-1].size)) 486 } 487 488 return int(count + zeroth(startCalc, c.sprints[len(c.sprints)-1].size) + (to-startCalc)/c.sprints[len(c.sprints)-1].size) 489 } 490 491 func (c *BorConfig) CalculateBackupMultiplier(number uint64) uint64 { 492 return c.calcConfig(c.BackupMultiplier, number) 493 } 494 495 func (c *BorConfig) CalculatePeriod(number uint64) uint64 { 496 return c.calcConfig(c.Period, number) 497 } 498 499 func (c *BorConfig) IsJaipur(number uint64) bool { 500 return isForked(c.JaipurBlock, number) 501 } 502 503 func (c *BorConfig) IsDelhi(number uint64) bool { 504 return isForked(c.DelhiBlock, number) 505 } 506 507 func (c *BorConfig) IsCalcutta(number uint64) bool { 508 return isForked(c.CalcuttaBlock, number) 509 } 510 511 func (c *BorConfig) IsOnCalcutta(number *big.Int) bool { 512 return numEqual(c.CalcuttaBlock, number) 513 } 514 515 func (c *BorConfig) IsIndore(number uint64) bool { 516 return isForked(c.IndoreBlock, number) 517 } 518 519 func (c *BorConfig) CalculateStateSyncDelay(number uint64) uint64 { 520 return borKeyValueConfigHelper(c.StateSyncConfirmationDelay, number) 521 } 522 523 func (c *BorConfig) calcConfig(field map[string]uint64, number uint64) uint64 { 524 keys := sortMapKeys(field) 525 for i := 0; i < len(keys)-1; i++ { 526 valUint, _ := strconv.ParseUint(keys[i], 10, 64) 527 valUintNext, _ := strconv.ParseUint(keys[i+1], 10, 64) 528 if number > valUint && number < valUintNext { 529 return field[keys[i]] 530 } 531 } 532 return field[keys[len(keys)-1]] 533 } 534 535 func borKeyValueConfigHelper(field map[string]uint64, number uint64) uint64 { 536 keys := sortMapKeys(field) 537 for i := 0; i < len(keys)-1; i++ { 538 valUint, _ := strconv.ParseUint(keys[i], 10, 64) 539 valUintNext, _ := strconv.ParseUint(keys[i+1], 10, 64) 540 541 if number >= valUint && number < valUintNext { 542 return field[keys[i]] 543 } 544 } 545 546 return field[keys[len(keys)-1]] 547 } 548 549 func sortMapKeys(m map[string]uint64) []string { 550 keys := make([]string, 0, len(m)) 551 for k := range m { 552 keys = append(keys, k) 553 } 554 sort.Strings(keys) 555 556 return keys 557 } 558 559 type sprint struct { 560 from, size uint64 561 } 562 563 type sprints []sprint 564 565 func (s sprints) Len() int { 566 return len(s) 567 } 568 569 func (s sprints) Swap(i, j int) { 570 s[i], s[j] = s[j], s[i] 571 } 572 573 func (s sprints) Less(i, j int) bool { 574 return s[i].from < s[j].from 575 } 576 577 func asSprints(configSprints map[string]uint64) sprints { 578 sprints := make(sprints, len(configSprints)) 579 580 i := 0 581 for key, value := range configSprints { 582 sprints[i].from, _ = strconv.ParseUint(key, 10, 64) 583 sprints[i].size = value 584 i++ 585 } 586 587 sort.Sort(sprints) 588 589 return sprints 590 } 591 592 // Rules is syntactic sugar over Config. It can be used for functions 593 // that do not have or require information about the block. 594 // 595 // Rules is a one time interface meaning that it shouldn't be used in between transition 596 // phases. 597 type Rules struct { 598 ChainID *big.Int 599 IsHomestead, IsTangerineWhistle, IsSpuriousDragon bool 600 IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool 601 IsBerlin, IsLondon, IsShanghai, IsCancun, IsPrague bool 602 IsEip1559FeeCollector, IsAura bool 603 } 604 605 // Rules ensures c's ChainID is not nil and returns a new Rules instance 606 func (c *Config) Rules(num uint64, time uint64) *Rules { 607 chainID := c.ChainID 608 if chainID == nil { 609 chainID = new(big.Int) 610 } 611 612 return &Rules{ 613 ChainID: new(big.Int).Set(chainID), 614 IsHomestead: c.IsHomestead(num), 615 IsTangerineWhistle: c.IsTangerineWhistle(num), 616 IsSpuriousDragon: c.IsSpuriousDragon(num), 617 IsByzantium: c.IsByzantium(num), 618 IsConstantinople: c.IsConstantinople(num), 619 IsPetersburg: c.IsPetersburg(num), 620 IsIstanbul: c.IsIstanbul(num), 621 IsBerlin: c.IsBerlin(num), 622 IsLondon: c.IsLondon(num), 623 IsShanghai: c.IsShanghai(time), 624 IsCancun: c.IsCancun(time), 625 IsPrague: c.IsPrague(time), 626 IsEip1559FeeCollector: c.IsEip1559FeeCollector(num), 627 IsAura: c.Aura != nil, 628 } 629 } 630 631 // isForked returns whether a fork scheduled at block s is active at the given head block. 632 func isForked(s *big.Int, head uint64) bool { 633 if s == nil { 634 return false 635 } 636 return s.Uint64() <= head 637 }