From 236a65d5983f26d2ebd63752a2dbb30fecc4617c Mon Sep 17 00:00:00 2001 From: Jamie Lokier Date: Tue, 4 May 2021 15:02:16 +0100 Subject: [PATCH] Fixtures: Make fixture "vm json tests" use new function fixtureCallEvm Move the EVM setup and call in fixtures "vm json tests" to new function `fixtureCallEvm` in `call_evm`. Extra return values needed for testing are returned specially. This entry point is different from all other `..CallEvm` type functions, because it uses `executeOpcodes` instead of `execComputation`, so it doesn't update the account balance or nonce on entry and exit from the EVM. The new code is a bit redundant and simplistic intentionally, as the purpose is to move functionality to `call_evm` with high confidence nothing really changed. The calls will be jointly refactored afterwards to merge differences. Signed-off-by: Jamie Lokier --- nimbus/transaction/call_evm.nim | 27 ++++++++++++++++++++++++++- tests/test_vm_json.nim | 22 ++++++++++------------ 2 files changed, 36 insertions(+), 13 deletions(-) diff --git a/nimbus/transaction/call_evm.nim b/nimbus/transaction/call_evm.nim index f1d6cabee..d26635955 100644 --- a/nimbus/transaction/call_evm.nim +++ b/nimbus/transaction/call_evm.nim @@ -283,7 +283,7 @@ proc asmCallEvm*(blockNumber: Uint256, chainDB: BaseChainDB, code, data: seq[byt result.vmState = c.vmState result.contractAddress = c.msg.contractAddress -proc fixtureSetupComputation*(vmState: BaseVMState, call: RpcCallData, origin: EthAddress): Computation = +proc fixtureSetupComputation(vmState: BaseVMState, call: RpcCallData, origin: EthAddress): Computation = vmState.setupTxContext( origin = origin, # Differs from `rpcSetupComputation` gasPrice = call.gasPrice, @@ -302,3 +302,28 @@ proc fixtureSetupComputation*(vmState: BaseVMState, call: RpcCallData, origin: E ) return newComputation(vmState, msg) + +type + FixtureResult* = object + isError*: bool + error*: Error + gasRemaining*: GasInt + output*: seq[byte] + vmState*: BaseVMState + logEntries*: seq[Log] + +proc fixtureCallEvm*(vmState: BaseVMState, call: RpcCallData, origin: EthAddress): FixtureResult = + var c = fixtureSetupComputation(vmState, call, origin) + + # Next line differs from all the other EVM calls. With `execComputation`, + # most "vm json tests" fail with either `balanceDiff` or `nonceDiff` errors. + c.executeOpcodes() + + # Some of these are extra returned state, for testing, that a normal EVMC API + # computation doesn't return. We'll have to obtain them outside EVMC. + result.isError = c.isError + result.error = c.error + result.gasRemaining = c.gasMeter.gasRemaining + result.output = c.output + result.vmState = c.vmState + shallowCopy(result.logEntries, c.logEntries) diff --git a/tests/test_vm_json.nim b/tests/test_vm_json.nim index 856dec351..c865af0f8 100644 --- a/tests/test_vm_json.nim +++ b/tests/test_vm_json.nim @@ -59,16 +59,15 @@ proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus) = # assume ZERO_ADDRESS is a contract creation call.contractCreation = (toAddress == ZERO_ADDRESS) - var computation = fixtureSetupComputation(vmState, call, origin) - computation.executeOpcodes() + var fixtureResult = fixtureCallEvm(vmState, call, origin) if not fixture{"post"}.isNil: # Success checks - check(not computation.isError) - if computation.isError: - echo "Computation error: ", computation.error.info + check(not fixtureResult.isError) + if fixtureResult.isError: + echo "Computation error: ", fixtureResult.error.info - let logEntries = computation.logEntries + let logEntries = fixtureResult.logEntries if not fixture{"logs"}.isNil: let actualLogsHash = hashLogEntries(logEntries) let expectedLogsHash = toLowerAscii(fixture{"logs"}.getStr) @@ -78,21 +77,20 @@ proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus) = fail() let expectedOutput = fixture{"out"}.getStr - check(computation.output.bytesToHex == expectedOutput) - let gasMeter = computation.gasMeter + check(fixtureResult.output.bytesToHex == expectedOutput) let expectedGasRemaining = fixture{"gas"}.getHexadecimalInt - let actualGasRemaining = gasMeter.gasRemaining + let actualGasRemaining = fixtureResult.gasRemaining checkpoint(&"Remaining: {actualGasRemaining} - Expected: {expectedGasRemaining}") check(actualGasRemaining == expectedGasRemaining) if not fixture{"post"}.isNil: - verifyStateDb(fixture{"post"}, computation.vmState.readOnlyStateDB) + verifyStateDb(fixture{"post"}, fixtureResult.vmState.readOnlyStateDB) else: # Error checks - check(computation.isError) + check(fixtureResult.isError) if not fixture{"pre"}.isNil: - verifyStateDb(fixture{"pre"}, computation.vmState.readOnlyStateDB) + verifyStateDb(fixture{"pre"}, fixtureResult.vmState.readOnlyStateDB) when isMainModule: vmJsonMain()