mirror of
https://github.com/status-im/nimbus-eth1.git
synced 2025-02-23 09:18:29 +00:00
Fix ForkID calculation
This commit is contained in:
parent
6e59cccc5b
commit
0ee448c1eb
@ -262,10 +262,6 @@ proc toHardFork*(map: ForkTransitionTable, forkDeterminer: ForkDeterminationInfo
|
|||||||
# should always have a match
|
# should always have a match
|
||||||
doAssert(false, "unreachable code")
|
doAssert(false, "unreachable code")
|
||||||
|
|
||||||
func forkDeterminationInfoForHeader*(header: BlockHeader): ForkDeterminationInfo =
|
|
||||||
# FIXME-Adam-mightAlsoNeedTTD?
|
|
||||||
forkDeterminationInfo(header.blockNumber, header.timestamp)
|
|
||||||
|
|
||||||
proc validateChainConfig*(conf: ChainConfig): bool =
|
proc validateChainConfig*(conf: ChainConfig): bool =
|
||||||
result = true
|
result = true
|
||||||
|
|
||||||
@ -448,6 +444,7 @@ proc chainConfigForNetwork*(id: NetworkId): ChainConfig =
|
|||||||
muirGlacierBlock: some(0.toBlockNumber),
|
muirGlacierBlock: some(0.toBlockNumber),
|
||||||
berlinBlock: some(0.toBlockNumber),
|
berlinBlock: some(0.toBlockNumber),
|
||||||
londonBlock: some(0.toBlockNumber),
|
londonBlock: some(0.toBlockNumber),
|
||||||
|
mergeForkBlock: some(1735371.toBlockNumber),
|
||||||
terminalTotalDifficulty: some(sepoliaTTD),
|
terminalTotalDifficulty: some(sepoliaTTD),
|
||||||
shanghaiTime: some(1_677_557_088.EthTime)
|
shanghaiTime: some(1_677_557_088.EthTime)
|
||||||
)
|
)
|
||||||
|
@ -58,7 +58,7 @@ type
|
|||||||
forkTransitionTable: ForkTransitionTable
|
forkTransitionTable: ForkTransitionTable
|
||||||
|
|
||||||
# Eth wire protocol need this
|
# Eth wire protocol need this
|
||||||
forkIds: array[HardFork, ForkID]
|
forkIdCalculator: ForkIdCalculator
|
||||||
networkId: NetworkId
|
networkId: NetworkId
|
||||||
|
|
||||||
# synchronizer need this
|
# synchronizer need this
|
||||||
@ -117,10 +117,13 @@ proc consensusTransition(com: CommonRef, fork: HardFork) =
|
|||||||
# this could happen during reorg
|
# this could happen during reorg
|
||||||
com.consensusType = com.config.consensusType
|
com.consensusType = com.config.consensusType
|
||||||
|
|
||||||
proc setForkId(com: CommonRef, blockZero: BlockHeader) =
|
proc setForkId(com: CommonRef, genesis: BlockHeader) =
|
||||||
com.genesisHash = blockZero.blockHash
|
com.genesisHash = genesis.blockHash
|
||||||
let genesisCRC = crc32(0, com.genesisHash.data)
|
let genesisCRC = crc32(0, com.genesisHash.data)
|
||||||
com.forkIds = calculateForkIds(com.config, genesisCRC)
|
com.forkIdCalculator = initForkIdCalculator(
|
||||||
|
com.forkTransitionTable,
|
||||||
|
genesisCRC,
|
||||||
|
genesis.timestamp.uint64)
|
||||||
|
|
||||||
proc daoCheck(conf: ChainConfig) =
|
proc daoCheck(conf: ChainConfig) =
|
||||||
if not conf.daoForkSupport or conf.daoForkBlock.isNone:
|
if not conf.daoForkSupport or conf.daoForkBlock.isNone:
|
||||||
@ -160,7 +163,7 @@ proc init(com : CommonRef,
|
|||||||
# already at the MergeFork
|
# already at the MergeFork
|
||||||
const TimeZero = EthTime(0)
|
const TimeZero = EthTime(0)
|
||||||
|
|
||||||
# com.forkIds and com.blockZeroHash is set
|
# com.forkIdCalculator and com.genesisHash are set
|
||||||
# by setForkId
|
# by setForkId
|
||||||
if genesis.isNil.not:
|
if genesis.isNil.not:
|
||||||
com.hardForkTransition(ForkDeterminationInfo(
|
com.hardForkTransition(ForkDeterminationInfo(
|
||||||
@ -246,7 +249,7 @@ proc clone*(com: CommonRef, db: CoreDbRef): CommonRef =
|
|||||||
pruneTrie : com.pruneTrie,
|
pruneTrie : com.pruneTrie,
|
||||||
config : com.config,
|
config : com.config,
|
||||||
forkTransitionTable: com.forkTransitionTable,
|
forkTransitionTable: com.forkTransitionTable,
|
||||||
forkIds : com.forkIds,
|
forkIdCalculator: com.forkIdCalculator,
|
||||||
genesisHash : com.genesisHash,
|
genesisHash : com.genesisHash,
|
||||||
genesisHeader: com.genesisHeader,
|
genesisHeader: com.genesisHeader,
|
||||||
syncProgress : com.syncProgress,
|
syncProgress : com.syncProgress,
|
||||||
@ -315,7 +318,7 @@ func toEVMFork*(com: CommonRef): EVMFork =
|
|||||||
|
|
||||||
func isLondon*(com: CommonRef, number: BlockNumber): bool =
|
func isLondon*(com: CommonRef, number: BlockNumber): bool =
|
||||||
# TODO: Fixme, use only London comparator
|
# TODO: Fixme, use only London comparator
|
||||||
com.toHardFork(number.blockNumberToForkDeterminationInfo) >= London
|
com.toHardFork(number.forkDeterminationInfo) >= London
|
||||||
|
|
||||||
func isLondon*(com: CommonRef, number: BlockNumber, timestamp: EthTime): bool =
|
func isLondon*(com: CommonRef, number: BlockNumber, timestamp: EthTime): bool =
|
||||||
# TODO: Fixme, use only London comparator
|
# TODO: Fixme, use only London comparator
|
||||||
@ -339,10 +342,13 @@ proc minerAddress*(com: CommonRef; header: BlockHeader): EthAddress
|
|||||||
|
|
||||||
account.value
|
account.value
|
||||||
|
|
||||||
func forkId*(com: CommonRef, forkDeterminer: ForkDeterminationInfo): ForkID {.gcsafe.} =
|
func forkId*(com: CommonRef, head, time: uint64): ForkID {.gcsafe.} =
|
||||||
## EIP 2364/2124
|
## EIP 2364/2124
|
||||||
let fork = com.toHardFork(forkDeterminer)
|
com.forkIdCalculator.newID(head, time)
|
||||||
com.forkIds[fork]
|
|
||||||
|
func forkId*(com: CommonRef, head: BlockNumber, time: EthTime): ForkID {.gcsafe.} =
|
||||||
|
## EIP 2364/2124
|
||||||
|
com.forkIdCalculator.newID(head.truncate(uint64), time.uint64)
|
||||||
|
|
||||||
func isEIP155*(com: CommonRef, number: BlockNumber): bool =
|
func isEIP155*(com: CommonRef, number: BlockNumber): bool =
|
||||||
com.config.eip155Block.isSome and number >= com.config.eip155Block.get
|
com.config.eip155Block.isSome and number >= com.config.eip155Block.get
|
||||||
|
@ -84,13 +84,13 @@ type
|
|||||||
# is because it's perfectly fine, if mergeForkBlock is
|
# is because it's perfectly fine, if mergeForkBlock is
|
||||||
# set, to not bother with TTD anymore. But I'm not sure
|
# set, to not bother with TTD anymore. But I'm not sure
|
||||||
# it makes sense to allow time to be optional. See the
|
# it makes sense to allow time to be optional. See the
|
||||||
# comment below on blockNumberToForkDeterminationInfo.
|
# comment below on forkDeterminationInfo.
|
||||||
ForkDeterminationInfo* = object
|
ForkDeterminationInfo* = object
|
||||||
blockNumber*: BlockNumber
|
blockNumber*: BlockNumber
|
||||||
time*: Option[EthTime]
|
time*: Option[EthTime]
|
||||||
td*: Option[DifficultyInt]
|
td*: Option[DifficultyInt]
|
||||||
|
|
||||||
func blockNumberToForkDeterminationInfo*(n: BlockNumber): ForkDeterminationInfo =
|
func forkDeterminationInfo*(n: BlockNumber): ForkDeterminationInfo =
|
||||||
# FIXME: All callers of this function are suspect; I'm guess we should
|
# FIXME: All callers of this function are suspect; I'm guess we should
|
||||||
# always be using both block number and time. But we have a few places,
|
# always be using both block number and time. But we have a few places,
|
||||||
# like various tests, where we only have block number and the tests are
|
# like various tests, where we only have block number and the tests are
|
||||||
@ -104,6 +104,10 @@ func forkDeterminationInfo*(n: BlockNumber, t: EthTime): ForkDeterminationInfo =
|
|||||||
func forkDeterminationInfoIncludingTd*(n: BlockNumber, t: EthTime, td: DifficultyInt): ForkDeterminationInfo =
|
func forkDeterminationInfoIncludingTd*(n: BlockNumber, t: EthTime, td: DifficultyInt): ForkDeterminationInfo =
|
||||||
ForkDeterminationInfo(blockNumber: n, time: some(t), td: some(td))
|
ForkDeterminationInfo(blockNumber: n, time: some(t), td: some(td))
|
||||||
|
|
||||||
|
func forkDeterminationInfo*(header: BlockHeader): ForkDeterminationInfo =
|
||||||
|
# FIXME-Adam-mightAlsoNeedTTD?
|
||||||
|
forkDeterminationInfo(header.blockNumber, header.timestamp)
|
||||||
|
|
||||||
proc adjustForNextBlock*(n: BlockNumber): BlockNumber =
|
proc adjustForNextBlock*(n: BlockNumber): BlockNumber =
|
||||||
n + 1
|
n + 1
|
||||||
|
|
||||||
@ -343,72 +347,74 @@ const
|
|||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Fork ID helpers
|
# Fork ID helpers
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
type
|
||||||
|
ForkIdCalculator* = object
|
||||||
|
byBlock: seq[uint64]
|
||||||
|
byTime: seq[uint64]
|
||||||
|
genesisCRC: uint32
|
||||||
|
|
||||||
func toNextFork(n: Option[BlockNumber]): uint64 =
|
func newID*(calc: ForkIdCalculator, head, time: uint64): ForkID =
|
||||||
if n.isSome:
|
var hash = calc.genesisCRC
|
||||||
n.get.truncate(uint64)
|
for fork in calc.byBlock:
|
||||||
else:
|
if fork <= head:
|
||||||
0'u64
|
# Fork already passed, checksum the previous hash and the fork number
|
||||||
|
hash = crc32(hash, fork.toBytesBE)
|
||||||
|
continue
|
||||||
|
return (hash, fork)
|
||||||
|
|
||||||
# EIP-6122: ForkID now works with timestamps too.
|
for fork in calc.byTime:
|
||||||
func toNextFork(t: Option[EthTime]): uint64 =
|
if fork <= time:
|
||||||
if t.isSome:
|
# Fork already passed, checksum the previous hash and fork timestamp
|
||||||
t.get.uint64
|
hash = crc32(hash, fork.toBytesBE)
|
||||||
else:
|
continue
|
||||||
0'u64
|
return (hash, fork)
|
||||||
|
|
||||||
func arrayMappingHardForkToNextFork(c: ChainConfig): array[HardFork, uint64] =
|
(hash, 0'u64)
|
||||||
return [
|
|
||||||
0'u64,
|
|
||||||
toNextFork(c.homesteadBlock),
|
|
||||||
toNextFork(c.daoForkBlock),
|
|
||||||
toNextFork(c.eip150Block),
|
|
||||||
toNextFork(c.eip158Block),
|
|
||||||
toNextFork(c.byzantiumBlock),
|
|
||||||
toNextFork(c.constantinopleBlock),
|
|
||||||
toNextFork(c.petersburgBlock),
|
|
||||||
toNextFork(c.istanbulBlock),
|
|
||||||
toNextFork(c.muirGlacierBlock),
|
|
||||||
toNextFork(c.berlinBlock),
|
|
||||||
toNextFork(c.londonBlock),
|
|
||||||
toNextFork(c.arrowGlacierBlock),
|
|
||||||
toNextFork(c.grayGlacierBlock),
|
|
||||||
toNextFork(c.mergeForkBlock),
|
|
||||||
toNextFork(c.shanghaiTime),
|
|
||||||
toNextFork(c.cancunTime),
|
|
||||||
]
|
|
||||||
|
|
||||||
func getNextFork(next: array[HardFork, uint64], fork: HardFork): uint64 =
|
func initForkIdCalculator*(map: ForkTransitionTable,
|
||||||
if fork == high(HardFork):
|
genesisCRC: uint32,
|
||||||
result = 0
|
genesisTime: uint64): ForkIdCalculator =
|
||||||
return
|
|
||||||
|
|
||||||
result = next[fork]
|
# Extract the fork rule block number aggregate it
|
||||||
for x in fork..high(HardFork):
|
var forksByBlock: seq[uint64]
|
||||||
if result != next[x]:
|
for fork, val in map.blockNumberThresholds:
|
||||||
result = next[x]
|
if val.isNone: continue
|
||||||
break
|
let val64 = val.get.truncate(uint64)
|
||||||
|
if forksByBlock.len == 0:
|
||||||
|
forksByBlock.add val64
|
||||||
|
elif forksByBlock[^1] != val64:
|
||||||
|
# Deduplicate fork identifiers applying multiple forks
|
||||||
|
forksByBlock.add val64
|
||||||
|
|
||||||
func calculateForkId(next: array[HardFork, uint64], fork: HardFork,
|
if map.mergeForkTransitionThreshold.blockNumber.isSome:
|
||||||
prevCRC: uint32, prevFork: uint64): ForkID =
|
let val64 = map.mergeForkTransitionThreshold.blockNumber.get.truncate(uint64)
|
||||||
result.nextFork = getNextFork(next, fork)
|
if forksByBlock.len == 0:
|
||||||
|
forksByBlock.add val64
|
||||||
|
elif forksByBlock[^1] != val64:
|
||||||
|
# Deduplicate fork identifiers applying multiple forks
|
||||||
|
forksByBlock.add val64
|
||||||
|
|
||||||
if result.nextFork != prevFork:
|
# Skip any forks in block 0, that's the genesis ruleset
|
||||||
result.crc = crc32(prevCRC, toBytesBE(prevFork))
|
if forksByBlock.len > 0 and forksByBlock[0] == 0:
|
||||||
else:
|
forksByBlock.delete(0)
|
||||||
result.crc = prevCRC
|
|
||||||
|
|
||||||
func calculateForkIds*(c: ChainConfig,
|
# Extract the fork rule timestamp number aggregate it
|
||||||
genesisCRC: uint32): array[HardFork, ForkID] =
|
var forksByTime: seq[uint64]
|
||||||
let next = arrayMappingHardForkToNextFork(c)
|
for fork, val in map.timeThresholds:
|
||||||
|
if val.isNone: continue
|
||||||
|
let val64 = val.get.uint64
|
||||||
|
if forksByTime.len == 0:
|
||||||
|
forksByTime.add val64
|
||||||
|
elif forksByTime[^1] != val64:
|
||||||
|
forksByTime.add val64
|
||||||
|
|
||||||
var prevCRC = genesisCRC
|
# Skip any forks before genesis.
|
||||||
var prevFork = getNextFork(next, Frontier)
|
while forksByTime.len > 0 and forksByTime[0] <= genesisTime:
|
||||||
|
forksByTime.delete(0)
|
||||||
|
|
||||||
for fork in HardFork:
|
result.genesisCRC = genesisCRC
|
||||||
result[fork] = calculateForkId(next, fork, prevCRC, prevFork)
|
result.byBlock = system.move(forksByBlock)
|
||||||
prevFork = result[fork].nextFork
|
result.byTime = system.move(forksByTime)
|
||||||
prevCRC = result[fork].crc
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# End
|
# End
|
||||||
|
@ -182,7 +182,7 @@ proc asyncProcessTransaction*(
|
|||||||
{.async, gcsafe.} =
|
{.async, gcsafe.} =
|
||||||
## Variant of `asyncProcessTransaction()` with `*fork* derived
|
## Variant of `asyncProcessTransaction()` with `*fork* derived
|
||||||
## from the `vmState` argument.
|
## from the `vmState` argument.
|
||||||
let fork = vmState.com.toEVMFork(header.forkDeterminationInfoForHeader)
|
let fork = vmState.com.toEVMFork(header.forkDeterminationInfo)
|
||||||
return await vmState.asyncProcessTransaction(tx, sender, header, fork)
|
return await vmState.asyncProcessTransaction(tx, sender, header, fork)
|
||||||
|
|
||||||
proc processTransaction*(
|
proc processTransaction*(
|
||||||
|
@ -171,7 +171,7 @@ template calcDifficultyGrayGlacier*(timeStamp: EthTime, parent: BlockHeader): Di
|
|||||||
makeDifficultyCalculator(11_400_000, timeStamp, parent)
|
makeDifficultyCalculator(11_400_000, timeStamp, parent)
|
||||||
|
|
||||||
func calcDifficulty*(com: CommonRef, timeStamp: EthTime, parent: BlockHeader): DifficultyInt =
|
func calcDifficulty*(com: CommonRef, timeStamp: EthTime, parent: BlockHeader): DifficultyInt =
|
||||||
let next = com.toHardFork(parent.forkDeterminationInfoForHeader.adjustForNextBlock)
|
let next = com.toHardFork(parent.forkDeterminationInfo.adjustForNextBlock)
|
||||||
if next >= GrayGlacier:
|
if next >= GrayGlacier:
|
||||||
result = calcDifficultyGrayGlacier(timeStamp, parent)
|
result = calcDifficultyGrayGlacier(timeStamp, parent)
|
||||||
elif next >= ArrowGlacier:
|
elif next >= ArrowGlacier:
|
||||||
|
@ -35,7 +35,7 @@ proc baseFeeGet*(com: CommonRef; parent: BlockHeader): GasPrice =
|
|||||||
|
|
||||||
# Note that the baseFee is calculated for the next header
|
# Note that the baseFee is calculated for the next header
|
||||||
let
|
let
|
||||||
forkDeterminer = forkDeterminationInfoForHeader(parent)
|
forkDeterminer = forkDeterminationInfo(parent)
|
||||||
parentFork = com.toEVMFork(forkDeterminer)
|
parentFork = com.toEVMFork(forkDeterminer)
|
||||||
nextFork = com.toEVMFork(forkDeterminer.adjustForNextBlock)
|
nextFork = com.toEVMFork(forkDeterminer.adjustForNextBlock)
|
||||||
|
|
||||||
|
@ -392,7 +392,7 @@ method getStatus*(ctx: EthWireRef): EthState
|
|||||||
db = ctx.db
|
db = ctx.db
|
||||||
com = ctx.chain.com
|
com = ctx.chain.com
|
||||||
bestBlock = db.getCanonicalHead()
|
bestBlock = db.getCanonicalHead()
|
||||||
forkId = com.forkId(bestBlock.forkDeterminationInfoForHeader)
|
forkId = com.forkId(bestBlock.blockNumber, bestBlock.timestamp)
|
||||||
|
|
||||||
EthState(
|
EthState(
|
||||||
totalDifficulty: db.headTotalDifficulty,
|
totalDifficulty: db.headTotalDifficulty,
|
||||||
@ -400,7 +400,7 @@ method getStatus*(ctx: EthWireRef): EthState
|
|||||||
bestBlockHash: bestBlock.blockHash,
|
bestBlockHash: bestBlock.blockHash,
|
||||||
forkId: ChainForkId(
|
forkId: ChainForkId(
|
||||||
forkHash: forkId.crc.toBytesBE,
|
forkHash: forkId.crc.toBytesBE,
|
||||||
forkNext: forkId.nextFork.toBlockNumber
|
forkNext: forkId.nextFork
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ type
|
|||||||
|
|
||||||
ChainForkId* = object
|
ChainForkId* = object
|
||||||
forkHash*: array[4, byte] # The RLP encoding must be exactly 4 bytes.
|
forkHash*: array[4, byte] # The RLP encoding must be exactly 4 bytes.
|
||||||
forkNext*: BlockNumber # The RLP encoding must be variable-length
|
forkNext*: uint64 # The RLP encoding must be variable-length
|
||||||
|
|
||||||
EthWireBase* = ref object of RootRef
|
EthWireBase* = ref object of RootRef
|
||||||
|
|
||||||
|
@ -212,7 +212,7 @@ proc genesisLoadRunner(noisy = true;
|
|||||||
params = params)
|
params = params)
|
||||||
|
|
||||||
check mcom.ttd.get == sSpcs.termTotalDff
|
check mcom.ttd.get == sSpcs.termTotalDff
|
||||||
check mcom.toHardFork(sSpcs.mergeFork.toBlockNumber.blockNumberToForkDeterminationInfo) == MergeFork
|
check mcom.toHardFork(sSpcs.mergeFork.toBlockNumber.forkDeterminationInfo) == MergeFork
|
||||||
|
|
||||||
test &"Construct persistent ChainDBRef on {tmpDir}, {persistPruneInfo}":
|
test &"Construct persistent ChainDBRef on {tmpDir}, {persistPruneInfo}":
|
||||||
# Before allocating the database, the data directory needs to be
|
# Before allocating the database, the data directory needs to be
|
||||||
@ -229,7 +229,7 @@ proc genesisLoadRunner(noisy = true;
|
|||||||
params = params)
|
params = params)
|
||||||
|
|
||||||
check dcom.ttd.get == sSpcs.termTotalDff
|
check dcom.ttd.get == sSpcs.termTotalDff
|
||||||
check dcom.toHardFork(sSpcs.mergeFork.toBlockNumber.blockNumberToForkDeterminationInfo) == MergeFork
|
check dcom.toHardFork(sSpcs.mergeFork.toBlockNumber.forkDeterminationInfo) == MergeFork
|
||||||
|
|
||||||
test "Initialise in-memory Genesis":
|
test "Initialise in-memory Genesis":
|
||||||
mcom.initializeEmptyDb
|
mcom.initializeEmptyDb
|
||||||
|
@ -1,47 +1,60 @@
|
|||||||
import
|
import
|
||||||
unittest2,
|
unittest2,
|
||||||
../nimbus/common/common
|
../nimbus/common/common,
|
||||||
|
../nimbus/utils/utils
|
||||||
|
|
||||||
const
|
const
|
||||||
MainNetIDs = [
|
MainNetIDs = [
|
||||||
(blockNumber: 0'u64, id: (crc: 0xfc64ec04'u32, nextFork: 1150000'u64)), # Unsynced
|
(number: 0'u64 , time: 0'u64, id: (crc: 0xfc64ec04'u32, next: 1150000'u64)), # Unsynced
|
||||||
(blockNumber: 1149999'u64, id: (crc: 0xfc64ec04'u32, nextFork: 1150000'u64)), # Last Frontier block
|
(number: 1149999'u64 , time: 0'u64, id: (crc: 0xfc64ec04'u32, next: 1150000'u64)), # Last Frontier block
|
||||||
(blockNumber: 1150000'u64, id: (crc: 0x97c2c34c'u32, nextFork: 1920000'u64)), # First Homestead block
|
(number: 1150000'u64 , time: 0'u64, id: (crc: 0x97c2c34c'u32, next: 1920000'u64)), # First Homestead block
|
||||||
(blockNumber: 1919999'u64, id: (crc: 0x97c2c34c'u32, nextFork: 1920000'u64)), # Last Homestead block
|
(number: 1919999'u64 , time: 0'u64, id: (crc: 0x97c2c34c'u32, next: 1920000'u64)), # Last Homestead block
|
||||||
(blockNumber: 1920000'u64, id: (crc: 0x91d1f948'u32, nextFork: 2463000'u64)), # First DAO block
|
(number: 1920000'u64 , time: 0'u64, id: (crc: 0x91d1f948'u32, next: 2463000'u64)), # First DAO block
|
||||||
(blockNumber: 2462999'u64, id: (crc: 0x91d1f948'u32, nextFork: 2463000'u64)), # Last DAO block
|
(number: 2462999'u64 , time: 0'u64, id: (crc: 0x91d1f948'u32, next: 2463000'u64)), # Last DAO block
|
||||||
(blockNumber: 2463000'u64, id: (crc: 0x7a64da13'u32, nextFork: 2675000'u64)), # First Tangerine block
|
(number: 2463000'u64 , time: 0'u64, id: (crc: 0x7a64da13'u32, next: 2675000'u64)), # First Tangerine block
|
||||||
(blockNumber: 2674999'u64, id: (crc: 0x7a64da13'u32, nextFork: 2675000'u64)), # Last Tangerine block
|
(number: 2674999'u64 , time: 0'u64, id: (crc: 0x7a64da13'u32, next: 2675000'u64)), # Last Tangerine block
|
||||||
(blockNumber: 2675000'u64, id: (crc: 0x3edd5b10'u32, nextFork: 4370000'u64)), # First Spurious block
|
(number: 2675000'u64 , time: 0'u64, id: (crc: 0x3edd5b10'u32, next: 4370000'u64)), # First Spurious block
|
||||||
(blockNumber: 4369999'u64, id: (crc: 0x3edd5b10'u32, nextFork: 4370000'u64)), # Last Spurious block
|
(number: 4369999'u64 , time: 0'u64, id: (crc: 0x3edd5b10'u32, next: 4370000'u64)), # Last Spurious block
|
||||||
(blockNumber: 4370000'u64, id: (crc: 0xa00bc324'u32, nextFork: 7280000'u64)), # First Byzantium block
|
(number: 4370000'u64 , time: 0'u64, id: (crc: 0xa00bc324'u32, next: 7280000'u64)), # First Byzantium block
|
||||||
(blockNumber: 7279999'u64, id: (crc: 0xa00bc324'u32, nextFork: 7280000'u64)), # Last Byzantium block
|
(number: 7279999'u64 , time: 0'u64, id: (crc: 0xa00bc324'u32, next: 7280000'u64)), # Last Byzantium block
|
||||||
(blockNumber: 7280000'u64, id: (crc: 0x668db0af'u32, nextFork: 9069000'u64)), # First and last Constantinople, first Petersburg block
|
(number: 7280000'u64 , time: 0'u64, id: (crc: 0x668db0af'u32, next: 9069000'u64)), # First and last Constantinople, first Petersburg block
|
||||||
(blockNumber: 7987396'u64, id: (crc: 0x668db0af'u32, nextFork: 9069000'u64)), # Past Petersburg block
|
(number: 7987396'u64 , time: 0'u64, id: (crc: 0x668db0af'u32, next: 9069000'u64)), # Past Petersburg block
|
||||||
(blockNumber: 9068999'u64, id: (crc: 0x668db0af'u32, nextFork: 9069000'u64)), # Last Petersburg block
|
(number: 9068999'u64 , time: 0'u64, id: (crc: 0x668db0af'u32, next: 9069000'u64)), # Last Petersburg block
|
||||||
(blockNumber: 9069000'u64, id: (crc: 0x879D6E30'u32, nextFork: 9200000'u64)), # First Istanbul block
|
(number: 9069000'u64 , time: 0'u64, id: (crc: 0x879D6E30'u32, next: 9200000'u64)), # First Istanbul block
|
||||||
(blockNumber: 9199999'u64, id: (crc: 0x879D6E30'u32, nextFork: 9200000'u64)), # Last Istanbul block
|
(number: 9199999'u64 , time: 0'u64, id: (crc: 0x879D6E30'u32, next: 9200000'u64)), # Last Istanbul block
|
||||||
(blockNumber: 9200000'u64, id: (crc: 0xE029E991'u32, nextFork: 12244000'u64)), # First MuirGlacier block
|
(number: 9200000'u64 , time: 0'u64, id: (crc: 0xE029E991'u32, next: 12244000'u64)), # First MuirGlacier block
|
||||||
(blockNumber: 12243999'u64, id: (crc: 0xE029E991'u32, nextFork: 12244000'u64)), # Last MuirGlacier block
|
(number: 12243999'u64, time: 0'u64, id: (crc: 0xE029E991'u32, next: 12244000'u64)), # Last MuirGlacier block
|
||||||
(blockNumber: 12244000'u64, id: (crc: 0x0eb440f6'u32, nextFork: 12965000'u64)), # First Berlin block
|
(number: 12244000'u64, time: 0'u64, id: (crc: 0x0eb440f6'u32, next: 12965000'u64)), # First Berlin block
|
||||||
(blockNumber: 12964999'u64, id: (crc: 0x0eb440f6'u32, nextFork: 12965000'u64)), # Last Berlin block
|
(number: 12964999'u64, time: 0'u64, id: (crc: 0x0eb440f6'u32, next: 12965000'u64)), # Last Berlin block
|
||||||
(blockNumber: 12965000'u64, id: (crc: 0xb715077d'u32, nextFork: 13773000'u64)), # First London block
|
(number: 12965000'u64, time: 0'u64, id: (crc: 0xb715077d'u32, next: 13773000'u64)), # First London block
|
||||||
(blockNumber: 13772999'u64, id: (crc: 0xb715077d'u32, nextFork: 13773000'u64)), # Last London block
|
(number: 13772999'u64, time: 0'u64, id: (crc: 0xb715077d'u32, next: 13773000'u64)), # Last London block
|
||||||
(blockNumber: 13773000'u64, id: (crc: 0x20c327fc'u32, nextFork: 15050000'u64)), # First Arrow Glacier block
|
(number: 13773000'u64, time: 0'u64, id: (crc: 0x20c327fc'u32, next: 15050000'u64)), # First Arrow Glacier block
|
||||||
(blockNumber: 15049999'u64, id: (crc: 0x20c327fc'u32, nextFork: 15050000'u64)), # Last Arrow Glacier block
|
(number: 15049999'u64, time: 0'u64, id: (crc: 0x20c327fc'u32, next: 15050000'u64)), # Last Arrow Glacier block
|
||||||
(blockNumber: 15050000'u64, id: (crc: 0xf0afd0e3'u32, nextFork: 0'u64)), # First Gray Glacier block
|
(number: 15050000'u64, time: 0'u64, id: (crc: 0xf0afd0e3'u32, next: 1681338455'u64)), # First Gray Glacier block
|
||||||
(blockNumber: 20000000'u64, id: (crc: 0xf0afd0e3'u32, nextFork: 0'u64)), # Future Gray Glacier block
|
(number: 20000000'u64, time: 1681338454'u64, id: (crc: 0xf0afd0e3'u32, next: 1681338455'u64)), # Last Gray Glacier block
|
||||||
|
(number: 20000000'u64, time: 1681338455'u64, id: (crc: 0xdce96c2d'u32, next: 0'u64)), # First Shanghai block
|
||||||
|
(number: 30000000'u64, time: 2000000000'u64, id: (crc: 0xdce96c2d'u32, next: 0'u64)), # Future Shanghai block
|
||||||
]
|
]
|
||||||
|
|
||||||
GoerliNetIDs = [
|
GoerliNetIDs = [
|
||||||
(blockNumber: 0'u64, id: (crc: 0xa3f5ab08'u32, nextFork: 1561651'u64)), # Unsynced, last Frontier, Homestead, Tangerine, Spurious, Byzantium, Constantinople and first Petersburg block
|
(number: 0'u64 , time: 0'u64, id: (crc: 0xa3f5ab08'u32, next: 1561651'u64)), # Unsynced, last Frontier, Homestead, Tangerine, Spurious, Byzantium, Constantinople and first Petersburg block
|
||||||
(blockNumber: 1561650'u64, id: (crc: 0xa3f5ab08'u32, nextFork: 1561651'u64)), # Last Petersburg block
|
(number: 1561650'u64, time: 0'u64, id: (crc: 0xa3f5ab08'u32, next: 1561651'u64)), # Last Petersburg block
|
||||||
(blockNumber: 1561651'u64, id: (crc: 0xc25efa5c'u32, nextFork: 4460644'u64)), # First Istanbul block
|
(number: 1561651'u64, time: 0'u64, id: (crc: 0xc25efa5c'u32, next: 4460644'u64)), # First Istanbul block
|
||||||
(blockNumber: 4460643'u64, id: (crc: 0xc25efa5c'u32, nextFork: 4460644'u64)), # Future Istanbul block
|
(number: 4460643'u64, time: 0'u64, id: (crc: 0xc25efa5c'u32, next: 4460644'u64)), # Future Istanbul block
|
||||||
(blockNumber: 4460644'u64, id: (crc: 0x757a1c47'u32, nextFork: 5062605'u64)), # First Berlin block
|
(number: 4460644'u64, time: 0'u64, id: (crc: 0x757a1c47'u32, next: 5062605'u64)), # First Berlin block
|
||||||
(blockNumber: 5062604'u64, id: (crc: 0x757a1c47'u32, nextFork: 5062605'u64)), # Last Berlin block
|
(number: 5062604'u64, time: 0'u64, id: (crc: 0x757a1c47'u32, next: 5062605'u64)), # Last Berlin block
|
||||||
(blockNumber: 5062605'u64, id: (crc: 0xb8c6299d'u32, nextFork: 0'u64)), # First London block
|
(number: 5062605'u64, time: 0'u64, id: (crc: 0xb8c6299d'u32, next: 1678832736'u64)), # First London block
|
||||||
(blockNumber: 10000000'u64, id: (crc: 0xb8c6299d'u32, nextFork: 0'u64)), # Future London block
|
(number: 6000000'u64, time: 1678832735'u64, id: (crc: 0xB8C6299D'u32, next: 1678832736'u64)), # Last London block
|
||||||
|
(number: 6000001'u64, time: 1678832736'u64, id: (crc: 0xf9843abf'u32, next: 0'u64)), # First Shanghai block
|
||||||
|
(number: 6500000'u64, time: 2678832736'u64, id: (crc: 0xf9843abf'u32, next: 0'u64)), # Future Shanghai block
|
||||||
|
]
|
||||||
|
|
||||||
|
SepoliaNetIDs = [
|
||||||
|
(number: 0'u64, time: 0'u64, id: (crc: 0xfe3366e7'u32, next: 1735371'u64)), # Unsynced, last Frontier, Homestead, Tangerine, Spurious, Byzantium, Constantinople, Petersburg, Istanbul, Berlin and first London block
|
||||||
|
(number: 1735370'u64, time: 0'u64, id: (crc: 0xfe3366e7'u32, next: 1735371'u64)), # Last London block
|
||||||
|
(number: 1735371'u64, time: 0'u64, id: (crc: 0xb96cbd13'u32, next: 1677557088'u64)), # First MergeNetsplit block
|
||||||
|
(number: 1735372'u64, time: 1677557087'u64, id: (crc: 0xb96cbd13'u32, next: 1677557088'u64)), # Last MergeNetsplit block
|
||||||
|
(number: 1735372'u64, time: 1677557088'u64, id: (crc: 0xf7f9bc08'u32, next: 0'u64)), # First Shanghai block
|
||||||
]
|
]
|
||||||
|
|
||||||
template runTest(network: untyped, name: string) =
|
template runTest(network: untyped, name: string) =
|
||||||
@ -50,15 +63,67 @@ template runTest(network: untyped, name: string) =
|
|||||||
params = networkParams(network)
|
params = networkParams(network)
|
||||||
com = CommonRef.new(newCoreDbRef LegacyDbMemory, true, network, params)
|
com = CommonRef.new(newCoreDbRef LegacyDbMemory, true, network, params)
|
||||||
|
|
||||||
for x in `network IDs`:
|
for i, x in `network IDs`:
|
||||||
let id = com.forkId(x.blockNumber.toBlockNumber.blockNumberToForkDeterminationInfo)
|
let id = com.forkId(x.number, x.time)
|
||||||
check id.crc == x.id.crc
|
check id.crc == x.id.crc
|
||||||
check id.nextFork == x.id.nextFork
|
check id.nextFork == x.id.next
|
||||||
|
|
||||||
|
func config(shanghai, cancun: uint64): ChainConfig =
|
||||||
|
ChainConfig(
|
||||||
|
chainID: ChainId(1337),
|
||||||
|
homesteadBlock: some(0.u256),
|
||||||
|
dAOForkBlock: none(BlockNumber),
|
||||||
|
dAOForkSupport: true,
|
||||||
|
eIP150Block: some(0.u256),
|
||||||
|
eIP155Block: some(0.u256),
|
||||||
|
eIP158Block: some(0.u256),
|
||||||
|
byzantiumBlock: some(0.u256),
|
||||||
|
constantinopleBlock: some(0.u256),
|
||||||
|
petersburgBlock: some(0.u256),
|
||||||
|
istanbulBlock: some(0.u256),
|
||||||
|
muirGlacierBlock: some(0.u256),
|
||||||
|
berlinBlock: some(0.u256),
|
||||||
|
londonBlock: some(0.u256),
|
||||||
|
terminalTotalDifficulty: some(0.u256),
|
||||||
|
terminalTotalDifficultyPassed: some(true),
|
||||||
|
mergeForkBlock: some(0.u256),
|
||||||
|
shanghaiTime: some(shanghai.EthTime),
|
||||||
|
cancunTime: some(cancun.EthTime),
|
||||||
|
)
|
||||||
|
|
||||||
|
func calcID(conf: ChainConfig, crc: uint32, time: uint64): ForkID =
|
||||||
|
let map = conf.toForkTransitionTable
|
||||||
|
let calc = map.initForkIdCalculator(crc, time)
|
||||||
|
calc.newID(0, time)
|
||||||
|
|
||||||
|
template runGenesisTimeIdTests() =
|
||||||
|
let
|
||||||
|
time = 1690475657'u64
|
||||||
|
genesis = common.BlockHeader(timestamp: time.EthTime)
|
||||||
|
genesisCRC = crc32(0, genesis.blockHash.data)
|
||||||
|
cases = [
|
||||||
|
# Shanghai active before genesis, skip
|
||||||
|
(c: config(time-1, time+1), want: (crc: genesisCRC, next: time + 1)),
|
||||||
|
|
||||||
|
# Shanghai active at genesis, skip
|
||||||
|
(c: config(time, time+1), want: (crc: genesisCRC, next: time + 1)),
|
||||||
|
|
||||||
|
# Shanghai not active, skip
|
||||||
|
(c: config(time+1, time+2), want: (crc: genesisCRC, next: time + 1)),
|
||||||
|
]
|
||||||
|
|
||||||
|
for i, x in cases:
|
||||||
|
let get = calcID(x.c, genesisCRC, time)
|
||||||
|
check get.crc == x.want.crc
|
||||||
|
check get.nextFork == x.want.next
|
||||||
|
|
||||||
proc forkIdMain*() =
|
proc forkIdMain*() =
|
||||||
suite "Fork ID tests":
|
suite "Fork ID tests":
|
||||||
runTest(MainNet, "MainNet")
|
runTest(MainNet, "MainNet")
|
||||||
runTest(GoerliNet, "GoerliNet")
|
runTest(GoerliNet, "GoerliNet")
|
||||||
|
runTest(SepoliaNet, "SepoliaNet")
|
||||||
|
test "Genesis Time Fork ID":
|
||||||
|
runGenesisTimeIdTests()
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
forkIdMain()
|
forkIdMain()
|
||||||
|
@ -92,7 +92,7 @@ proc testFixtureIndexes(ctx: var TestCtx, testStatusIMPL: var TestStatus) =
|
|||||||
|
|
||||||
var gasUsed: GasInt
|
var gasUsed: GasInt
|
||||||
let sender = ctx.tx.getSender()
|
let sender = ctx.tx.getSender()
|
||||||
let fork = com.toEVMFork(ctx.header.forkDeterminationInfoForHeader)
|
let fork = com.toEVMFork(ctx.header.forkDeterminationInfo)
|
||||||
|
|
||||||
vmState.mutateStateDB:
|
vmState.mutateStateDB:
|
||||||
setupStateDB(ctx.pre, db)
|
setupStateDB(ctx.pre, db)
|
||||||
|
@ -107,7 +107,7 @@ proc writeRootHashToStderr(vmState: BaseVMState) =
|
|||||||
proc runExecution(ctx: var StateContext, conf: StateConf, pre: JsonNode): StateResult =
|
proc runExecution(ctx: var StateContext, conf: StateConf, pre: JsonNode): StateResult =
|
||||||
let
|
let
|
||||||
com = CommonRef.new(newCoreDbRef LegacyDbMemory, ctx.chainConfig, pruneTrie = false)
|
com = CommonRef.new(newCoreDbRef LegacyDbMemory, ctx.chainConfig, pruneTrie = false)
|
||||||
fork = com.toEVMFork(ctx.header.forkDeterminationInfoForHeader)
|
fork = com.toEVMFork(ctx.header.forkDeterminationInfo)
|
||||||
stream = newFileStream(stderr)
|
stream = newFileStream(stderr)
|
||||||
tracer = if conf.jsonEnabled:
|
tracer = if conf.jsonEnabled:
|
||||||
newJSonTracer(stream, ctx.tracerFlags, conf.pretty)
|
newJSonTracer(stream, ctx.tracerFlags, conf.pretty)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user