Reduce EVM complexity by removing forkOverride (#2448)

* Reduce EVM complexity by removing forkOverride

* Fixes
This commit is contained in:
andri lim 2024-07-04 20:48:36 +07:00 committed by GitHub
parent 81e75622cf
commit f04f30c72b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 78 additions and 115 deletions

View File

@ -45,8 +45,9 @@ proc processBlock(
var dbTx = vmState.com.db.newTransaction() var dbTx = vmState.com.db.newTransaction()
defer: dbTx.dispose() defer: dbTx.dispose()
if vmState.com.daoForkSupport and let com = vmState.com
vmState.com.daoForkBlock.get == header.number: if com.daoForkSupport and
com.daoForkBlock.get == header.number:
vmState.mutateStateDB: vmState.mutateStateDB:
db.applyDAOHardFork() db.applyDAOHardFork()
@ -55,19 +56,19 @@ proc processBlock(
? processTransactions(vmState, header, blk.transactions) ? processTransactions(vmState, header, blk.transactions)
if vmState.determineFork >= FkShanghai: if com.isShanghaiOrLater(header.timestamp):
for withdrawal in blk.withdrawals.get: for withdrawal in blk.withdrawals.get:
vmState.stateDB.addBalance(withdrawal.address, withdrawal.weiAmount) vmState.stateDB.addBalance(withdrawal.address, withdrawal.weiAmount)
if header.ommersHash != EMPTY_UNCLE_HASH: if header.ommersHash != EMPTY_UNCLE_HASH:
discard vmState.com.db.persistUncles(blk.uncles) discard com.db.persistUncles(blk.uncles)
# EIP-3675: no reward for miner in POA/POS # EIP-3675: no reward for miner in POA/POS
if vmState.com.consensus == ConsensusType.POW: if com.consensus == ConsensusType.POW:
vmState.calculateReward(header, blk.uncles) vmState.calculateReward(header, blk.uncles)
vmState.mutateStateDB: vmState.mutateStateDB:
let clearEmptyAccount = vmState.determineFork >= FkSpurious let clearEmptyAccount = com.isSpuriousOrLater(header.number)
db.persist(clearEmptyAccount) db.persist(clearEmptyAccount)
dbTx.commit() dbTx.commit()

View File

@ -302,6 +302,9 @@ func toEVMFork*(com: CommonRef, forkDeterminer: ForkDeterminationInfo): EVMFork
func toEVMFork*(com: CommonRef): EVMFork = func toEVMFork*(com: CommonRef): EVMFork =
ToEVMFork[com.currentFork] ToEVMFork[com.currentFork]
func isSpuriousOrLater*(com: CommonRef, number: BlockNumber): bool =
com.toHardFork(number.forkDeterminationInfo) >= Spurious
func isLondonOrLater*(com: CommonRef, number: BlockNumber): bool = func isLondonOrLater*(com: CommonRef, number: BlockNumber): bool =
# TODO: Fixme, use only London comparator # TODO: Fixme, use only London comparator
com.toHardFork(number.forkDeterminationInfo) >= London com.toHardFork(number.forkDeterminationInfo) >= London

View File

@ -57,7 +57,8 @@ proc procBlkPreamble(
template header(): BlockHeader = template header(): BlockHeader =
blk.header blk.header
if vmState.com.daoForkSupport and vmState.com.daoForkBlock.get == header.number: let com = vmState.com
if com.daoForkSupport and com.daoForkBlock.get == header.number:
vmState.mutateStateDB: vmState.mutateStateDB:
db.applyDAOHardFork() db.applyDAOHardFork()
@ -65,7 +66,7 @@ proc procBlkPreamble(
if blk.transactions.calcTxRoot != header.txRoot: if blk.transactions.calcTxRoot != header.txRoot:
return err("Mismatched txRoot") return err("Mismatched txRoot")
if vmState.determineFork >= FkCancun: if com.isCancunOrLater(header.timestamp):
if header.parentBeaconBlockRoot.isNone: if header.parentBeaconBlockRoot.isNone:
return err("Post-Cancun block header must have parentBeaconBlockRoot") return err("Post-Cancun block header must have parentBeaconBlockRoot")
@ -82,7 +83,7 @@ proc procBlkPreamble(
elif blk.transactions.len > 0: elif blk.transactions.len > 0:
return err("Transactions in block with empty txRoot") return err("Transactions in block with empty txRoot")
if vmState.determineFork >= FkShanghai: if com.isShanghaiOrLater(header.timestamp):
if header.withdrawalsRoot.isNone: if header.withdrawalsRoot.isNone:
return err("Post-Shanghai block header must have withdrawalsRoot") return err("Post-Shanghai block header must have withdrawalsRoot")
if blk.withdrawals.isNone: if blk.withdrawals.isNone:
@ -127,7 +128,7 @@ proc procBlkEpilogue(
# Clearing the account cache here helps manage its size when replaying # Clearing the account cache here helps manage its size when replaying
# large ranges of blocks, implicitly limiting its size using the gas limit # large ranges of blocks, implicitly limiting its size using the gas limit
db.persist( db.persist(
clearEmptyAccount = vmState.determineFork >= FkSpurious, clearEmptyAccount = vmState.com.isSpuriousOrLater(header.number),
clearCache = true) clearCache = true)
if not skipValidation: if not skipValidation:

View File

@ -70,12 +70,12 @@ proc processTransactionImpl(
tx: Transaction; ## Transaction to validate tx: Transaction; ## Transaction to validate
sender: EthAddress; ## tx.getSender or tx.ecRecover sender: EthAddress; ## tx.getSender or tx.ecRecover
header: BlockHeader; ## Header for the block containing the current tx header: BlockHeader; ## Header for the block containing the current tx
fork: EVMFork;
): Result[GasInt, string] = ): Result[GasInt, string] =
## Modelled after `https://eips.ethereum.org/EIPS/eip-1559#specification`_ ## Modelled after `https://eips.ethereum.org/EIPS/eip-1559#specification`_
## which provides a backward compatible framwork for EIP1559. ## which provides a backward compatible framwork for EIP1559.
let let
fork = vmState.fork
roDB = vmState.readOnlyStateDB roDB = vmState.readOnlyStateDB
baseFee256 = header.eip1559BaseFee(fork) baseFee256 = header.eip1559BaseFee(fork)
baseFee = baseFee256.truncate(GasInt) baseFee = baseFee256.truncate(GasInt)
@ -115,7 +115,7 @@ proc processTransactionImpl(
vmState.captureTxStart(tx.gasLimit) vmState.captureTxStart(tx.gasLimit)
let let
accTx = vmState.stateDB.beginSavepoint accTx = vmState.stateDB.beginSavepoint
gasBurned = tx.txCallEvm(sender, vmState, fork) gasBurned = tx.txCallEvm(sender, vmState)
vmState.captureTxEnd(tx.gasLimit - gasBurned) vmState.captureTxEnd(tx.gasLimit - gasBurned)
res = commitOrRollbackDependingOnGasUsed(vmState, accTx, header, tx, gasBurned, priorityFee) res = commitOrRollbackDependingOnGasUsed(vmState, accTx, header, tx, gasBurned, priorityFee)
@ -169,18 +169,8 @@ proc processTransaction*(
tx: Transaction; ## Transaction to validate tx: Transaction; ## Transaction to validate
sender: EthAddress; ## tx.getSender or tx.ecRecover sender: EthAddress; ## tx.getSender or tx.ecRecover
header: BlockHeader; ## Header for the block containing the current tx header: BlockHeader; ## Header for the block containing the current tx
fork: EVMFork;
): Result[GasInt,string] = ): Result[GasInt,string] =
vmState.processTransactionImpl(tx, sender, header, fork) vmState.processTransactionImpl(tx, sender, header)
proc processTransaction*(
vmState: BaseVMState; ## Parent accounts environment for transaction
tx: Transaction; ## Transaction to validate
sender: EthAddress; ## tx.getSender or tx.ecRecover
header: BlockHeader;
): Result[GasInt,string] =
let fork = vmState.com.toEVMFork(header.forkDeterminationInfo)
vmState.processTransaction(tx, sender, header, fork)
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# End # End

View File

@ -250,7 +250,7 @@ func excessBlobGas*(dh: TxChainRef): uint64 =
func nextFork*(dh: TxChainRef): EVMFork = func nextFork*(dh: TxChainRef): EVMFork =
## Getter, fork of next block ## Getter, fork of next block
dh.com.toEVMFork(dh.txEnv.vmState.forkDeterminationInfoForVMState) dh.txEnv.vmState.fork
func gasUsed*(dh: TxChainRef): GasInt = func gasUsed*(dh: TxChainRef): GasInt =
## Getter, accumulated gas burned for collected blocks ## Getter, accumulated gas burned for collected blocks

View File

@ -81,11 +81,10 @@ proc runTx(pst: TxPackerStateRef; item: TxItemRef): GasInt =
## Execute item transaction and update `vmState` book keeping. Returns the ## Execute item transaction and update `vmState` book keeping. Returns the
## `gasUsed` after executing the transaction. ## `gasUsed` after executing the transaction.
let let
fork = pst.xp.chain.nextFork
baseFee = pst.xp.chain.baseFee baseFee = pst.xp.chain.baseFee
tx = item.tx.eip1559TxNormalization(baseFee.GasInt) tx = item.tx.eip1559TxNormalization(baseFee.GasInt)
let gasUsed = tx.txCallEvm(item.sender, pst.xp.chain.vmState, fork) let gasUsed = tx.txCallEvm(item.sender, pst.xp.chain.vmState)
pst.cleanState = false pst.cleanState = false
doAssert 0 <= gasUsed doAssert 0 <= gasUsed
gasUsed gasUsed

View File

@ -20,6 +20,12 @@ import
./types, ./types,
./evm_errors ./evm_errors
func forkDeterminationInfoForVMState(vmState: BaseVMState): ForkDeterminationInfo =
forkDeterminationInfo(vmState.parent.number + 1, vmState.blockCtx.timestamp)
func determineFork(vmState: BaseVMState): EVMFork =
vmState.com.toEVMFork(vmState.forkDeterminationInfoForVMState)
proc init( proc init(
self: BaseVMState; self: BaseVMState;
ac: LedgerRef, ac: LedgerRef,
@ -37,6 +43,8 @@ proc init(
self.stateDB = ac self.stateDB = ac
self.flags = flags self.flags = flags
self.blobGasUsed = 0'u64 self.blobGasUsed = 0'u64
self.fork = self.determineFork
self.gasCosts = self.fork.forkToSchedule
func blockCtx(com: CommonRef, header: BlockHeader): func blockCtx(com: CommonRef, header: BlockHeader):
BlockContext = BlockContext =
@ -272,15 +280,6 @@ proc `collectWitnessData=`*(vmState: BaseVMState, status: bool) =
if status: vmState.flags.incl CollectWitnessData if status: vmState.flags.incl CollectWitnessData
else: vmState.flags.excl CollectWitnessData else: vmState.flags.excl CollectWitnessData
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.blockCtx.timestamp)
func determineFork*(vmState: BaseVMState): EVMFork =
vmState.com.toEVMFork(vmState.forkDeterminationInfoForVMState)
func tracingEnabled*(vmState: BaseVMState): bool = func tracingEnabled*(vmState: BaseVMState): bool =
vmState.tracer.isNil.not vmState.tracer.isNil.not

View File

@ -9,10 +9,8 @@
# according to those terms. # according to those terms.
import import
eth/common/eth_types,
../constants, ../constants,
../db/ledger, ../db/ledger,
../transaction,
./computation, ./computation,
./interpreter_dispatch, ./interpreter_dispatch,
./interpreter/gas_costs, ./interpreter/gas_costs,
@ -22,19 +20,6 @@ import
{.push raises: [].} {.push raises: [].}
proc setupTxContext*(vmState: BaseVMState,
txCtx: sink TxContext,
forkOverride=Opt.none(EVMFork)) =
## this proc will be called each time a new transaction
## is going to be executed
vmState.txCtx = system.move(txCtx)
vmState.fork =
if forkOverride.isSome:
forkOverride.get
else:
vmState.determineFork
vmState.gasCosts = vmState.fork.forkToSchedule
# Using `proc` as `incNonce()` might be `proc` in logging mode # Using `proc` as `incNonce()` might be `proc` in logging mode
proc preExecComputation(c: Computation) = proc preExecComputation(c: Computation) =
if not c.msg.isCreate: if not c.msg.isCreate:

View File

@ -32,8 +32,7 @@ func destination*(args: TransactionArgs): EthAddress =
ethAddr args.to.get(ZeroAddr) ethAddr args.to.get(ZeroAddr)
proc toCallParams*(vmState: BaseVMState, args: TransactionArgs, proc toCallParams*(vmState: BaseVMState, args: TransactionArgs,
globalGasCap: GasInt, baseFee: Opt[UInt256], globalGasCap: GasInt, baseFee: Opt[UInt256]): EvmResult[CallParams] =
forkOverride = Opt.none(EVMFork)): EvmResult[CallParams] =
# Reject invalid combinations of pre- and post-1559 fee styles # Reject invalid combinations of pre- and post-1559 fee styles
if args.gasPrice.isSome and if args.gasPrice.isSome and
@ -74,7 +73,6 @@ proc toCallParams*(vmState: BaseVMState, args: TransactionArgs,
ok(CallParams( ok(CallParams(
vmState: vmState, vmState: vmState,
forkOverride: forkOverride,
sender: args.sender, sender: args.sender,
to: args.destination, to: args.destination,
isCreate: args.to.isNone, isCreate: args.to.isNone,

View File

@ -31,7 +31,6 @@ type
# Standard call parameters. # Standard call parameters.
CallParams* = object CallParams* = object
vmState*: BaseVMState # Chain, database, state, block, fork. vmState*: BaseVMState # Chain, database, state, block, fork.
forkOverride*: Opt[EVMFork] # Default fork is usually correct.
origin*: Opt[HostAddress] # Default origin is `sender`. origin*: Opt[HostAddress] # Default origin is `sender`.
gasPrice*: GasInt # Gas price for this call. gasPrice*: GasInt # Gas price for this call.
gasLimit*: GasInt # Maximum gas available for this call. gasLimit*: GasInt # Maximum gas available for this call.
@ -133,14 +132,11 @@ proc initialAccessListEIP2929(call: CallParams) =
proc setupHost(call: CallParams): TransactionHost = proc setupHost(call: CallParams): TransactionHost =
let vmState = call.vmState let vmState = call.vmState
vmState.setupTxContext( vmState.txCtx = TxContext(
TxContext( origin : call.origin.get(call.sender),
origin : call.origin.get(call.sender), gasPrice : call.gasPrice,
gasPrice : call.gasPrice, versionedHashes: call.versionedHashes,
versionedHashes: call.versionedHashes, blobBaseFee : getBlobBaseFee(vmState.blockCtx.excessBlobGas),
blobBaseFee : getBlobBaseFee(vmState.blockCtx.excessBlobGas),
),
forkOverride = call.forkOverride
) )
var intrinsicGas: GasInt = 0 var intrinsicGas: GasInt = 0

View File

@ -63,7 +63,7 @@ proc rpcEstimateGas*(args: TransactionArgs,
baseFeePerGas: Opt.none UInt256, ## ??? baseFeePerGas: Opt.none UInt256, ## ???
) )
let vmState = ? BaseVMState.new(topHeader, com) let vmState = ? BaseVMState.new(topHeader, com)
let fork = vmState.determineFork let fork = vmState.fork
let txGas = gasFees[fork][GasTransaction] # txGas always 21000, use constants? let txGas = gasFees[fork][GasTransaction] # txGas always 21000, use constants?
var params = ? toCallParams(vmState, args, gasCap, header.baseFeePerGas) var params = ? toCallParams(vmState, args, gasCap, header.baseFeePerGas)
@ -147,12 +147,11 @@ proc rpcEstimateGas*(args: TransactionArgs,
ok(hi) ok(hi)
proc callParamsForTx(tx: Transaction, sender: EthAddress, vmState: BaseVMState, fork: EVMFork): CallParams = proc callParamsForTx(tx: Transaction, sender: EthAddress, vmState: BaseVMState): CallParams =
# Is there a nice idiom for this kind of thing? Should I # Is there a nice idiom for this kind of thing? Should I
# just be writing this as a bunch of assignment statements? # just be writing this as a bunch of assignment statements?
result = CallParams( result = CallParams(
vmState: vmState, vmState: vmState,
forkOverride: Opt.some(fork),
gasPrice: tx.gasPrice, gasPrice: tx.gasPrice,
gasLimit: tx.gasLimit, gasLimit: tx.gasLimit,
sender: sender, sender: sender,
@ -167,10 +166,9 @@ proc callParamsForTx(tx: Transaction, sender: EthAddress, vmState: BaseVMState,
if tx.txType >= TxEip4844: if tx.txType >= TxEip4844:
result.versionedHashes = tx.versionedHashes result.versionedHashes = tx.versionedHashes
proc callParamsForTest(tx: Transaction, sender: EthAddress, vmState: BaseVMState, fork: EVMFork): CallParams = proc callParamsForTest(tx: Transaction, sender: EthAddress, vmState: BaseVMState): CallParams =
result = CallParams( result = CallParams(
vmState: vmState, vmState: vmState,
forkOverride: Opt.some(fork),
gasPrice: tx.gasPrice, gasPrice: tx.gasPrice,
gasLimit: tx.gasLimit, gasLimit: tx.gasLimit,
sender: sender, sender: sender,
@ -190,16 +188,14 @@ proc callParamsForTest(tx: Transaction, sender: EthAddress, vmState: BaseVMState
proc txCallEvm*(tx: Transaction, proc txCallEvm*(tx: Transaction,
sender: EthAddress, sender: EthAddress,
vmState: BaseVMState, vmState: BaseVMState): GasInt =
fork: EVMFork): GasInt =
let let
call = callParamsForTx(tx, sender, vmState, fork) call = callParamsForTx(tx, sender, vmState)
res = runComputation(call) res = runComputation(call)
res.gasUsed res.gasUsed
proc testCallEvm*(tx: Transaction, proc testCallEvm*(tx: Transaction,
sender: EthAddress, sender: EthAddress,
vmState: BaseVMState, vmState: BaseVMState): CallResult =
fork: EVMFork): CallResult = let call = callParamsForTest(tx, sender, vmState)
let call = callParamsForTest(tx, sender, vmState, fork)
runComputation(call) runComputation(call)

View File

@ -395,12 +395,11 @@ proc createSignedTx(payload: Blob, chainId: ChainId): Transaction =
proc runVM*(vmState: BaseVMState, boa: Assembler): bool = proc runVM*(vmState: BaseVMState, boa: Assembler): bool =
let let
com = vmState.com com = vmState.com
fork = com.toEVMFork()
vmState.mutateStateDB: vmState.mutateStateDB:
db.setCode(codeAddress, boa.code) db.setCode(codeAddress, boa.code)
db.setBalance(codeAddress, 1_000_000.u256) db.setBalance(codeAddress, 1_000_000.u256)
let tx = createSignedTx(boa.data, com.chainId) let tx = createSignedTx(boa.data, com.chainId)
let asmResult = testCallEvm(tx, tx.getSender, vmState, fork) let asmResult = testCallEvm(tx, tx.getSender, vmState)
verifyAsmResult(vmState, boa, asmResult) verifyAsmResult(vmState, boa, asmResult)
macro assembler*(list: untyped): untyped = macro assembler*(list: untyped): untyped =

View File

@ -19,7 +19,6 @@ import
../nimbus/evm/memory, ../nimbus/evm/memory,
../nimbus/evm/code_stream, ../nimbus/evm/code_stream,
../nimbus/evm/internals, ../nimbus/evm/internals,
../nimbus/evm/types,
../nimbus/constants, ../nimbus/constants,
../nimbus/core/pow/header, ../nimbus/core/pow/header,
../nimbus/db/ledger, ../nimbus/db/ledger,
@ -377,7 +376,7 @@ proc runTestOverflow() =
let privateKey = PrivateKey.fromHex("0000000000000000000000000000000000000000000000000000001000000000")[] let privateKey = PrivateKey.fromHex("0000000000000000000000000000000000000000000000000000001000000000")[]
let tx = signTransaction(unsignedTx, privateKey, ChainId(1), false) let tx = signTransaction(unsignedTx, privateKey, ChainId(1), false)
let res = testCallEvm(tx, tx.getSender, s, FkHomestead) let res = testCallEvm(tx, tx.getSender, s)
when defined(evmc_enabled): when defined(evmc_enabled):
check res.error == "EVMC_FAILURE" check res.error == "EVMC_FAILURE"

View File

@ -101,7 +101,6 @@ 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.forkDeterminationInfo)
vmState.mutateStateDB: vmState.mutateStateDB:
setupStateDB(ctx.pre, db) setupStateDB(ctx.pre, db)
@ -112,12 +111,12 @@ proc testFixtureIndexes(ctx: var TestCtx, testStatusIMPL: var TestStatus) =
db.persist() db.persist()
let rc = vmState.processTransaction( let rc = vmState.processTransaction(
ctx.tx, sender, ctx.header, fork) ctx.tx, sender, ctx.header)
if rc.isOk: if rc.isOk:
gasUsed = rc.value gasUsed = rc.value
let miner = ctx.header.coinbase let miner = ctx.header.coinbase
coinbaseStateClearing(vmState, miner, fork) coinbaseStateClearing(vmState, miner)
block post: block post:
let obtainedHash = vmState.readOnlyStateDB.rootHash let obtainedHash = vmState.readOnlyStateDB.rootHash

View File

@ -10,6 +10,7 @@ import
unittest2, stew/byteutils, unittest2, stew/byteutils,
eth/[keys, trie], eth/[keys, trie],
../nimbus/common/common, ../nimbus/common/common,
../tools/common/helpers as chp,
../nimbus/[evm/computation, ../nimbus/[evm/computation,
evm/state, evm/state,
evm/types, evm/types,
@ -23,7 +24,7 @@ import
proc initAddress(i: byte): EthAddress = result[19] = i proc initAddress(i: byte): EthAddress = result[19] = i
template doTest(fixture: JsonNode; vmState: BaseVMState; fork: EVMFork, address: PrecompileAddresses): untyped = template doTest(fixture: JsonNode; vmState: BaseVMState; address: PrecompileAddresses): untyped =
for test in fixture: for test in fixture:
let let
expectedErr = test.hasKey("ExpectedError") expectedErr = test.hasKey("ExpectedError")
@ -44,7 +45,7 @@ template doTest(fixture: JsonNode; vmState: BaseVMState; fork: EVMFork, address:
payload: if dataStr.len > 0: dataStr.hexToSeqByte else: @[] payload: if dataStr.len > 0: dataStr.hexToSeqByte else: @[]
) )
let tx = signTransaction(unsignedTx, privateKey, ChainId(1), false) let tx = signTransaction(unsignedTx, privateKey, ChainId(1), false)
let fixtureResult = testCallEvm(tx, tx.getSender, vmState, fork) let fixtureResult = testCallEvm(tx, tx.getSender, vmState)
if expectedErr: if expectedErr:
check fixtureResult.isError check fixtureResult.isError
@ -59,20 +60,16 @@ template doTest(fixture: JsonNode; vmState: BaseVMState; fork: EVMFork, address:
debugEcho "GAS: ", fixtureResult.gasUsed, " ", gasExpected.get debugEcho "GAS: ", fixtureResult.gasUsed, " ", gasExpected.get
check fixtureResult.gasUsed == gasExpected.get check fixtureResult.gasUsed == gasExpected.get
proc parseFork(x: string): EVMFork = proc parseFork(x: string): string =
let x = x.toLowerAscii result = x.capitalizeAscii
for name, fork in nameToFork:
if name.toLowerAscii == x:
return fork
doAssert(false, "unsupported fork name " & x)
proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus) = proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus) =
let let
label = fixtures["func"].getStr label = fixtures["func"].getStr
fork = parseFork(fixtures["fork"].getStr) conf = getChainConfig(parseFork(fixtures["fork"].getStr))
data = fixtures["data"] data = fixtures["data"]
privateKey = PrivateKey.fromHex("7a28b5ba57c53603b0b07b56bba752f7784bf506fa95edc395f5cf6c7514fe9d")[] privateKey = PrivateKey.fromHex("7a28b5ba57c53603b0b07b56bba752f7784bf506fa95edc395f5cf6c7514fe9d")[]
com = CommonRef.new(newCoreDbRef DefaultDbMemory, config = ChainConfig()) com = CommonRef.new(newCoreDbRef DefaultDbMemory, config = conf)
vmState = BaseVMState.new( vmState = BaseVMState.new(
BlockHeader(number: 1'u64, stateRoot: emptyRlpHash), BlockHeader(number: 1'u64, stateRoot: emptyRlpHash),
BlockHeader(), BlockHeader(),
@ -80,25 +77,25 @@ proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus) =
) )
case toLowerAscii(label) case toLowerAscii(label)
of "ecrecover": data.doTest(vmState, fork, paEcRecover) of "ecrecover": data.doTest(vmState, paEcRecover)
of "sha256" : data.doTest(vmState, fork, paSha256) of "sha256" : data.doTest(vmState, paSha256)
of "ripemd" : data.doTest(vmState, fork, paRipeMd160) of "ripemd" : data.doTest(vmState, paRipeMd160)
of "identity" : data.doTest(vmState, fork, paIdentity) of "identity" : data.doTest(vmState, paIdentity)
of "modexp" : data.doTest(vmState, fork, paModExp) of "modexp" : data.doTest(vmState, paModExp)
of "bn256add" : data.doTest(vmState, fork, paEcAdd) of "bn256add" : data.doTest(vmState, paEcAdd)
of "bn256mul" : data.doTest(vmState, fork, paEcMul) of "bn256mul" : data.doTest(vmState, paEcMul)
of "ecpairing": data.doTest(vmState, fork, paPairing) of "ecpairing": data.doTest(vmState, paPairing)
of "blake2f" : data.doTest(vmState, fork, paBlake2bf) of "blake2f" : data.doTest(vmState, paBlake2bf)
of "blsg1add" : data.doTest(vmState, fork, paBlsG1Add) of "blsg1add" : data.doTest(vmState, paBlsG1Add)
of "blsg1mul" : data.doTest(vmState, fork, paBlsG1Mul) of "blsg1mul" : data.doTest(vmState, paBlsG1Mul)
of "blsg1multiexp" : data.doTest(vmState, fork, paBlsG1MultiExp) of "blsg1multiexp" : data.doTest(vmState, paBlsG1MultiExp)
of "blsg2add" : data.doTest(vmState, fork, paBlsG2Add) of "blsg2add" : data.doTest(vmState, paBlsG2Add)
of "blsg2mul" : data.doTest(vmState, fork, paBlsG2Mul) of "blsg2mul" : data.doTest(vmState, paBlsG2Mul)
# EIP 2537: disabled due to gas price changes/discprepancies # EIP 2537: disabled due to gas price changes/discprepancies
#of "blsg2multiexp": data.doTest(vmState, fork, paBlsG2MultiExp) #of "blsg2multiexp": data.doTest(vmState, paBlsG2MultiExp)
#of "blspairing": data.doTest(vmState, fork, paBlsPairing) #of "blspairing": data.doTest(vmState, paBlsPairing)
#of "blsmapg1": data.doTest(vmState, fork, paBlsMapG1) #of "blsmapg1": data.doTest(vmState, paBlsMapG1)
#of "blsmapg2": data.doTest(vmState, fork, paBlsMapG2) #of "blsmapg2": data.doTest(vmState, paBlsMapG2)
else: else:
echo "Unknown test vector '" & $label & "'" echo "Unknown test vector '" & $label & "'"
testStatusIMPL = SKIPPED testStatusIMPL = SKIPPED

View File

@ -121,6 +121,8 @@ func getChainConfig*(network: string, c: ChainConfig) =
c.assignTime(HardFork.Cancun, TimeZero) c.assignTime(HardFork.Cancun, TimeZero)
of $TestFork.ShanghaiToCancunAtTime15k: of $TestFork.ShanghaiToCancunAtTime15k:
c.assignTime(HardFork.Cancun, EthTime(15000)) c.assignTime(HardFork.Cancun, EthTime(15000))
of $TestFork.Prague:
c.assignTime(HardFork.Prague, TimeZero)
else: else:
raise newException(ValueError, "unsupported network " & network) raise newException(ValueError, "unsupported network " & network)

View File

@ -15,7 +15,6 @@ import
proc coinbaseStateClearing*(vmState: BaseVMState, proc coinbaseStateClearing*(vmState: BaseVMState,
miner: EthAddress, miner: EthAddress,
fork: EVMFork,
touched = true) = touched = true) =
# This is necessary due to the manner in which the state tests are # This is necessary due to the manner in which the state tests are
# generated. State tests are generated from the BlockChainTest tests # generated. State tests are generated from the BlockChainTest tests
@ -38,4 +37,4 @@ proc coinbaseStateClearing*(vmState: BaseVMState,
# do not clear cache, we need the cache when constructing # do not clear cache, we need the cache when constructing
# post state # post state
db.persist(clearEmptyAccount = fork >= FkSpurious) db.persist(clearEmptyAccount = vmState.fork >= FkSpurious)

View File

@ -37,6 +37,7 @@ type
ParisToShanghaiAtTime15k ParisToShanghaiAtTime15k
Cancun Cancun
ShanghaiToCancunAtTime15k ShanghaiToCancunAtTime15k
Prague
LogLevel* = enum LogLevel* = enum
Silent Silent

View File

@ -130,7 +130,6 @@ 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 DefaultDbMemory, ctx.chainConfig) com = CommonRef.new(newCoreDbRef DefaultDbMemory, ctx.chainConfig)
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)
@ -175,12 +174,12 @@ proc runExecution(ctx: var StateContext, conf: StateConf, pre: JsonNode): StateR
try: try:
let rc = vmState.processTransaction( let rc = vmState.processTransaction(
ctx.tx, sender, ctx.header, fork) ctx.tx, sender, ctx.header)
if rc.isOk: if rc.isOk:
gasUsed = rc.value gasUsed = rc.value
let miner = ctx.header.coinbase let miner = ctx.header.coinbase
coinbaseStateClearing(vmState, miner, fork) coinbaseStateClearing(vmState, miner)
except CatchableError as ex: except CatchableError as ex:
echo "FATAL: ", ex.msg echo "FATAL: ", ex.msg
quit(QuitFailure) quit(QuitFailure)

View File

@ -300,7 +300,7 @@ proc exec(ctx: var TransContext,
let miner = ctx.env.currentCoinbase let miner = ctx.env.currentCoinbase
let fork = vmState.com.toEVMFork let fork = vmState.com.toEVMFork
coinbaseStateClearing(vmState, miner, fork, stateReward.isSome()) coinbaseStateClearing(vmState, miner, stateReward.isSome())
let stateDB = vmState.stateDB let stateDB = vmState.stateDB
stateDB.postState(result.alloc) stateDB.postState(result.alloc)