simplify evm call of test_precompiles

first step towards evm call variation reduction
This commit is contained in:
jangko 2021-10-14 13:08:40 +07:00
parent b77034c870
commit eb2251ec37
No known key found for this signature in database
GPG Key ID: 31702AE10541E6B9
2 changed files with 48 additions and 60 deletions

View File

@ -187,40 +187,21 @@ proc asmCallEvm*(blockNumber: Uint256, chainDB: BaseChainDB, code, data: seq[byt
result.vmState = vmState result.vmState = vmState
result.contractAddress = contractAddress result.contractAddress = contractAddress
type proc testCallEvm*(tx: Transaction, sender: EthAddress, vmState: BaseVMState, fork: Fork): CallResult =
FixtureResult* = object var call = CallParams(
isError*: bool
error*: Error
gasUsed*: GasInt
output*: seq[byte]
vmState*: BaseVMState
logEntries*: seq[Log]
proc fixtureCallEvm*(vmState: BaseVMState, call: RpcCallData,
origin: EthAddress, forkOverride = none(Fork)): FixtureResult =
let callResult = runComputation(CallParams(
vmState: vmState, vmState: vmState,
forkOverride: forkOverride, forkOverride: some(fork),
origin: some(origin), # Differs from `rpcSetupComputation`. gasPrice: tx.gasPrice,
gasPrice: call.gasPrice, gasLimit: tx.gasLimit,
gasLimit: call.gas, # Differs from `rpcSetupComputation`. sender: sender,
sender: call.source, to: tx.destination,
to: call.to, isCreate: tx.contractCreation,
isCreate: call.contractCreation, value: tx.value,
value: call.value, input: tx.payload,
input: call.data,
noIntrinsic: true, # Don't charge intrinsic gas.
noAccessList: true, # Don't initialise EIP-2929 access list.
noGasCharge: true, # Don't charge sender account for gas.
noRefund: true, # Don't apply gas refund/burn rule.
noTransfer: true, # Don't update balances, nonces, code.
))
# Some of these are extra returned state, for testing, that a normal EVMC API noIntrinsic: true, # Don't charge intrinsic gas.
# computation doesn't return. We'll have to obtain them outside EVMC. noRefund: true, # Don't apply gas refund/burn rule.
result.isError = callResult.isError )
result.error = callResult.error if tx.txType > TxLegacy:
result.gasUsed = callResult.gasUsed shallowCopy(call.accessList, tx.accessList)
result.output = callResult.output runComputation(call)
result.vmState = vmState
shallowCopy(result.logEntries, callResult.logEntries)

View File

@ -6,35 +6,43 @@
# at your option. This file may not be copied, modified, or distributed except according to those terms. # at your option. This file may not be copied, modified, or distributed except according to those terms.
import import
unittest2, ../nimbus/vm_precompiles, json, stew/byteutils, test_helpers, os, tables, std/[strformat, strutils, json, os, tables, macros, options],
strformat, strutils, eth/trie/db, eth/common, ../nimbus/db/db_chain, ../nimbus/constants, unittest2, stew/byteutils,
../nimbus/[vm_computation, vm_state, forks], macros, eth/[trie/db, common, keys],
test_allowed_to_fail,
../nimbus/transaction/call_evm, options ../nimbus/[vm_computation,
vm_state,
forks,
constants,
vm_precompiles,
transaction,
db/db_chain,
transaction/call_evm
],
./test_helpers, ./test_allowed_to_fail
proc initAddress(i: byte): EthAddress = result[19] = i proc initAddress(i: byte): EthAddress = result[19] = i
template doTest(fixture: JsonNode, fork: Fork, address: PrecompileAddresses): untyped = template doTest(fixture: JsonNode, fork: Fork, address: PrecompileAddresses): untyped =
for test in fixture: for test in fixture:
let let
blockNum = 1.u256 # TODO: Check other forks
header = BlockHeader(blockNumber: blockNum)
expectedErr = test.hasKey("ExpectedError") expectedErr = test.hasKey("ExpectedError")
expected = if test.hasKey("Expected"): hexToSeqByte(test["Expected"].getStr) else: @[] expected = if test.hasKey("Expected"): hexToSeqByte(test["Expected"].getStr) else: @[]
dataStr = test["Input"].getStr dataStr = test["Input"].getStr
vmState = newBaseVMState(header.stateRoot, header, newBaseChainDB(newMemoryDb()))
gasExpected = if test.hasKey("Gas"): test["Gas"].getInt else: -1 gasExpected = if test.hasKey("Gas"): test["Gas"].getInt else: -1
var call: RpcCallData let unsignedTx = Transaction(
call.source = ZERO_ADDRESS txType: TxLegacy,
call.to = initAddress(address.byte) nonce: 0,
call.gas = 1_000_000_000.GasInt gasPrice: 1.GasInt,
call.gasPrice = 1.GasInt gasLimit: 1_000_000_000.GasInt,
call.value = 0.u256 to: initAddress(address.byte).some,
call.data = if dataStr.len > 0: dataStr.hexToSeqByte else: @[] value: 0.u256,
call.contractCreation = false payload: if dataStr.len > 0: dataStr.hexToSeqByte else: @[]
)
let fixtureResult = fixtureCallEvm(vmState, call, call.source, some(fork)) let tx = signTransaction(unsignedTx, privateKey, ChainId(1), false)
let fixtureResult = testCallEvm(tx, tx.getSender, vmState, fork)
if expectedErr: if expectedErr:
check fixtureResult.isError check fixtureResult.isError
@ -54,7 +62,10 @@ proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus) =
label = fixtures["func"].getStr label = fixtures["func"].getStr
fork = parseEnum[Fork](fixtures["fork"].getStr.toLowerAscii) fork = parseEnum[Fork](fixtures["fork"].getStr.toLowerAscii)
data = fixtures["data"] data = fixtures["data"]
privateKey = PrivateKey.fromHex("7a28b5ba57c53603b0b07b56bba752f7784bf506fa95edc395f5cf6c7514fe9d")[]
header = BlockHeader(blockNumber: 1.u256)
vmState = newBaseVMState(header.stateRoot, header, newBaseChainDB(newMemoryDb()))
case toLowerAscii(label) case toLowerAscii(label)
of "ecrecover": data.doTest(fork, paEcRecover) of "ecrecover": data.doTest(fork, paEcRecover)
of "sha256" : data.doTest(fork, paSha256) of "sha256" : data.doTest(fork, paSha256)
@ -82,11 +93,7 @@ proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus) =
proc precompilesMain*() = proc precompilesMain*() =
suite "Precompiles": suite "Precompiles":
# TODO: For now, EVMC is incompatible with these tests. jsonTest("PrecompileTests", testFixture, skipPrecompilesTests)
when defined(evmc_enabled):
discard
else:
jsonTest("PrecompileTests", testFixture, skipPrecompilesTests)
when isMainModule: when isMainModule:
precompilesMain() precompilesMain()