mirror of
https://github.com/status-im/nimbus-eth1.git
synced 2025-01-24 19:19:21 +00:00
Precompiles: Change precompile tests to use fixtureCallEvm
Move the EVM setup and call in precompile tests to `fixtureCallEvm` in `call_evm`. Extra return values needed for testing are returned specially, and the convention for reporting gas used is changed to match `asmCallEvm`. Although the precompile tests used `execPrecompiles` before, `executeOpcodes` does perfectly well as a substitute, allowing `fixtureCallEvm` to be shared. _Significantly, this patch also makes `Computation` more or less an internal type of the EVM now._ Nothing outside the EVM (except `call_evm`) needs access any more to `Computation`, `execComputation`, `executeOpcodes` or `execPrecompiles`. Many imports can be trimmed, some files removed, and EVMC is much closer. (As a bonus, the functions in `call_evm` reveal what capabilities parts of the program have needed over time, makes certain bugs and inconsistencies clearer, and suggests how to refactor into a more useful shared entry point.) Signed-off-by: Jamie Lokier <jamie@shareable.org>
This commit is contained in:
parent
751068a4d4
commit
1574136a25
@ -302,7 +302,7 @@ type
|
||||
FixtureResult* = object
|
||||
isError*: bool
|
||||
error*: Error
|
||||
gasRemaining*: GasInt
|
||||
gasUsed*: GasInt
|
||||
output*: seq[byte]
|
||||
vmState*: BaseVMState
|
||||
logEntries*: seq[Log]
|
||||
@ -310,6 +310,7 @@ type
|
||||
proc fixtureCallEvm*(vmState: BaseVMState, call: RpcCallData,
|
||||
origin: EthAddress, forkOverride = none(Fork)): FixtureResult =
|
||||
var c = fixtureSetupComputation(vmState, call, origin, forkOverride)
|
||||
let gas = c.gasMeter.gasRemaining
|
||||
|
||||
# Next line differs from all the other EVM calls. With `execComputation`,
|
||||
# most "vm json tests" fail with either `balanceDiff` or `nonceDiff` errors.
|
||||
@ -319,7 +320,7 @@ proc fixtureCallEvm*(vmState: BaseVMState, call: RpcCallData,
|
||||
# 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.gasUsed = gas - c.gasMeter.gasRemaining
|
||||
result.output = c.output
|
||||
result.vmState = c.vmState
|
||||
shallowCopy(result.logEntries, c.logEntries)
|
||||
|
@ -9,7 +9,8 @@ import
|
||||
unittest2, ../nimbus/vm_precompiles, json, stew/byteutils, test_helpers, os, tables,
|
||||
strformat, strutils, eth/trie/db, eth/common, ../nimbus/db/db_chain,
|
||||
../nimbus/[vm_computation, vm_types, vm_state, vm_types2], macros,
|
||||
test_allowed_to_fail
|
||||
test_allowed_to_fail,
|
||||
../nimbus/transaction/call_evm, options
|
||||
|
||||
proc initAddress(i: byte): EthAddress = result[19] = i
|
||||
|
||||
@ -21,46 +22,32 @@ template doTest(fixture: JsonNode, fork: Fork, address: PrecompileAddresses): un
|
||||
expectedErr = test.hasKey("ExpectedError")
|
||||
expected = if test.hasKey("Expected"): hexToSeqByte(test["Expected"].getStr) else: @[]
|
||||
dataStr = test["Input"].getStr
|
||||
data = if dataStr.len > 0: dataStr.hexToSeqByte else: @[]
|
||||
vmState = newBaseVMState(header.stateRoot, header, newBaseChainDB(newMemoryDb()))
|
||||
gas = 1_000_000_000.GasInt
|
||||
gasPrice = 1.GasInt
|
||||
sender = initAddress(0x00)
|
||||
toAddress = initAddress(address.byte)
|
||||
gasCost = if test.hasKey("Gas"): test["Gas"].getInt else: -1
|
||||
gasExpected = if test.hasKey("Gas"): test["Gas"].getInt else: -1
|
||||
|
||||
vmState.setupTxContext(
|
||||
origin = sender,
|
||||
gasPrice = gasPrice
|
||||
)
|
||||
var call: RpcCallData
|
||||
call.source = initAddress(0x00)
|
||||
call.to = initAddress(address.byte)
|
||||
call.gas = 1_000_000_000.GasInt
|
||||
call.gasPrice = 1.GasInt
|
||||
call.value = 0.u256
|
||||
call.data = if dataStr.len > 0: dataStr.hexToSeqByte else: @[]
|
||||
call.contractCreation = false
|
||||
|
||||
var
|
||||
message = Message(
|
||||
kind: evmcCall,
|
||||
gas: gas,
|
||||
sender: sender,
|
||||
contractAddress: toAddress,
|
||||
codeAddress: toAddress,
|
||||
value: 0.u256,
|
||||
data: data
|
||||
)
|
||||
comp = newComputation(vmState, message)
|
||||
|
||||
let initialGas = comp.gasMeter.gasRemaining
|
||||
discard execPrecompiles(comp, fork)
|
||||
let fixtureResult = fixtureCallEvm(vmState, call, call.source, some(fork))
|
||||
|
||||
if expectedErr:
|
||||
check comp.isError
|
||||
check fixtureResult.isError
|
||||
else:
|
||||
let c = comp.output == expected
|
||||
if not c: echo "Output : " & comp.output.toHex & "\nExpected: " & expected.toHex
|
||||
check not fixtureResult.isError
|
||||
let c = fixtureResult.output == expected
|
||||
if not c: echo "Output : " & fixtureResult.output.toHex & "\nExpected: " & expected.toHex
|
||||
check c
|
||||
|
||||
if gasCost >= 0:
|
||||
let gasFee = initialGas - comp.gasMeter.gasRemaining
|
||||
if gasFee != gasCost:
|
||||
debugEcho "GAS: ", gasFee, " ", gasCost
|
||||
check gasFee == gasCost
|
||||
if gasExpected >= 0:
|
||||
if fixtureResult.gasUsed != gasExpected:
|
||||
debugEcho "GAS: ", fixtureResult.gasUsed, " ", gasExpected
|
||||
check fixtureResult.gasUsed == gasExpected
|
||||
|
||||
proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus) =
|
||||
let
|
||||
|
@ -80,7 +80,7 @@ proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus) =
|
||||
check(fixtureResult.output.bytesToHex == expectedOutput)
|
||||
|
||||
let expectedGasRemaining = fixture{"gas"}.getHexadecimalInt
|
||||
let actualGasRemaining = fixtureResult.gasRemaining
|
||||
let actualGasRemaining = call.gas - fixtureResult.gasUsed
|
||||
checkpoint(&"Remaining: {actualGasRemaining} - Expected: {expectedGasRemaining}")
|
||||
check(actualGasRemaining == expectedGasRemaining)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user