From 28cdfcaf6bd83b81be1e4adabe781af39f327c9a Mon Sep 17 00:00:00 2001 From: jangko Date: Tue, 8 Feb 2022 16:17:59 +0700 Subject: [PATCH] fix EIP-4399 'random' opcode - fix previous implementation of EIP-4399 - now `random` opcode can be used with evmc_enabled --- nimbus/db/db_chain.nim | 13 ++++++ nimbus/forks.nim | 3 -- nimbus/p2p/executor/calculate_reward.nim | 5 +-- nimbus/transaction/host_services.nim | 6 +-- nimbus/utils/tx_pool/tx_chain.nim | 22 +++++++--- nimbus/vm/computation.nim | 9 ----- nimbus/vm/evmc_host.nim | 5 +-- nimbus/vm/interpreter/gas_costs.nim | 8 +--- nimbus/vm/interpreter/opcodes_impl.nim | 5 --- nimbus/vm/interpreter_dispatch.nim | 17 +------- nimbus/vm/state.nim | 24 +++++++++-- nimbus/vm/types.nim | 1 + nimbus/vm2/computation.nim | 3 -- nimbus/vm2/interpreter/gas_costs.nim | 9 +---- .../interpreter/op_handlers/oph_blockdata.nim | 15 +------ .../vm2/interpreter/op_handlers/oph_defs.nim | 3 -- nimbus/vm2/state.nim | 22 +++++++++- nimbus/vm2/types.nim | 1 + tests/test_op_env.nim | 40 +++++++++---------- 19 files changed, 102 insertions(+), 109 deletions(-) diff --git a/nimbus/db/db_chain.nim b/nimbus/db/db_chain.nim index ce5b931f5..f985bce98 100644 --- a/nimbus/db/db_chain.nim +++ b/nimbus/db/db_chain.nim @@ -19,6 +19,7 @@ type networkId*: NetworkId config* : ChainConfig genesis* : Genesis + totalDifficulty*: DifficultyInt # startingBlock, currentBlock, and highestBlock # are progress indicator @@ -30,6 +31,16 @@ type blockNumber: BlockNumber index: int +proc getTotalDifficulty*(self: BaseChainDB): UInt256 = + # this is actually a combination of `getHash` and `getScore` + const key = canonicalHeadHashKey() + let data = self.db.get(key.toOpenArray) + if data.len == 0: + return 0.u256 + + let blockHash = rlp.decode(data, Hash256) + rlp.decode(self.db.get(blockHashToScoreKey(blockHash).toOpenArray), Uint256) + proc newBaseChainDB*( db: TrieDatabaseRef, pruneTrie: bool = true, @@ -42,6 +53,7 @@ proc newBaseChainDB*( result.networkId = id result.config = params.config result.genesis = params.genesis + result.totalDifficulty = result.getTotalDifficulty() proc `$`*(db: BaseChainDB): string = result = "BaseChainDB" @@ -335,6 +347,7 @@ proc persistHeaderToDb*(self: BaseChainDB; header: BlockHeader): seq[BlockHeader return self.setAsCanonicalChainHead(headerHash) if score > headScore: + self.totalDifficulty = score result = self.setAsCanonicalChainHead(headerHash) proc persistUncles*(self: BaseChainDB, uncles: openarray[BlockHeader]): Hash256 = diff --git a/nimbus/forks.nim b/nimbus/forks.nim index b0a033e72..12ac040f2 100644 --- a/nimbus/forks.nim +++ b/nimbus/forks.nim @@ -18,6 +18,3 @@ type FkIstanbul = "Istanbul" FkBerlin = "Berlin" FkLondon = "London" - # TODO: PostMerge is a temporary name - # until we have an official name - FkPostMerge = "PostMerge" diff --git a/nimbus/p2p/executor/calculate_reward.nim b/nimbus/p2p/executor/calculate_reward.nim index 54c5f9afb..85f3b5e38 100644 --- a/nimbus/p2p/executor/calculate_reward.nim +++ b/nimbus/p2p/executor/calculate_reward.nim @@ -38,9 +38,8 @@ const eth2, # FkPetersburg eth2, # FkIstanbul eth2, # FkBerlin - eth2, # FkLondon - eth0 # FkPostMerge - ] + eth2 # FkLondon + ] {.push raises: [Defect].} diff --git a/nimbus/transaction/host_services.nim b/nimbus/transaction/host_services.nim index 4575292bf..2bf5a4c63 100644 --- a/nimbus/transaction/host_services.nim +++ b/nimbus/transaction/host_services.nim @@ -73,11 +73,7 @@ proc setupTxContext(host: TransactionHost) = # EIP-4399 # Transfer block randomness to difficulty OPCODE let difficulty = vmState.difficulty.toEvmc - if difficulty.isZero: - # no flipping, because hash is a 32 bytes array - host.txContext.block_difficulty = vmState.random.toEvmc - else: - host.txContext.block_difficulty = flip256(difficulty) + host.txContext.block_difficulty = flip256(difficulty) host.cachedTxContext = true diff --git a/nimbus/utils/tx_pool/tx_chain.nim b/nimbus/utils/tx_pool/tx_chain.nim index 033e3b80d..a8e5c517a 100644 --- a/nimbus/utils/tx_pool/tx_chain.nim +++ b/nimbus/utils/tx_pool/tx_chain.nim @@ -66,6 +66,10 @@ type limits: TxChainGasLimits ## Gas limits for packer and next header txEnv: TxChainPackerEnv ## Assorted parameters, tx packer environment + # EIP-4399 and EIP-3675 + ttdReached: bool ## Total Terminal Difficulty reached + random: Hash256 ## POS block randomness + # ------------------------------------------------------------------------------ # Private functions # ------------------------------------------------------------------------------ @@ -78,13 +82,11 @@ proc resetTxEnv(dh: TxChainRef; parent: BlockHeader; fee: Option[UInt256]) parent = parent, timestamp = getTime().utc.toTime, gasLimit = (if dh.maxMode: dh.limits.maxLimit else: dh.limits.trgLimit), - fee = fee, - # EIP-4399 extra complexity - # TODO: make sure from where or what value - # this `random` param should be - random = Hash256(), + fee = fee, + random = dh.random, miner = dh.miner, - chainDB = dh.db) + chainDB = dh.db, + ttdReached= dh.ttdReached) dh.txEnv.txRoot = BLANK_ROOT_HASH dh.txEnv.stateRoot = dh.txEnv.vmState.parent.stateRoot @@ -307,6 +309,14 @@ proc `txRoot=`*(dh: TxChainRef; val: Hash256) = ## Setter dh.txEnv.txRoot = val +proc `ttdReached=`*(dh: TxChainRef; val: bool) = + ## Setter + dh.ttdReached = val + +proc `random=`*(dh: TxChainRef; val: Hash256) = + ## Setter + dh.random = val + # ------------------------------------------------------------------------------ # End # ------------------------------------------------------------------------------ diff --git a/nimbus/vm/computation.nim b/nimbus/vm/computation.nim index 12ebd0883..4010721f8 100644 --- a/nimbus/vm/computation.nim +++ b/nimbus/vm/computation.nim @@ -51,15 +51,6 @@ template getDifficulty*(c: Computation): DifficultyInt = else: c.vmState.difficulty -template getRandom*(c: Computation): Hash256 = - when evmc_enabled: - # EIP-4399 - # no flipping because `block_difficulty` in this context - # is a 32 bytes array - Hash256.fromEvmc c.host.getTxContext().block_difficulty - else: - c.vmState.random - template getGasLimit*(c: Computation): GasInt = when evmc_enabled: c.host.getTxContext().block_gas_limit.GasInt diff --git a/nimbus/vm/evmc_host.nim b/nimbus/vm/evmc_host.nim index 8e9de99ac..b822fc17d 100644 --- a/nimbus/vm/evmc_host.nim +++ b/nimbus/vm/evmc_host.nim @@ -20,10 +20,7 @@ proc hostGetTxContextImpl(ctx: Computation): nimbus_tx_context {.cdecl.} = # EIP-4399 # Transfer block randomness to difficulty OPCODE let difficulty = toEvmc(vmstate.difficulty) - if difficulty == default(evmc_bytes32): # or difficulty.isZero - result.block_difficulty = vmState.random.toEvmc - else: - result.block_difficulty = difficulty + result.block_difficulty = difficulty result.chain_id = toEvmc(vmstate.chaindb.config.chainId.uint.u256) result.block_base_fee = toEvmc(vmstate.baseFee) diff --git a/nimbus/vm/interpreter/gas_costs.nim b/nimbus/vm/interpreter/gas_costs.nim index 99c861fec..0ad1cbc8b 100644 --- a/nimbus/vm/interpreter/gas_costs.nim +++ b/nimbus/vm/interpreter/gas_costs.nim @@ -761,8 +761,7 @@ const FkPetersburg: SpuriousGasFees, FkIstanbul: IstanbulGasFees, FkBerlin: BerlinGasFees, - FkLondon: LondonGasFees, - FkPostMerge: LondonGasFees + FkLondon: LondonGasFees ] @@ -774,7 +773,6 @@ gasCosts(FkConstantinople, constantinople, ConstantinopleGasCosts) gasCosts(FkIstanbul, istanbul, IstanbulGasCosts) gasCosts(FkBerlin, berlin, BerlinGasCosts) gasCosts(FkLondon, london, LondonGasCosts) -gasCosts(FkPostMerge, postMerge, PostMergeGasCosts) proc forkToSchedule*(fork: Fork): GasCosts = if fork < FkHomestead: @@ -791,10 +789,8 @@ proc forkToSchedule*(fork: Fork): GasCosts = IstanbulGasCosts elif fork < FkLondon: BerlinGasCosts - elif fork < FkPostMerge: - LondonGasCosts else: - PostMergeGasCosts + LondonGasCosts const ## Precompile costs diff --git a/nimbus/vm/interpreter/opcodes_impl.nim b/nimbus/vm/interpreter/opcodes_impl.nim index 8f583a93d..9b4a8622d 100644 --- a/nimbus/vm/interpreter/opcodes_impl.nim +++ b/nimbus/vm/interpreter/opcodes_impl.nim @@ -412,11 +412,6 @@ op difficulty, inline = true: ## 0x44, Get the block's difficulty push: c.getDifficulty() -op randomEIP4399, inline = true: - ## since EIP-4399 0x44 renamed from `DIFFICULTY` to `RANDOM` - ## 0x44, Get the block's randomness - push: c.getRandom() - op gasLimit, inline = true: ## 0x45, Get the block's gas limit push: c.getGasLimit() diff --git a/nimbus/vm/interpreter_dispatch.nim b/nimbus/vm/interpreter_dispatch.nim index fcad86fd3..3fcc7e77b 100644 --- a/nimbus/vm/interpreter_dispatch.nim +++ b/nimbus/vm/interpreter_dispatch.nim @@ -254,13 +254,6 @@ proc genLondonJumpTable(ops: array[Op, NimNode]): array[Op, NimNode] {.compileTi let LondonOpDispatch {.compileTime.}: array[Op, NimNode] = genLondonJumpTable(BerlinOpDispatch) -proc genPostMergeJumpTable(ops: array[Op, NimNode]): array[Op, NimNode] {.compileTime.} = - result = ops - # EIP-4399 - result[Random] = newIdentNode "randomEIP4399" - -let PostMergeOpDispatch {.compileTime.}: array[Op, NimNode] = genPostMergeJumpTable(LondonOpDispatch) - proc opTableToCaseStmt(opTable: array[Op, NimNode], c: NimNode): NimNode = let instr = quote do: `c`.instr @@ -352,9 +345,6 @@ macro genBerlinDispatch(c: Computation): untyped = macro genLondonDispatch(c: Computation): untyped = result = opTableToCaseStmt(LondonOpDispatch, c) -macro genPostMergeDispatch(c: Computation): untyped = - result = opTableToCaseStmt(PostMergeOpDispatch, c) - proc frontierVM(c: Computation) = genFrontierDispatch(c) @@ -385,9 +375,6 @@ proc berlinVM(c: Computation) {.gcsafe.} = proc londonVM(c: Computation) {.gcsafe.} = genLondonDispatch(c) -proc postMergeVM(c: Computation) {.gcsafe.} = - genPostMergeDispatch(c) - proc selectVM(c: Computation, fork: Fork) {.gcsafe.} = # TODO: Optimise getting fork and updating opCodeExec only when necessary case fork @@ -409,10 +396,8 @@ proc selectVM(c: Computation, fork: Fork) {.gcsafe.} = c.istanbulVM() of FkBerlin: c.berlinVM() - of FkLondon: - c.londonVM() else: - c.postMergeVM() + c.londonVM() proc executeOpcodes(c: Computation) = let fork = c.fork diff --git a/nimbus/vm/state.nim b/nimbus/vm/state.nim index 2f3fa5f99..8e556cf5c 100644 --- a/nimbus/vm/state.nim +++ b/nimbus/vm/state.nim @@ -62,6 +62,7 @@ proc init( random: Hash256; miner: EthAddress; chainDB: BaseChainDB; + ttdReached: bool; tracer: TransactionTracer) {.gcsafe, raises: [Defect,CatchableError].} = ## Initialisation helper @@ -73,6 +74,7 @@ proc init( self.fee = fee self.random = random self.chaindb = chainDB + self.ttdReached = ttdReached self.tracer = tracer self.logEntries = @[] self.stateDB = ac @@ -89,6 +91,7 @@ proc init( random: Hash256; miner: EthAddress; chainDB: BaseChainDB; + ttdReached: bool; tracerFlags: set[TracerFlags]) {.gcsafe, raises: [Defect,CatchableError].} = var tracer: TransactionTracer @@ -102,6 +105,7 @@ proc init( random = random, miner = miner, chainDB = chainDB, + ttdReached= ttdReached, tracer = tracer) # -------------- @@ -121,9 +125,10 @@ proc new*( timestamp: EthTime; ## tx env: time stamp gasLimit: GasInt; ## tx env: gas limit fee: Option[Uint256]; ## tx env: optional base fee - random: Hash256; ## tx env: POS block randomness + random: Hash256; ## tx env: POS block randomness miner: EthAddress; ## tx env: coinbase(PoW) or signer(PoA) chainDB: BaseChainDB; ## block chain database + ttdReached: bool; ## total terminal difficulty reached tracerFlags: set[TracerFlags] = {}; pruneTrie: bool = true): T {.gcsafe, raises: [Defect,CatchableError].} = @@ -144,6 +149,7 @@ proc new*( random = random, miner = miner, chainDB = chainDB, + ttdReached = ttdReached, tracerFlags = tracerFlags) proc reinit*(self: BaseVMState; ## Object descriptor @@ -153,6 +159,7 @@ proc reinit*(self: BaseVMState; ## Object descriptor fee: Option[Uint256]; ## tx env: optional base fee random: Hash256; ## tx env: POS block randomness miner: EthAddress; ## tx env: coinbase(PoW) or signer(PoA) + ttdReached:bool; ## total terminal difficulty reached pruneTrie: bool = true): bool {.gcsafe, raises: [Defect,CatchableError].} = ## Re-initialise state descriptor. The `AccountsCache` database is @@ -179,10 +186,17 @@ proc reinit*(self: BaseVMState; ## Object descriptor random = random, miner = miner, chainDB = db, + ttdReached = ttdReached, tracer = tracer) return true # else: false +proc ttd(chainDB: BaseChainDB): DifficultyInt = + if chainDB.config.terminalTotalDifficulty.isSome: + chainDB.config.terminalTotalDifficulty.get() + else: + high(DifficultyInt) + proc reinit*(self: BaseVMState; ## Object descriptor parent: BlockHeader; ## parent header, account sync pos. header: BlockHeader; ## header with tx environment data fields @@ -194,6 +208,7 @@ proc reinit*(self: BaseVMState; ## Object descriptor ## ## It requires the `header` argument properly initalised so that for PoA ## networks, the miner address is retrievable via `ecRecover()`. + let ttdReached = self.chainDB.totalDifficulty + header.difficulty > self.chainDB.ttd self.reinit( parent = parent, timestamp = header.timestamp, @@ -201,6 +216,7 @@ proc reinit*(self: BaseVMState; ## Object descriptor fee = header.fee, random = header.random, miner = self.chainDB.getMinerAddress(header), + ttdReached= ttdReached, pruneTrie = pruneTrie) proc reinit*(self: BaseVMState; ## Object descriptor @@ -231,6 +247,7 @@ proc init*( ## ## It requires the `header` argument properly initalised so that for PoA ## networks, the miner address is retrievable via `ecRecover()`. + let ttdReached = chainDB.totalDifficulty + header.difficulty > chainDB.ttd self.init(AccountsCache.init(chainDB.db, parent.stateRoot, pruneTrie), parent, header.timestamp, @@ -239,6 +256,7 @@ proc init*( header.random, chainDB.getMinerAddress(header), chainDB, + ttdReached, tracerFlags) proc new*( @@ -308,9 +326,9 @@ method blockNumber*(vmState: BaseVMState): BlockNumber {.base, gcsafe.} = vmState.parent.blockNumber + 1 method difficulty*(vmState: BaseVMState): UInt256 {.base, gcsafe.} = - if vmState.fork >= FkPostMerge: + if vmState.ttdReached: # EIP-4399/EIP-3675 - 0.u256 + UInt256.fromBytesBE(vmState.random.data, allowPadding = false) else: vmState.chainDB.config.calcDifficulty(vmState.timestamp, vmState.parent) diff --git a/nimbus/vm/types.nim b/nimbus/vm/types.nim index 1f422550d..2cd112861 100644 --- a/nimbus/vm/types.nim +++ b/nimbus/vm/types.nim @@ -39,6 +39,7 @@ type gasLimit* : GasInt fee* : Option[Uint256] random* : Hash256 + ttdReached* : bool name* : string flags* : set[VMFlag] tracer* : TransactionTracer diff --git a/nimbus/vm2/computation.nim b/nimbus/vm2/computation.nim index 83d39d56b..0c1b7b4ff 100644 --- a/nimbus/vm2/computation.nim +++ b/nimbus/vm2/computation.nim @@ -58,9 +58,6 @@ template getBlockNumber*(c: Computation): Uint256 = template getDifficulty*(c: Computation): DifficultyInt = c.vmState.difficulty -template getRandom*(c: Computation): Hash256 = - c.vmState.random - template getGasLimit*(c: Computation): GasInt = c.vmState.gasLimit diff --git a/nimbus/vm2/interpreter/gas_costs.nim b/nimbus/vm2/interpreter/gas_costs.nim index 7f0a339af..70264d8e3 100644 --- a/nimbus/vm2/interpreter/gas_costs.nim +++ b/nimbus/vm2/interpreter/gas_costs.nim @@ -730,11 +730,9 @@ const FkPetersburg: SpuriousGasFees, FkIstanbul: IstanbulGasFees, FkBerlin: BerlinGasFees, - FkLondon: LondonGasFees, - FkPostMerge: LondonGasFees + FkLondon: LondonGasFees ] - gasCosts(FkFrontier, base, BaseGasCosts) gasCosts(FkHomestead, homestead, HomesteadGasCosts) gasCosts(FkTangerine, tangerine, TangerineGasCosts) @@ -743,7 +741,6 @@ gasCosts(FkConstantinople, constantinople, ConstantinopleGasCosts) gasCosts(FkIstanbul, istanbul, IstanbulGasCosts) gasCosts(FkBerlin, berlin, BerlinGasCosts) gasCosts(FkLondon, london, LondonGasCosts) -gasCosts(FkPostMerge, postMerge, PostMergeGasCosts) proc forkToSchedule*(fork: Fork): GasCosts = if fork < FkHomestead: @@ -760,10 +757,8 @@ proc forkToSchedule*(fork: Fork): GasCosts = IstanbulGasCosts elif fork < FkLondon: BerlinGasCosts - elif fork < FkPostMerge: - LondonGasCosts else: - PostMergeGasCosts + LondonGasCosts const ## Precompile costs diff --git a/nimbus/vm2/interpreter/op_handlers/oph_blockdata.nim b/nimbus/vm2/interpreter/op_handlers/oph_blockdata.nim index 2e92f5486..7d71df99e 100644 --- a/nimbus/vm2/interpreter/op_handlers/oph_blockdata.nim +++ b/nimbus/vm2/interpreter/op_handlers/oph_blockdata.nim @@ -53,11 +53,6 @@ const k.cpt.stack.push: k.cpt.getDifficulty - randomOp: Vm2OpFn = proc (k: var Vm2Ctx) = - ## 0x44, Get the block's randomness - k.cpt.stack.push: - k.cpt.getRandom - gasLimitOp: Vm2OpFn = proc (k: var Vm2Ctx) = ## 0x45, Get the block's gas limit k.cpt.stack.push: @@ -118,7 +113,7 @@ const post: vm2OpIgnore)), (opCode: Difficulty, ## 0x44, Block difficulty - forks: Vm2OpAllForks - Vm2OpPostMergeAndLater, + forks: Vm2OpAllForks, name: "difficulty", info: "Get the block's difficulty", exec: (prep: vm2OpIgnore, @@ -155,14 +150,6 @@ const info: "Get current block's EIP-1559 base fee", exec: (prep: vm2OpIgnore, run: baseFeeOp, - post: vm2OpIgnore)), - - (opCode: Random, ## 0x44, EIP-4399 Block randomness. - forks: Vm2OpPostMergeAndLater, - name: "random", - info: "Get current block's EIP-4399 randomness", - exec: (prep: vm2OpIgnore, - run: randomOp, post: vm2OpIgnore))] # ------------------------------------------------------------------------------ diff --git a/nimbus/vm2/interpreter/op_handlers/oph_defs.nim b/nimbus/vm2/interpreter/op_handlers/oph_defs.nim index e817acd2b..da222cd21 100644 --- a/nimbus/vm2/interpreter/op_handlers/oph_defs.nim +++ b/nimbus/vm2/interpreter/op_handlers/oph_defs.nim @@ -81,9 +81,6 @@ const Vm2OpLondonAndLater* = Vm2OpBerlinAndLater - {FkBerlin} - Vm2OpPostMergeAndLater* = - Vm2OpLondonAndLater - {FkLondon} - # ------------------------------------------------------------------------------ # End # ------------------------------------------------------------------------------ diff --git a/nimbus/vm2/state.nim b/nimbus/vm2/state.nim index 6332d7149..4be05a783 100644 --- a/nimbus/vm2/state.nim +++ b/nimbus/vm2/state.nim @@ -61,6 +61,7 @@ proc init( random: Hash256; miner: EthAddress; chainDB: BaseChainDB; + ttdReached: bool; tracer: TransactionTracer) {.gcsafe, raises: [Defect,CatchableError].} = ## Initialisation helper @@ -72,6 +73,7 @@ proc init( self.fee = fee self.random = random self.chaindb = chainDB + self.ttdReached = ttdReached self.tracer = tracer self.logEntries = @[] self.stateDB = ac @@ -88,6 +90,7 @@ proc init( random: Hash256; miner: EthAddress; chainDB: BaseChainDB; + ttdReached: bool; tracerFlags: set[TracerFlags]) {.gcsafe, raises: [Defect,CatchableError].} = var tracer: TransactionTracer @@ -101,6 +104,7 @@ proc init( random = random, miner = miner, chainDB = chainDB, + ttdReached= ttdReached, tracer = tracer) # -------------- @@ -123,6 +127,7 @@ proc new*( random: Hash256; ## tx env: POS block randomness miner: EthAddress; ## tx env: coinbase(PoW) or signer(PoA) chainDB: BaseChainDB; ## block chain database + ttdReached: bool; ## total terminal difficulty reached tracerFlags: set[TracerFlags] = {}; pruneTrie: bool = true): T {.gcsafe, raises: [Defect,CatchableError].} = @@ -143,6 +148,7 @@ proc new*( random = random, miner = miner, chainDB = chainDB, + ttdReached = ttdReached, tracerFlags = tracerFlags) proc reinit*(self: BaseVMState; ## Object descriptor @@ -152,6 +158,7 @@ proc reinit*(self: BaseVMState; ## Object descriptor fee: Option[Uint256]; ## tx env: optional base fee random: Hash256; ## tx env: POS block randomness miner: EthAddress; ## tx env: coinbase(PoW) or signer(PoA) + ttdReached:bool; ## total terminal difficulty reached pruneTrie: bool = true): bool {.gcsafe, raises: [Defect,CatchableError].} = ## Re-initialise state descriptor. The `AccountsCache` database is @@ -178,10 +185,17 @@ proc reinit*(self: BaseVMState; ## Object descriptor random = random, miner = miner, chainDB = db, + ttdReached = ttdReached, tracer = tracer) return true # else: false +proc ttd(chainDB: BaseChainDB): DifficultyInt = + if chainDB.config.terminalTotalDifficulty.isSome: + chainDB.config.terminalTotalDifficulty.get() + else: + high(DifficultyInt) + proc reinit*(self: BaseVMState; ## Object descriptor parent: BlockHeader; ## parent header, account sync pos. header: BlockHeader; ## header with tx environment data fields @@ -193,6 +207,7 @@ proc reinit*(self: BaseVMState; ## Object descriptor ## ## It requires the `header` argument properly initalised so that for PoA ## networks, the miner address is retrievable via `ecRecover()`. + let ttdReached = self.chainDB.totalDifficulty + header.difficulty > self.chainDB.ttd self.reinit( parent = parent, timestamp = header.timestamp, @@ -200,6 +215,7 @@ proc reinit*(self: BaseVMState; ## Object descriptor fee = header.fee, random = header.random, miner = self.chainDB.getMinerAddress(header), + ttdReached= ttdReached, pruneTrie = pruneTrie) proc reinit*(self: BaseVMState; ## Object descriptor @@ -230,6 +246,7 @@ proc init*( ## ## It requires the `header` argument properly initalised so that for PoA ## networks, the miner address is retrievable via `ecRecover()`. + let ttdReached = chainDB.totalDifficulty + header.difficulty > chainDB.ttd self.init(AccountsCache.init(chainDB.db, parent.stateRoot, pruneTrie), parent, header.timestamp, @@ -238,6 +255,7 @@ proc init*( header.random, chainDB.getMinerAddress(header), chainDB, + ttdReached, tracerFlags) proc new*( @@ -295,9 +313,9 @@ method blockNumber*(vmState: BaseVMState): BlockNumber {.base, gcsafe.} = vmState.parent.blockNumber + 1 method difficulty*(vmState: BaseVMState): UInt256 {.base, gcsafe.} = - if vmState.fork >= FkPostMerge: + if vmState.ttdReached: # EIP-4399/EIP-3675 - 0.u256 + UInt256.fromBytesBE(vmState.random.data, allowPadding = false) else: vmState.chainDB.config.calcDifficulty(vmState.timestamp, vmState.parent) diff --git a/nimbus/vm2/types.nim b/nimbus/vm2/types.nim index 1a3075014..76a698fbe 100644 --- a/nimbus/vm2/types.nim +++ b/nimbus/vm2/types.nim @@ -30,6 +30,7 @@ type gasLimit* : GasInt fee* : Option[Uint256] random* : Hash256 + ttdReached* : bool name* : string flags* : set[VMFlag] tracer* : TransactionTracer diff --git a/tests/test_op_env.nim b/tests/test_op_env.nim index e07f9fce2..ea8a9f3eb 100644 --- a/tests/test_op_env.nim +++ b/tests/test_op_env.nim @@ -324,27 +324,27 @@ proc opEnvMain*() = fork: berlin gasused: 2603 - when not defined(evmc_enabled): - # TODO: enable this test for EVMC when EVMC - # support this EVM version - assembler: - title: "EIP-4399 RANDOM 0" - code: - Random - STOP - stack: - "0x0000000000000000000000000000000000000000000000000000000000000000" - fork: postmerge + vmState.ttdReached = true + assembler: + title: "EIP-4399 RANDOM 0" + code: + Random + STOP + stack: + "0x0000000000000000000000000000000000000000000000000000000000000000" + fork: london - vmState.random = EMPTY_UNCLE_HASH - assembler: - title: "EIP-4399 RANDOM: EMPTY_UNCLE_HASH" - code: - Random - STOP - stack: - "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" - fork: postmerge + vmState.random = EMPTY_UNCLE_HASH + assembler: + title: "EIP-4399 RANDOM: EMPTY_UNCLE_HASH" + code: + Random + STOP + stack: + "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + fork: london + + vmState.ttdReached = false when isMainModule: opEnvMain()