Reduce EVM complexity by removing forkOverride (#2448)
* Reduce EVM complexity by removing forkOverride * Fixes
This commit is contained in:
parent
81e75622cf
commit
f04f30c72b
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 =
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -37,6 +37,7 @@ type
|
||||||
ParisToShanghaiAtTime15k
|
ParisToShanghaiAtTime15k
|
||||||
Cancun
|
Cancun
|
||||||
ShanghaiToCancunAtTime15k
|
ShanghaiToCancunAtTime15k
|
||||||
|
Prague
|
||||||
|
|
||||||
LogLevel* = enum
|
LogLevel* = enum
|
||||||
Silent
|
Silent
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue