mirror of
https://github.com/status-im/nimbus-eth1.git
synced 2025-01-11 12:54:13 +00:00
Time based forking (#1465)
* Refactoring in preparation for time-based forking. * Timestamp-based hard-fork-transition. * Workaround SideEffect issue / compiler bug for both failing locations in Portal history code --------- Co-authored-by: kdeme <kim.demey@gmail.com>
This commit is contained in:
parent
54958d4731
commit
fad3ed64cf
@ -12,7 +12,7 @@ import
|
||||
stew/results, chronos, chronicles,
|
||||
eth/common/eth_types, eth/rlp,
|
||||
../network/wire/portal_protocol,
|
||||
../network/history/[history_content, accumulator],
|
||||
../network/history/[history_content, history_network, accumulator],
|
||||
"."/[history_data_json_store, history_data_ssz_e2s]
|
||||
|
||||
export results
|
||||
|
@ -21,6 +21,29 @@ logScope:
|
||||
|
||||
export accumulator
|
||||
|
||||
# This looks like it makes no sense, because it makes no sense. It's a
|
||||
# workaround for what seems to be a compiler bug; see here:
|
||||
#
|
||||
# https://github.com/status-im/nimbus-eth1/pull/1465
|
||||
#
|
||||
# Without this, the call `error` on a `Result` might give a compiler error for
|
||||
# the `Result[BlockHeader, string]` or `Result[seq[BlockHeader], string]` types.
|
||||
# The error is due to the `$` for `BlockHeader causing side effects, which
|
||||
# appears to be due to the timestamp field, which is of `times.Time` type. Its
|
||||
# `$` from the times module has side effects (Yes, silly times). In (my) theory
|
||||
# this `$` should not leak here, but it seems to do. To workaround this we
|
||||
# introduce this additional `$` call, which appears to work.
|
||||
#
|
||||
# Note that this also fixes the same error in another module, even when not
|
||||
# specifically exporting (no asterisk) the call.
|
||||
#
|
||||
# If you think this is unnecessary, feel free to try deleting it; if all the
|
||||
# tests still pass after deleting it, feel free to leave it out. In the
|
||||
# meantime, please just ignore it and go on with your life.
|
||||
#
|
||||
proc `$`(x: BlockHeader): string =
|
||||
$x
|
||||
|
||||
const
|
||||
historyProtocolId* = [byte 0x50, 0x0B]
|
||||
|
||||
|
@ -24,8 +24,8 @@ proc genesisToTrie(filePath: string): HexaryTrie =
|
||||
quit(1)
|
||||
|
||||
let sdb = newStateDB(newMemoryDB(), false)
|
||||
let map = toForkToBlockNumber(cn.config)
|
||||
let fork = map.toHardFork(0.toBlockNumber)
|
||||
let map = toForkTransitionTable(cn.config)
|
||||
let fork = map.toHardFork(forkDeterminationInfo(0.toBlockNumber, cn.genesis.timestamp))
|
||||
discard toGenesisHeader(cn.genesis, sdb, fork)
|
||||
|
||||
sdb.getTrie
|
||||
|
@ -187,73 +187,89 @@ template to(a: string, b: type UInt256): UInt256 =
|
||||
# json_serialization decode table stuff
|
||||
UInt256.fromHex(a)
|
||||
|
||||
macro fillTmpArray(conf, tmp: typed): untyped =
|
||||
macro fillArrayOfBlockNumberBasedForkOptionals(conf, tmp: typed): untyped =
|
||||
result = newStmtList()
|
||||
for i, x in forkBlockField:
|
||||
let fieldIdent = newIdentNode(x)
|
||||
result.add quote do:
|
||||
`tmp`[`i`] = ForkOptional(
|
||||
`tmp`[`i`] = BlockNumberBasedForkOptional(
|
||||
number : `conf`.`fieldIdent`,
|
||||
name : `x`)
|
||||
|
||||
macro fillToBlockNumberArray(conf, arr: typed): untyped =
|
||||
macro fillArrayOfTimeBasedForkOptionals(conf, tmp: typed): untyped =
|
||||
result = newStmtList()
|
||||
for fork, forkField in forkBlockNumber:
|
||||
let
|
||||
fieldIdent = newIdentNode(forkField)
|
||||
forkIdent = newIdentNode($HardFork(fork.ord))
|
||||
for i, x in forkTimeField:
|
||||
let fieldIdent = newIdentNode(x)
|
||||
result.add quote do:
|
||||
`arr`[`forkIdent`] = `conf`.`fieldIdent`
|
||||
`tmp`[`i`] = TimeBasedForkOptional(
|
||||
time : `conf`.`fieldIdent`,
|
||||
name : `x`)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Public functions
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
proc toForkToBlockNumber*(conf: ChainConfig): ForkToBlockNumber =
|
||||
fillToBlockNumberArray(conf, result)
|
||||
result[Frontier] = some(0.toBlockNumber)
|
||||
|
||||
proc toHardFork*(forkToBlock: ForkToBlockNumber, number: BlockNumber): HardFork =
|
||||
proc toHardFork*(map: ForkTransitionTable, forkDeterminer: ForkDeterminationInfo): HardFork =
|
||||
for fork in countdown(HardFork.high, HardFork.low):
|
||||
let forkBlock = forkToBlock[fork]
|
||||
if forkBlock.isSome and number >= forkBlock.get:
|
||||
if isGTETransitionThreshold(map, forkDeterminer, fork):
|
||||
return fork
|
||||
|
||||
# should always have a match
|
||||
doAssert(false, "unreachable code")
|
||||
|
||||
func forkDeterminationInfoForHeader*(header: BlockHeader): ForkDeterminationInfo =
|
||||
# FIXME-Adam-mightAlsoNeedTTD?
|
||||
forkDeterminationInfo(header.blockNumber, header.timestamp)
|
||||
|
||||
proc validateChainConfig*(conf: ChainConfig): bool =
|
||||
result = true
|
||||
|
||||
var tmp: array[forkBlockField.len, ForkOptional]
|
||||
fillTmpArray(conf, tmp)
|
||||
# FIXME: factor this to remove the duplication between the
|
||||
# block-based ones and the time-based ones.
|
||||
|
||||
var lastFork = tmp[0]
|
||||
for i in 1..<tmp.len:
|
||||
let cur = tmp[i]
|
||||
var blockNumberBasedForkOptionals: array[forkBlockField.len, BlockNumberBasedForkOptional]
|
||||
fillArrayOfBlockNumberBasedForkOptionals(conf, blockNumberBasedForkOptionals)
|
||||
|
||||
# Next one must be higher number
|
||||
#if lastFork.number.isNone and cur.number.isSome:
|
||||
# error "Unsupported fork ordering",
|
||||
# lastFork=lastFork.name,
|
||||
# lastNumber=lastFork.number,
|
||||
# curFork=cur.name,
|
||||
# curNumber=cur.number
|
||||
# return false
|
||||
var timeBasedForkOptionals: array[forkTimeField.len, TimeBasedForkOptional]
|
||||
fillArrayOfTimeBasedForkOptionals(conf, timeBasedForkOptionals)
|
||||
|
||||
if lastFork.number.isSome and cur.number.isSome:
|
||||
if lastFork.number.get > cur.number.get:
|
||||
var lastBlockNumberBasedFork = blockNumberBasedForkOptionals[0]
|
||||
for i in 1..<blockNumberBasedForkOptionals.len:
|
||||
let cur = blockNumberBasedForkOptionals[i]
|
||||
|
||||
if lastBlockNumberBasedFork.number.isSome and cur.number.isSome:
|
||||
if lastBlockNumberBasedFork.number.get > cur.number.get:
|
||||
error "Unsupported fork ordering",
|
||||
lastFork=lastFork.name,
|
||||
lastNumber=lastFork.number,
|
||||
lastFork=lastBlockNumberBasedFork.name,
|
||||
lastNumber=lastBlockNumberBasedFork.number,
|
||||
curFork=cur.name,
|
||||
curNumber=cur.number
|
||||
return false
|
||||
|
||||
# If it was optional and not set, then ignore it
|
||||
if cur.number.isSome:
|
||||
lastFork = cur
|
||||
lastBlockNumberBasedFork = cur
|
||||
|
||||
# TODO: check to make sure the timestamps are all past the
|
||||
# block numbers?
|
||||
|
||||
var lastTimeBasedFork = timeBasedForkOptionals[0]
|
||||
for i in 1..<timeBasedForkOptionals.len:
|
||||
let cur = timeBasedForkOptionals[i]
|
||||
|
||||
if lastTimeBasedFork.time.isSome and cur.time.isSome:
|
||||
if lastTimeBasedFork.time.get > cur.time.get:
|
||||
error "Unsupported fork ordering",
|
||||
lastFork=lastTimeBasedFork.name,
|
||||
lastTime=lastTimeBasedFork.time,
|
||||
curFork=cur.name,
|
||||
curTime=cur.time
|
||||
return false
|
||||
|
||||
# If it was optional and not set, then ignore it
|
||||
if cur.time.isSome:
|
||||
lastTimeBasedFork = cur
|
||||
|
||||
if conf.clique.period.isSome or
|
||||
conf.clique.epoch.isSome:
|
||||
conf.consensusType = ConsensusType.POA
|
||||
|
@ -53,10 +53,9 @@ type
|
||||
genesisHash: KeccakHash
|
||||
genesisHeader: BlockHeader
|
||||
|
||||
# map block number and ttd to
|
||||
# map block number and ttd and time to
|
||||
# HardFork
|
||||
forkToBlock: ForkToBlockNumber
|
||||
blockToFork: BlockToForks
|
||||
forkTransitionTable: ForkTransitionTable
|
||||
|
||||
# Eth wire protocol need this
|
||||
forkIds: array[HardFork, ForkID]
|
||||
@ -86,8 +85,7 @@ type
|
||||
# Forward declarations
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
proc hardForkTransition*(com: CommonRef,
|
||||
number: BlockNumber, td: Option[DifficultyInt]) {.gcsafe, raises: [CatchableError].}
|
||||
proc hardForkTransition*(com: CommonRef, forkDeterminer: ForkDeterminationInfo) {.gcsafe, raises: [CatchableError].}
|
||||
|
||||
func cliquePeriod*(com: CommonRef): int
|
||||
|
||||
@ -129,8 +127,7 @@ proc init(com : CommonRef,
|
||||
com.db = ChainDBRef.new(db)
|
||||
com.pruneTrie = pruneTrie
|
||||
com.config = config
|
||||
com.forkToBlock = config.toForkToBlockNumber()
|
||||
com.blockToFork = config.blockToForks(com.forkToBlock)
|
||||
com.forkTransitionTable = config.toForkTransitionTable()
|
||||
com.networkId = networkId
|
||||
com.syncProgress= SyncProgress()
|
||||
|
||||
@ -139,7 +136,8 @@ proc init(com : CommonRef,
|
||||
# set it before creating genesis block
|
||||
# TD need to be some(0.u256) because it can be the genesis
|
||||
# already at the MergeFork
|
||||
com.hardForkTransition(0.toBlockNumber, some(0.u256))
|
||||
let optionalGenesisTime = if genesis.isNil: none[EthTime]() else: some(genesis.timestamp)
|
||||
com.hardForkTransition(ForkDeterminationInfo(blockNumber: 0.toBlockNumber, td: some(0.u256), time: optionalGenesisTime))
|
||||
|
||||
# com.forkIds and com.blockZeroHash is set
|
||||
# by setForkId
|
||||
@ -156,6 +154,24 @@ proc init(com : CommonRef,
|
||||
com.pow = PowRef.new
|
||||
com.pos = CasperRef.new
|
||||
|
||||
proc getTd(com: CommonRef, blockHash: Hash256): Option[DifficultyInt] =
|
||||
var td: DifficultyInt
|
||||
if not com.db.getTd(blockHash, td):
|
||||
# TODO: Is this really ok?
|
||||
none[DifficultyInt]()
|
||||
else:
|
||||
some(td)
|
||||
|
||||
proc needTdForHardForkDetermination(com: CommonRef): bool =
|
||||
let t = com.forkTransitionTable.mergeForkTransitionThreshold
|
||||
t.blockNumber.isNone and t.ttd.isSome
|
||||
|
||||
proc getTdIfNecessary(com: CommonRef, blockHash: Hash256): Option[DifficultyInt] =
|
||||
if needTdForHardForkDetermination(com):
|
||||
getTd(com, blockHash)
|
||||
else:
|
||||
none[DifficultyInt]()
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Public constructors
|
||||
# ------------------------------------------------------------------------------
|
||||
@ -201,8 +217,7 @@ proc clone*(com: CommonRef, db: TrieDatabaseRef): CommonRef =
|
||||
db : ChainDBRef.new(db),
|
||||
pruneTrie : com.pruneTrie,
|
||||
config : com.config,
|
||||
forkToBlock : com.forkToBlock,
|
||||
blockToFork : com.blockToFork,
|
||||
forkTransitionTable: com.forkTransitionTable,
|
||||
forkIds : com.forkIds,
|
||||
genesisHash : com.genesisHash,
|
||||
genesisHeader: com.genesisHeader,
|
||||
@ -222,85 +237,41 @@ proc clone*(com: CommonRef): CommonRef =
|
||||
# Public functions
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
func toHardFork*(com: CommonRef, number: BlockNumber): HardFork =
|
||||
## doesn't do transition
|
||||
## only want to know a particular block number
|
||||
## belongs to which fork without considering TD or TTD
|
||||
## MergeFork: assume the MergeForkBlock isSome,
|
||||
## if there is a MergeFork, thus bypassing the TD >= TTD
|
||||
## comparison
|
||||
toHardFork(com.forkToBlock, number)
|
||||
func toHardFork*(com: CommonRef, forkDeterminer: ForkDeterminationInfo): HardFork =
|
||||
toHardFork(com.forkTransitionTable, forkDeterminer)
|
||||
|
||||
proc hardForkTransition(com: CommonRef,
|
||||
number: BlockNumber, td: Option[DifficultyInt])
|
||||
proc hardForkTransition(com: CommonRef, forkDeterminer: ForkDeterminationInfo)
|
||||
{.gcsafe, raises: [Defect, CatchableError].} =
|
||||
## When consensus type already transitioned to POS,
|
||||
## the storage can choose not to store TD anymore,
|
||||
## at that time, TD is no longer needed to find a fork
|
||||
## TD only needed during transition from POW/POA to POS.
|
||||
## Same thing happen before London block, TD can be ignored.
|
||||
let fork = com.toHardFork(forkDeterminer)
|
||||
com.currentFork = fork
|
||||
com.consensusTransition(fork)
|
||||
|
||||
if td.isNone:
|
||||
# fork transition ignoring TD
|
||||
let fork = com.toHardFork(number)
|
||||
com.currentFork = fork
|
||||
com.consensusTransition(fork)
|
||||
return
|
||||
proc hardForkTransition*(com: CommonRef,
|
||||
number: BlockNumber,
|
||||
td: Option[DifficultyInt],
|
||||
time: Option[EthTime])
|
||||
{.gcsafe, raises: [Defect, CatchableError].} =
|
||||
com.hardForkTransition(ForkDeterminationInfo(blockNumber: number, time: time, td: td))
|
||||
|
||||
# fork transition considering TD
|
||||
let td = td.get()
|
||||
for fork in countdown(HardFork.high, HardFork.low):
|
||||
let x = com.blockToFork[fork]
|
||||
if x.toFork(x.data, number, td):
|
||||
com.currentFork = fork
|
||||
com.consensusTransition(fork)
|
||||
return
|
||||
|
||||
# should always have a match
|
||||
doAssert(false, "unreachable code")
|
||||
|
||||
proc hardForkTransition*(com: CommonRef, parentHash: Hash256,
|
||||
number: BlockNumber)
|
||||
{.gcsafe, raises: [CatchableError].} =
|
||||
|
||||
# if mergeForkBlock is present, it has higher
|
||||
# priority than TTD
|
||||
if com.config.mergeForkBlock.isSome or
|
||||
com.config.terminalTotalDifficulty.isNone:
|
||||
let fork = com.toHardFork(number)
|
||||
com.currentFork = fork
|
||||
com.consensusTransition(fork)
|
||||
return
|
||||
|
||||
var td: DifficultyInt
|
||||
if not com.db.getTd(parentHash, td):
|
||||
# TODO: Is this really ok?
|
||||
let fork = com.toHardFork(number)
|
||||
com.currentFork = fork
|
||||
com.consensusTransition(fork)
|
||||
return
|
||||
|
||||
for fork in countdown(HardFork.high, HardFork.low):
|
||||
let x = com.blockToFork[fork]
|
||||
if x.toFork(x.data, number, td):
|
||||
com.currentFork = fork
|
||||
com.consensusTransition(fork)
|
||||
return
|
||||
|
||||
# should always have a match
|
||||
doAssert(false, "unreachable code")
|
||||
proc hardForkTransition*(com: CommonRef,
|
||||
parentHash: Hash256,
|
||||
number: BlockNumber,
|
||||
time: Option[EthTime])
|
||||
{.gcsafe, raises: [Defect, CatchableError].} =
|
||||
com.hardForkTransition(number, getTdIfNecessary(com, parentHash), time)
|
||||
|
||||
proc hardForkTransition*(com: CommonRef, header: BlockHeader)
|
||||
{.gcsafe, raises: [CatchableError].} =
|
||||
{.gcsafe, raises: [Defect, CatchableError].} =
|
||||
com.hardForkTransition(header.parentHash, header.blockNumber, some(header.timestamp))
|
||||
|
||||
com.hardForkTransition(header.parentHash, header.blockNumber)
|
||||
|
||||
func toEVMFork*(com: CommonRef, number: BlockNumber): EVMFork =
|
||||
func toEVMFork*(com: CommonRef, forkDeterminer: ForkDeterminationInfo): EVMFork =
|
||||
## similar to toFork, but produce EVMFork
|
||||
## be aware that if MergeFork is not set in
|
||||
## chain config, this function probably give wrong
|
||||
## result because no TD is put into consideration
|
||||
let fork = com.toHardFork(number)
|
||||
let fork = com.toHardFork(forkDeterminer)
|
||||
ToEVMFork[fork]
|
||||
|
||||
func toEVMFork*(com: CommonRef): EVMFork =
|
||||
@ -308,7 +279,7 @@ func toEVMFork*(com: CommonRef): EVMFork =
|
||||
|
||||
func isLondon*(com: CommonRef, number: BlockNumber): bool =
|
||||
# TODO: Fixme, use only London comparator
|
||||
com.toHardFork(number) >= London
|
||||
com.toHardFork(number.blockNumberToForkDeterminationInfo) >= London
|
||||
|
||||
func forkGTE*(com: CommonRef, fork: HardFork): bool =
|
||||
com.currentFork >= fork
|
||||
@ -328,9 +299,9 @@ proc minerAddress*(com: CommonRef; header: BlockHeader): EthAddress
|
||||
|
||||
account.value
|
||||
|
||||
func forkId*(com: CommonRef, number: BlockNumber): ForkID {.gcsafe.} =
|
||||
func forkId*(com: CommonRef, forkDeterminer: ForkDeterminationInfo): ForkID {.gcsafe.} =
|
||||
## EIP 2364/2124
|
||||
let fork = com.toHardFork(number)
|
||||
let fork = com.toHardFork(forkDeterminer)
|
||||
com.forkIds[fork]
|
||||
|
||||
func isEIP155*(com: CommonRef, number: BlockNumber): bool =
|
||||
@ -470,9 +441,8 @@ proc `syncHighest=`*(com: CommonRef, number: BlockNumber) =
|
||||
proc setTTD*(com: CommonRef, ttd: Option[DifficultyInt]) =
|
||||
## useful for testing
|
||||
com.config.terminalTotalDifficulty = ttd
|
||||
# rebuild blockToFork
|
||||
# TODO: Fix me, only need to rebuild MergeFork comparator
|
||||
com.blockToFork = com.config.blockToForks(com.forkToBlock)
|
||||
# rebuild the MergeFork piece of the forkTransitionTable
|
||||
com.forkTransitionTable.mergeForkTransitionThreshold = com.config.mergeForkTransitionThreshold
|
||||
|
||||
proc setFork*(com: CommonRef, fork: HardFork): Hardfork =
|
||||
## useful for testing
|
||||
|
@ -112,8 +112,8 @@ proc toGenesisHeader*(
|
||||
): BlockHeader
|
||||
{.raises: [RlpError].} =
|
||||
## Generate the genesis block header from the `genesis` and `config` argument value.
|
||||
let map = toForkToBlockNumber(params.config)
|
||||
let fork = map.toHardFork(0.toBlockNumber)
|
||||
let map = toForkTransitionTable(params.config)
|
||||
let fork = map.toHardFork(forkDeterminationInfo(0.toBlockNumber, params.genesis.timestamp))
|
||||
toGenesisHeader(params.genesis, fork, db)
|
||||
|
||||
# End
|
||||
|
@ -8,7 +8,7 @@
|
||||
# those terms.
|
||||
|
||||
import
|
||||
std/options,
|
||||
std/[options, times],
|
||||
eth/common,
|
||||
json_serialization,
|
||||
../utils/utils,
|
||||
@ -49,10 +49,103 @@ type
|
||||
Shanghai
|
||||
Cancun
|
||||
|
||||
const lastPurelyBlockNumberBasedFork* = GrayGlacier
|
||||
# MergeFork is special because of TTD.
|
||||
const firstTimeBasedFork* = Shanghai
|
||||
|
||||
|
||||
type
|
||||
CliqueOptions* = object
|
||||
epoch* : Option[int]
|
||||
period*: Option[int]
|
||||
|
||||
MergeForkTransitionThreshold* = object
|
||||
blockNumber*: Option[BlockNumber]
|
||||
ttd*: Option[DifficultyInt]
|
||||
|
||||
ForkTransitionTable* = object
|
||||
blockNumberThresholds*: array[Frontier..GrayGlacier, Option[BlockNumber]]
|
||||
mergeForkTransitionThreshold*: MergeForkTransitionThreshold
|
||||
timeThresholds*: array[Shanghai..Cancun, Option[EthTime]]
|
||||
|
||||
# Starting with Shanghai, forking is based on timestamp
|
||||
# rather than block number.
|
||||
#
|
||||
# I'm not sure what to call this type, but we used to pass
|
||||
# just the block number into various places that need to
|
||||
# determine which fork we're on, and now we need to pass
|
||||
# around both block number and also time. And the config
|
||||
# info for each individual fork will be either a block
|
||||
# number or a time.
|
||||
#
|
||||
# Note that time and TD are optional. TD being optional
|
||||
# is because it's perfectly fine, if mergeForkBlock is
|
||||
# set, to not bother with TTD anymore. But I'm not sure
|
||||
# it makes sense to allow time to be optional. See the
|
||||
# comment below on blockNumberToForkDeterminationInfo.
|
||||
ForkDeterminationInfo* = object
|
||||
blockNumber*: BlockNumber
|
||||
time*: Option[EthTime]
|
||||
td*: Option[DifficultyInt]
|
||||
|
||||
func blockNumberToForkDeterminationInfo*(n: BlockNumber): ForkDeterminationInfo =
|
||||
# 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,
|
||||
# like various tests, where we only have block number and the tests are
|
||||
# meant for pre-Merge forks, so maybe those are okay.
|
||||
ForkDeterminationInfo(blockNumber: n, time: none[EthTime](), td: none[DifficultyInt]())
|
||||
|
||||
func forkDeterminationInfo*(n: BlockNumber, t: EthTime): ForkDeterminationInfo =
|
||||
ForkDeterminationInfo(blockNumber: n, time: some(t), td: none[DifficultyInt]())
|
||||
|
||||
# FIXME: Is this called anywhere?
|
||||
func forkDeterminationInfoIncludingTd*(n: BlockNumber, t: EthTime, td: DifficultyInt): ForkDeterminationInfo =
|
||||
ForkDeterminationInfo(blockNumber: n, time: some(t), td: some(td))
|
||||
|
||||
proc adjustForNextBlock*(n: BlockNumber): BlockNumber =
|
||||
n + 1
|
||||
|
||||
func adjustForNextBlock*(t: EthTime): EthTime =
|
||||
# FIXME-Adam: what's the right thing to do here?
|
||||
# How do we calculate "the timestamp for the block
|
||||
# after this one"?
|
||||
#
|
||||
# If this makes no sense, what should the callers
|
||||
# do instead?
|
||||
fromUnix(t.toUnix + 12)
|
||||
|
||||
func adjustForNextBlock*(f: ForkDeterminationInfo): ForkDeterminationInfo =
|
||||
ForkDeterminationInfo(
|
||||
blockNumber: adjustForNextBlock(f.blockNumber),
|
||||
time: f.time.map(adjustForNextBlock),
|
||||
td: f.td
|
||||
)
|
||||
|
||||
# This function is awkward because there are various different ways now of
|
||||
# doing a hard-fork transition (block number, ttd, time, block number *or*
|
||||
# time). We used to have a simple array called forkToBlock that mapped each
|
||||
# HardFork to a BlockNumber; now we have this ForkTransitionTable, which
|
||||
# contains a couple of arrays and also special cases for MergeBlock and
|
||||
# Shanghai.
|
||||
func isGTETransitionThreshold*(map: ForkTransitionTable, forkDeterminer: ForkDeterminationInfo, fork: HardFork): bool =
|
||||
if fork <= lastPurelyBlockNumberBasedFork:
|
||||
map.blockNumberThresholds[fork].isSome and forkDeterminer.blockNumber >= map.blockNumberThresholds[fork].get
|
||||
elif fork == MergeFork:
|
||||
# MergeFork is a special case that can use either block number or ttd;
|
||||
# block number takes precedence.
|
||||
let t = map.mergeForkTransitionThreshold
|
||||
if t.blockNumber.isSome:
|
||||
forkDeterminer.blockNumber >= t.blockNumber.get
|
||||
elif t.ttd.isSome and forkDeterminer.td.isSome:
|
||||
forkDeterminer.td.get >= t.ttd.get
|
||||
else:
|
||||
false
|
||||
elif fork <= HardFork.high:
|
||||
map.timeThresholds[fork].isSome and forkDeterminer.time.isSome and forkDeterminer.time.get >= map.timeThresholds[fork].get
|
||||
else:
|
||||
raise newException(Defect, "Why is this hard fork not in one of the above categories?")
|
||||
|
||||
type
|
||||
# if you add more fork block
|
||||
# please update forkBlockField constant too
|
||||
ChainConfig* = ref object
|
||||
@ -74,18 +167,24 @@ type
|
||||
arrowGlacierBlock* : Option[BlockNumber]
|
||||
grayGlacierBlock* : Option[BlockNumber]
|
||||
mergeForkBlock* : Option[BlockNumber]
|
||||
shanghaiBlock* : Option[BlockNumber]
|
||||
cancunBlock* : Option[BlockNumber]
|
||||
shanghaiTime* : Option[EthTime]
|
||||
cancunTime* : Option[EthTime]
|
||||
|
||||
clique* : CliqueOptions
|
||||
terminalTotalDifficulty*: Option[UInt256]
|
||||
consensusType*
|
||||
{.dontSerialize.} : ConsensusType
|
||||
|
||||
ForkToBlockNumber* = array[HardFork, Option[BlockNumber]]
|
||||
ForkOptional* = object
|
||||
# These are used for checking that the values of the fields
|
||||
# are in a valid order.
|
||||
BlockNumberBasedForkOptional* = object
|
||||
name*: string
|
||||
number*: Option[BlockNumber]
|
||||
TimeBasedForkOptional* = object
|
||||
name*: string
|
||||
time*: Option[EthTime]
|
||||
|
||||
|
||||
|
||||
const
|
||||
# this table is used for generate
|
||||
@ -107,32 +206,62 @@ const
|
||||
"arrowGlacierBlock",
|
||||
"grayGlacierBlock",
|
||||
"mergeForkBlock",
|
||||
"shanghaiBlock",
|
||||
"cancunBlock",
|
||||
]
|
||||
|
||||
# this table is used to generate
|
||||
# code to build fork to block number
|
||||
# array
|
||||
forkBlockNumber* = [
|
||||
Homestead: "homesteadBlock",
|
||||
DAOFork: "daoForkBlock",
|
||||
Tangerine: "eip150Block",
|
||||
Spurious: "eip158Block",
|
||||
Byzantium: "byzantiumBlock",
|
||||
Constantinople: "constantinopleBlock",
|
||||
Petersburg: "petersburgBlock",
|
||||
Istanbul: "istanbulBlock",
|
||||
MuirGlacier: "muirGlacierBlock",
|
||||
Berlin: "berlinBlock",
|
||||
London: "londonBlock",
|
||||
ArrowGlacier: "arrowGlacierBlock",
|
||||
GrayGlacier: "grayGlacierBlock",
|
||||
MergeFork: "mergeForkBlock",
|
||||
Shanghai: "shanghaiBlock",
|
||||
Cancun: "cancunBlock",
|
||||
forkTimeField* = [
|
||||
"shanghaiTime",
|
||||
"cancunTime",
|
||||
]
|
||||
|
||||
|
||||
func mergeForkTransitionThreshold*(conf: ChainConfig): MergeForkTransitionThreshold =
|
||||
MergeForkTransitionThreshold(blockNumber: conf.mergeForkBlock, ttd: conf.terminalTotalDifficulty)
|
||||
|
||||
proc toForkTransitionTable*(conf: ChainConfig): ForkTransitionTable =
|
||||
# We used to auto-generate this code from a list of
|
||||
# field names, but it doesn't seem worthwhile anymore
|
||||
# (now that there's irregularity due to block-based vs
|
||||
# timestamp-based forking).
|
||||
result.blockNumberThresholds[Frontier ] = some(0.toBlockNumber)
|
||||
result.blockNumberThresholds[Homestead ] = conf.homesteadBlock
|
||||
result.blockNumberThresholds[DAOFork ] = conf.daoForkBlock
|
||||
result.blockNumberThresholds[Tangerine ] = conf.eip150Block
|
||||
result.blockNumberThresholds[Spurious ] = conf.eip158Block
|
||||
result.blockNumberThresholds[Byzantium ] = conf.byzantiumBlock
|
||||
result.blockNumberThresholds[Constantinople] = conf.constantinopleBlock
|
||||
result.blockNumberThresholds[Petersburg ] = conf.petersburgBlock
|
||||
result.blockNumberThresholds[Istanbul ] = conf.istanbulBlock
|
||||
result.blockNumberThresholds[MuirGlacier ] = conf.muirGlacierBlock
|
||||
result.blockNumberThresholds[Berlin ] = conf.berlinBlock
|
||||
result.blockNumberThresholds[London ] = conf.londonBlock
|
||||
result.blockNumberThresholds[ArrowGlacier ] = conf.arrowGlacierBlock
|
||||
result.blockNumberThresholds[GrayGlacier ] = conf.grayGlacierBlock
|
||||
result.mergeForkTransitionThreshold = conf.mergeForkTransitionThreshold
|
||||
result.timeThresholds[Shanghai] = conf.shanghaiTime
|
||||
result.timeThresholds[Cancun] = conf.cancunTime
|
||||
|
||||
proc populateFromForkTransitionTable*(conf: ChainConfig, t: ForkTransitionTable) =
|
||||
conf.homesteadBlock = t.blockNumberThresholds[HardFork.Homestead]
|
||||
conf.daoForkBlock = t.blockNumberThresholds[HardFork.DAOFork]
|
||||
conf.eip150Block = t.blockNumberThresholds[HardFork.Tangerine]
|
||||
conf.eip155Block = t.blockNumberThresholds[HardFork.Spurious]
|
||||
conf.eip158Block = t.blockNumberThresholds[HardFork.Spurious]
|
||||
conf.byzantiumBlock = t.blockNumberThresholds[HardFork.Byzantium]
|
||||
conf.constantinopleBlock = t.blockNumberThresholds[HardFork.Constantinople]
|
||||
conf.petersburgBlock = t.blockNumberThresholds[HardFork.Petersburg]
|
||||
conf.istanbulBlock = t.blockNumberThresholds[HardFork.Istanbul]
|
||||
conf.muirGlacierBlock = t.blockNumberThresholds[HardFork.MuirGlacier]
|
||||
conf.berlinBlock = t.blockNumberThresholds[HardFork.Berlin]
|
||||
conf.londonBlock = t.blockNumberThresholds[HardFork.London]
|
||||
conf.arrowGlacierBlock = t.blockNumberThresholds[HardFork.ArrowGlacier]
|
||||
conf.grayGlacierBlock = t.blockNumberThresholds[HardFork.GrayGlacier]
|
||||
|
||||
conf.mergeForkBlock = t.mergeForkTransitionThreshold.blockNumber
|
||||
conf.terminalTotalDifficulty = t.mergeForkTransitionThreshold.ttd
|
||||
|
||||
conf.shanghaiTime = t.timeThresholds[HardFork.Shanghai]
|
||||
conf.cancunTime = t.timeThresholds[HardFork.Cancun]
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Map HardFork to EVM/EVMC Fork
|
||||
# ------------------------------------------------------------------------------
|
||||
@ -201,8 +330,15 @@ func toNextFork(n: Option[BlockNumber]): uint64 =
|
||||
else:
|
||||
0'u64
|
||||
|
||||
func getNextFork(c: ChainConfig, fork: HardFork): uint64 =
|
||||
let next: array[HardFork, uint64] = [
|
||||
# EIP-6122: ForkID now works with timestamps too.
|
||||
func toNextFork(t: Option[EthTime]): uint64 =
|
||||
if t.isSome:
|
||||
t.get.toUnix.uint64
|
||||
else:
|
||||
0'u64
|
||||
|
||||
func arrayMappingHardForkToNextFork(c: ChainConfig): array[HardFork, uint64] =
|
||||
return [
|
||||
0'u64,
|
||||
toNextFork(c.homesteadBlock),
|
||||
toNextFork(c.daoForkBlock),
|
||||
@ -218,10 +354,11 @@ func getNextFork(c: ChainConfig, fork: HardFork): uint64 =
|
||||
toNextFork(c.arrowGlacierBlock),
|
||||
toNextFork(c.grayGlacierBlock),
|
||||
toNextFork(c.mergeForkBlock),
|
||||
toNextFork(c.shanghaiBlock),
|
||||
toNextFork(c.cancunBlock),
|
||||
toNextFork(c.shanghaiTime),
|
||||
toNextFork(c.cancunTime),
|
||||
]
|
||||
|
||||
func getNextFork(next: array[HardFork, uint64], fork: HardFork): uint64 =
|
||||
if fork == high(HardFork):
|
||||
result = 0
|
||||
return
|
||||
@ -232,9 +369,9 @@ func getNextFork(c: ChainConfig, fork: HardFork): uint64 =
|
||||
result = next[x]
|
||||
break
|
||||
|
||||
func calculateForkId(c: ChainConfig, fork: HardFork,
|
||||
func calculateForkId(next: array[HardFork, uint64], fork: HardFork,
|
||||
prevCRC: uint32, prevFork: uint64): ForkID =
|
||||
result.nextFork = c.getNextFork(fork)
|
||||
result.nextFork = getNextFork(next, fork)
|
||||
|
||||
if result.nextFork != prevFork:
|
||||
result.crc = crc32(prevCRC, toBytesBE(prevFork))
|
||||
@ -243,70 +380,16 @@ func calculateForkId(c: ChainConfig, fork: HardFork,
|
||||
|
||||
func calculateForkIds*(c: ChainConfig,
|
||||
genesisCRC: uint32): array[HardFork, ForkID] =
|
||||
let next = arrayMappingHardForkToNextFork(c)
|
||||
|
||||
var prevCRC = genesisCRC
|
||||
var prevFork = c.getNextFork(Frontier)
|
||||
var prevFork = getNextFork(next, Frontier)
|
||||
|
||||
for fork in HardFork:
|
||||
result[fork] = calculateForkId(c, fork, prevCRC, prevFork)
|
||||
result[fork] = calculateForkId(next, fork, prevCRC, prevFork)
|
||||
prevFork = result[fork].nextFork
|
||||
prevCRC = result[fork].crc
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# BlockNumber + TD comparator
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
type
|
||||
BlockToForkFunc* = proc(data, number, td: UInt256): bool
|
||||
{.gcsafe, noSideEffect, nimcall, raises: [Defect, CatchableError].}
|
||||
|
||||
BlockToFork* = object
|
||||
# `data` can be blockNumber or TTD
|
||||
data* : UInt256
|
||||
toFork*: BlockToForkFunc
|
||||
|
||||
BlockToForks* = array[HardFork, BlockToFork]
|
||||
|
||||
func forkTrue(data, number, td: UInt256): bool
|
||||
{.gcsafe, nimcall, raises: [].} =
|
||||
# frontier always return true
|
||||
true
|
||||
|
||||
func forkFalse(data, number, td: UInt256): bool
|
||||
{.gcsafe, nimcall, raises: [].} =
|
||||
# forkBlock.isNone always return false
|
||||
false
|
||||
|
||||
func forkMaybe(data, number, td: UInt256): bool
|
||||
{.gcsafe, nimcall, raises: [].} =
|
||||
# data is a blockNumber
|
||||
number >= data
|
||||
|
||||
func mergeMaybe(data, number, td: UInt256): bool
|
||||
{.gcsafe, nimcall, raises: [].} =
|
||||
# data is a TTD
|
||||
td >= data
|
||||
|
||||
proc blockToForks*(conf: ChainConfig, map: ForkToBlockNumber): BlockToForks =
|
||||
# between Frontier and latest HardFork
|
||||
# can be a match or not
|
||||
for fork, number in map:
|
||||
if number.isSome:
|
||||
result[fork].data = number.get()
|
||||
result[fork].toFork = forkMaybe
|
||||
else:
|
||||
result[fork].toFork = forkFalse
|
||||
|
||||
# Frontier always return true
|
||||
result[Frontier].toFork = forkTrue
|
||||
|
||||
# special case for MergeFork
|
||||
# if MergeForkBlock.isSome, it takes precedence over TTD
|
||||
# if MergeForkBlock.isNone, compare TD with TTD
|
||||
if map[MergeFork].isNone and
|
||||
conf.terminalTotalDifficulty.isSome:
|
||||
result[MergeFork].data = conf.terminalTotalDifficulty.get()
|
||||
result[MergeFork].toFork = mergeMaybe
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# End
|
||||
# ------------------------------------------------------------------------------
|
||||
|
@ -127,7 +127,7 @@ proc processTransaction*(
|
||||
{.gcsafe, raises: [CatchableError].} =
|
||||
## Variant of `processTransaction()` with `*fork* derived
|
||||
## from the `vmState` argument.
|
||||
let fork = vmState.com.toEVMFork(header.blockNumber)
|
||||
let fork = vmState.com.toEVMFork(header.forkDeterminationInfoForHeader)
|
||||
vmState.processTransaction(tx, sender, header, fork)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
@ -172,7 +172,7 @@ template calcDifficultyGrayGlacier*(timeStamp: EthTime, parent: BlockHeader): Di
|
||||
makeDifficultyCalculator(11_400_000, timeStamp, parent)
|
||||
|
||||
func calcDifficulty*(com: CommonRef, timeStamp: EthTime, parent: BlockHeader): DifficultyInt =
|
||||
let next = com.toHardFork(parent.blockNumber + bigOne)
|
||||
let next = com.toHardFork(parent.forkDeterminationInfoForHeader.adjustForNextBlock)
|
||||
if next >= GrayGlacier:
|
||||
result = calcDifficultyGrayGlacier(timeStamp, parent)
|
||||
elif next >= ArrowGlacier:
|
||||
|
@ -106,7 +106,7 @@ proc resetTxEnv(dh: TxChainRef; parent: BlockHeader; fee: Option[UInt256])
|
||||
|
||||
# do hardfork transition before
|
||||
# BaseVMState querying any hardfork/consensus from CommonRef
|
||||
dh.com.hardForkTransition(parent.blockHash, parent.blockNumber+1)
|
||||
dh.com.hardForkTransition(parent.blockHash, parent.blockNumber+1, some(parent.timestamp.adjustForNextBlock))
|
||||
dh.prepareHeader(parent)
|
||||
|
||||
# we don't consider PoS difficulty here
|
||||
@ -249,7 +249,7 @@ proc baseFee*(dh: TxChainRef): GasPrice =
|
||||
|
||||
proc nextFork*(dh: TxChainRef): EVMFork =
|
||||
## Getter, fork of next block
|
||||
dh.com.toEVMFork(dh.txEnv.vmState.blockNumber)
|
||||
dh.com.toEVMFork(dh.txEnv.vmState.forkDeterminationInfoForVMState)
|
||||
|
||||
proc gasUsed*(dh: TxChainRef): GasInt =
|
||||
## Getter, accumulated gas burned for collected blocks
|
||||
|
@ -35,8 +35,9 @@ proc baseFeeGet*(com: CommonRef; parent: BlockHeader): GasPrice =
|
||||
|
||||
# Note that the baseFee is calculated for the next header
|
||||
let
|
||||
parentFork = com.toEVMFork(parent.blockNumber)
|
||||
nextFork = com.toEVMFork(parent.blockNumber + 1)
|
||||
forkDeterminer = forkDeterminationInfoForHeader(parent)
|
||||
parentFork = com.toEVMFork(forkDeterminer)
|
||||
nextFork = com.toEVMFork(forkDeterminer.adjustForNextBlock)
|
||||
|
||||
if nextFork < FkLondon:
|
||||
return 0.GasPrice
|
||||
|
@ -379,3 +379,9 @@ proc buildWitness*(vmState: BaseVMState): seq[byte]
|
||||
# build witness from tree
|
||||
var wb = initWitnessBuilder(vmState.com.db.db, rootHash, flags)
|
||||
wb.buildWitness(mkeys)
|
||||
|
||||
func forkDeterminationInfoForVMState*(vmState: BaseVMState): ForkDeterminationInfo =
|
||||
# FIXME-Adam: Is this timestamp right? Note that up above in blockNumber we add 1;
|
||||
# should timestamp be adding 12 or something?
|
||||
# Also, can I get the TD? Do I need to?
|
||||
forkDeterminationInfo(vmState.blockNumber, vmState.timestamp)
|
||||
|
@ -33,7 +33,7 @@ proc setupTxContext*(vmState: BaseVMState, origin: EthAddress, gasPrice: GasInt,
|
||||
if forkOverride.isSome:
|
||||
forkOverride.get
|
||||
else:
|
||||
vmState.com.toEVMFork(vmState.blockNumber)
|
||||
vmState.com.toEVMFork(vmState.forkDeterminationInfoForVMState)
|
||||
vmState.gasCosts = vmState.fork.forkToSchedule
|
||||
|
||||
|
||||
|
@ -393,7 +393,7 @@ proc setupEthRpc*(
|
||||
var
|
||||
idx = 0
|
||||
prevGasUsed = GasInt(0)
|
||||
fork = com.toEVMFork(header.blockNumber)
|
||||
fork = com.toEVMFork(header.forkDeterminationInfoForHeader)
|
||||
|
||||
for receipt in chainDB.getReceipts(header.receiptRoot):
|
||||
let gasUsed = receipt.cumulativeGasUsed - prevGasUsed
|
||||
|
@ -385,7 +385,7 @@ method getStatus*(ctx: EthWireRef): EthState
|
||||
db = ctx.db
|
||||
com = ctx.chain.com
|
||||
bestBlock = db.getCanonicalHead()
|
||||
forkId = com.forkId(bestBlock.blockNumber)
|
||||
forkId = com.forkId(bestBlock.forkDeterminationInfoForHeader)
|
||||
|
||||
EthState(
|
||||
totalDifficulty: db.headTotalDifficulty,
|
||||
|
@ -101,7 +101,7 @@ proc rpcEstimateGas*(cd: RpcCallData, header: BlockHeader, com: CommonRef, gasCa
|
||||
gasLimit: 0.GasInt, ## ???
|
||||
fee: UInt256.none()) ## ???
|
||||
let vmState = BaseVMState.new(topHeader, com)
|
||||
let fork = com.toEVMFork(header.blockNumber)
|
||||
let fork = com.toEVMFork(vmState.forkDeterminationInfoForVMState)
|
||||
let txGas = gasFees[fork][GasTransaction] # txGas always 21000, use constants?
|
||||
var params = toCallParams(vmState, cd, gasCap, header.fee)
|
||||
|
||||
|
@ -24,6 +24,7 @@ export
|
||||
vms.enableTracing,
|
||||
vms.tracingEnabled,
|
||||
vms.baseFee,
|
||||
vms.forkDeterminationInfoForVMState,
|
||||
vms.generateWitness,
|
||||
vms.`generateWitness=`,
|
||||
vms.getAncestorHash,
|
||||
|
@ -174,7 +174,7 @@ proc importBlock(tester: var Tester, com: CommonRef,
|
||||
|
||||
let parentHeader = com.db.getBlockHeader(tb.header.parentHash)
|
||||
let td = some(com.db.getScore(tb.header.parentHash))
|
||||
com.hardForkTransition(tb.header.blockNumber, td)
|
||||
com.hardForkTransition(tb.header.blockNumber, td, some(tb.header.timestamp))
|
||||
|
||||
tester.vmState = BaseVMState.new(
|
||||
parentHeader,
|
||||
|
@ -237,7 +237,7 @@ proc genesisLoadRunner(noisy = true;
|
||||
params = params)
|
||||
|
||||
check mcom.ttd.get == sSpcs.termTotalDff
|
||||
check mcom.toHardFork(sSpcs.mergeFork.toBlockNumber) == MergeFork
|
||||
check mcom.toHardFork(sSpcs.mergeFork.toBlockNumber.blockNumberToForkDeterminationInfo) == MergeFork
|
||||
|
||||
test &"Construct persistent ChainDBRef on {tmpDir}, {persistPruneInfo}":
|
||||
if disablePersistentDB:
|
||||
@ -257,7 +257,7 @@ proc genesisLoadRunner(noisy = true;
|
||||
params = params)
|
||||
|
||||
check dcom.ttd.get == sSpcs.termTotalDff
|
||||
check dcom.toHardFork(sSpcs.mergeFork.toBlockNumber) == MergeFork
|
||||
check dcom.toHardFork(sSpcs.mergeFork.toBlockNumber.blockNumberToForkDeterminationInfo) == MergeFork
|
||||
|
||||
test "Initialise in-memory Genesis":
|
||||
mcom.initializeEmptyDb
|
||||
|
@ -92,7 +92,7 @@ template runTest(network: untyped, name: string) =
|
||||
com = CommonRef.new(newMemoryDB(), true, network, params)
|
||||
|
||||
for x in `network IDs`:
|
||||
let id = com.forkId(x.blockNumber.toBlockNumber)
|
||||
let id = com.forkId(x.blockNumber.toBlockNumber.blockNumberToForkDeterminationInfo)
|
||||
check id.crc == x.id.crc
|
||||
check id.nextFork == x.id.nextFork
|
||||
|
||||
|
@ -98,7 +98,7 @@ proc testFixtureIndexes(tester: Tester, testStatusIMPL: var TestStatus) =
|
||||
|
||||
var gasUsed: GasInt
|
||||
let sender = tester.tx.getSender()
|
||||
let fork = com.toEVMFork(tester.header.blockNumber)
|
||||
let fork = com.toEVMFork(tester.header.forkDeterminationInfoForHeader)
|
||||
|
||||
vmState.mutateStateDB:
|
||||
setupStateDB(tester.pre, db)
|
||||
|
@ -9,104 +9,112 @@
|
||||
# according to those terms.
|
||||
|
||||
import
|
||||
std/times,
|
||||
../../nimbus/common/common,
|
||||
./types
|
||||
|
||||
export
|
||||
types
|
||||
|
||||
const
|
||||
BlockNumberZero: BlockNumber = 0.toBlockNumber
|
||||
BlockNumberFive: BlockNumber = 5.toBlockNumber
|
||||
TimeZero: EthTime = fromUnix(0)
|
||||
|
||||
proc createForkTransitionTable(transitionFork: HardFork, b: Option[BlockNumber], t: Option[EthTime], ttd: Option[DifficultyInt]): ForkTransitionTable =
|
||||
|
||||
proc blockNumberToUse(f: HardFork): Option[BlockNumber] =
|
||||
if f < transitionFork:
|
||||
some(BlockNumberZero)
|
||||
elif f == transitionFork:
|
||||
b
|
||||
else:
|
||||
none(BlockNumber)
|
||||
|
||||
proc timeToUse(f: HardFork): Option[EthTime] =
|
||||
if f < transitionFork:
|
||||
some(TimeZero)
|
||||
elif f == transitionFork:
|
||||
t
|
||||
else:
|
||||
none(EthTime)
|
||||
|
||||
for f in low(HardFork) .. lastPurelyBlockNumberBasedFork:
|
||||
result.blockNumberThresholds[f] = blockNumberToUse(f)
|
||||
|
||||
result.mergeForkTransitionThreshold.blockNumber = blockNumberToUse(HardFork.MergeFork)
|
||||
result.mergeForkTransitionThreshold.ttd = ttd
|
||||
|
||||
for f in firstTimeBasedFork .. high(HardFork):
|
||||
result.timeThresholds[f] = timeToUse(f)
|
||||
|
||||
proc assignNumber(c: ChainConfig, transitionFork: HardFork, n: BlockNumber) =
|
||||
let table = createForkTransitionTable(transitionFork, some(n), none(EthTime), none(DifficultyInt))
|
||||
c.populateFromForkTransitionTable(table)
|
||||
|
||||
proc assignTime(c: ChainConfig, transitionFork: HardFork, t: EthTime) =
|
||||
let table = createForkTransitionTable(transitionFork, none(BlockNumber), some(t), none(DifficultyInt))
|
||||
c.populateFromForkTransitionTable(table)
|
||||
|
||||
func getChainConfig*(network: string, c: ChainConfig) =
|
||||
const
|
||||
Zero = 0.toBlockNumber
|
||||
Five = 5.toBlockNumber
|
||||
|
||||
proc assignNumber(c: ChainConfig,
|
||||
fork: HardFork, n: BlockNumber) =
|
||||
var number: array[HardFork, Option[BlockNumber]]
|
||||
var z = low(HardFork)
|
||||
while z < fork:
|
||||
number[z] = some(Zero)
|
||||
z = z.succ
|
||||
number[fork] = some(n)
|
||||
z = high(HardFork)
|
||||
while z > fork:
|
||||
number[z] = none(BlockNumber)
|
||||
z = z.pred
|
||||
|
||||
c.homesteadBlock = number[HardFork.Homestead]
|
||||
c.daoForkBlock = number[HardFork.DAOFork]
|
||||
c.eip150Block = number[HardFork.Tangerine]
|
||||
c.eip155Block = number[HardFork.Spurious]
|
||||
c.eip158Block = number[HardFork.Spurious]
|
||||
c.byzantiumBlock = number[HardFork.Byzantium]
|
||||
c.constantinopleBlock = number[HardFork.Constantinople]
|
||||
c.petersburgBlock = number[HardFork.Petersburg]
|
||||
c.istanbulBlock = number[HardFork.Istanbul]
|
||||
c.muirGlacierBlock = number[HardFork.MuirGlacier]
|
||||
c.berlinBlock = number[HardFork.Berlin]
|
||||
c.londonBlock = number[HardFork.London]
|
||||
c.arrowGlacierBlock = number[HardFork.ArrowGlacier]
|
||||
c.grayGlacierBlock = number[HardFork.GrayGlacier]
|
||||
c.mergeForkBlock = number[HardFork.MergeFork]
|
||||
c.shanghaiBlock = number[HardFork.Shanghai]
|
||||
c.cancunBlock = number[HardFork.Cancun]
|
||||
|
||||
c.daoForkSupport = false
|
||||
c.chainId = 1.ChainId
|
||||
c.terminalTotalDifficulty = none(UInt256)
|
||||
|
||||
case network
|
||||
of $TestFork.Frontier:
|
||||
c.assignNumber(HardFork.Frontier, Zero)
|
||||
c.assignNumber(HardFork.Frontier, BlockNumberZero)
|
||||
of $TestFork.Homestead:
|
||||
c.assignNumber(HardFork.Homestead, Zero)
|
||||
c.assignNumber(HardFork.Homestead, BlockNumberZero)
|
||||
of $TestFork.EIP150:
|
||||
c.assignNumber(HardFork.Tangerine, Zero)
|
||||
c.assignNumber(HardFork.Tangerine, BlockNumberZero)
|
||||
of $TestFork.EIP158:
|
||||
c.assignNumber(HardFork.Spurious, Zero)
|
||||
c.assignNumber(HardFork.Spurious, BlockNumberZero)
|
||||
of $TestFork.Byzantium:
|
||||
c.assignNumber(HardFork.Byzantium, Zero)
|
||||
c.assignNumber(HardFork.Byzantium, BlockNumberZero)
|
||||
of $TestFork.Constantinople:
|
||||
c.assignNumber(HardFork.Constantinople, Zero)
|
||||
c.assignNumber(HardFork.Constantinople, BlockNumberZero)
|
||||
of $TestFork.ConstantinopleFix:
|
||||
c.assignNumber(HardFork.Petersburg, Zero)
|
||||
c.assignNumber(HardFork.Petersburg, BlockNumberZero)
|
||||
of $TestFork.Istanbul:
|
||||
c.assignNumber(HardFork.Istanbul, Zero)
|
||||
c.assignNumber(HardFork.Istanbul, BlockNumberZero)
|
||||
of $TestFork.FrontierToHomesteadAt5:
|
||||
c.assignNumber(HardFork.Homestead, Five)
|
||||
c.assignNumber(HardFork.Homestead, BlockNumberFive)
|
||||
of $TestFork.HomesteadToEIP150At5:
|
||||
c.assignNumber(HardFork.Tangerine, Five)
|
||||
c.assignNumber(HardFork.Tangerine, BlockNumberFive)
|
||||
of $TestFork.HomesteadToDaoAt5:
|
||||
c.assignNumber(HardFork.DAOFork, Five)
|
||||
c.assignNumber(HardFork.DAOFork, BlockNumberFive)
|
||||
c.daoForkSupport = true
|
||||
of $TestFork.EIP158ToByzantiumAt5:
|
||||
c.assignNumber(HardFork.Byzantium, Five)
|
||||
c.assignNumber(HardFork.Byzantium, BlockNumberFive)
|
||||
of $TestFork.ByzantiumToConstantinopleAt5:
|
||||
c.assignNumber(HardFork.Constantinople, Five)
|
||||
c.assignNumber(HardFork.Constantinople, BlockNumberFive)
|
||||
of $TestFork.ByzantiumToConstantinopleFixAt5:
|
||||
c.assignNumber(HardFork.Petersburg, Five)
|
||||
c.constantinopleBlock = some(Five)
|
||||
c.assignNumber(HardFork.Petersburg, BlockNumberFive)
|
||||
c.constantinopleBlock = some(BlockNumberFive)
|
||||
of $TestFork.ConstantinopleFixToIstanbulAt5:
|
||||
c.assignNumber(HardFork.Istanbul, Five)
|
||||
c.assignNumber(HardFork.Istanbul, BlockNumberFive)
|
||||
of $TestFork.Berlin:
|
||||
c.assignNumber(HardFork.Berlin, Zero)
|
||||
c.assignNumber(HardFork.Berlin, BlockNumberZero)
|
||||
of $TestFork.BerlinToLondonAt5:
|
||||
c.assignNumber(HardFork.London, Five)
|
||||
c.assignNumber(HardFork.London, BlockNumberFive)
|
||||
of $TestFork.London:
|
||||
c.assignNumber(HardFork.London, Zero)
|
||||
c.assignNumber(HardFork.London, BlockNumberZero)
|
||||
of $TestFork.ArrowGlacier:
|
||||
c.assignNumber(HardFork.ArrowGlacier, Zero)
|
||||
c.assignNumber(HardFork.ArrowGlacier, BlockNumberZero)
|
||||
of $TestFork.GrayGlacier:
|
||||
c.assignNumber(HardFork.GrayGlacier, Zero)
|
||||
c.assignNumber(HardFork.GrayGlacier, BlockNumberZero)
|
||||
of $TestFork.Merge:
|
||||
c.assignNumber(HardFork.MergeFork, Zero)
|
||||
c.assignNumber(HardFork.MergeFork, BlockNumberZero)
|
||||
of $TestFork.ArrowGlacierToMergeAtDiffC0000:
|
||||
c.assignNumber(HardFork.GrayGlacier, Zero)
|
||||
c.assignNumber(HardFork.GrayGlacier, BlockNumberZero)
|
||||
c.terminalTotalDifficulty = some(0xC0000.u256)
|
||||
of $TestFork.Shanghai:
|
||||
c.assignNumber(HardFork.Shanghai, Zero)
|
||||
c.assignTime(HardFork.Shanghai, TimeZero)
|
||||
of $TestFork.MergeToShanghaiAtTime15k:
|
||||
c.assignTime(HardFork.Shanghai, fromUnix(15000))
|
||||
of $TestFork.Cancun:
|
||||
c.assignNumber(HardFork.Cancun, Zero)
|
||||
c.assignTime(HardFork.Cancun, TimeZero)
|
||||
else:
|
||||
raise newException(ValueError, "unsupported network " & network)
|
||||
|
||||
|
@ -33,6 +33,7 @@ type
|
||||
Merge
|
||||
ArrowGlacierToMergeAtDiffC0000
|
||||
Shanghai
|
||||
MergeToShanghaiAtTime15k
|
||||
Cancun
|
||||
|
||||
LogLevel* = enum
|
||||
|
@ -200,7 +200,7 @@ proc runExecution(ctx: var StateContext, conf: StateConf, pre: JsonNode): StateR
|
||||
let
|
||||
com = CommonRef.new(newMemoryDB(), ctx.chainConfig, pruneTrie = false)
|
||||
parent = BlockHeader(stateRoot: emptyRlpHash)
|
||||
fork = com.toEVMFork(ctx.header.blockNumber)
|
||||
fork = com.toEVMFork(ctx.header.forkDeterminationInfoForHeader)
|
||||
|
||||
let vmState = TestVMState()
|
||||
vmState.init(
|
||||
|
Loading…
x
Reference in New Issue
Block a user