mirror of
https://github.com/status-im/nimbus-eth1.git
synced 2025-01-10 12:26:02 +00:00
db202dc35f
This blindly changes logging to nim-chronicles - issues that ensue: * keeps gas cost computation logs hidden behind flag * unclear if logScope is practical - for example, since vm is split over many files, topics get lost when using simple top-level per-module topics * when passing named object around, scope should incliude the name of the object but this is caught neither by logScope nor by dynamicLogScope
115 lines
4.2 KiB
Nim
115 lines
4.2 KiB
Nim
# Nimbus
|
|
# Copyright (c) 2018 Status Research & Development GmbH
|
|
# Licensed under either of
|
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
|
|
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
|
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
|
|
|
import
|
|
unittest, strformat, strutils, sequtils, tables, json, ospaths, times,
|
|
byteutils, ranges/typedranges, nimcrypto/[keccak, hash],
|
|
rlp, eth_trie/[types, memdb], eth_common,
|
|
./test_helpers,
|
|
../nimbus/[constants, errors],
|
|
../nimbus/[vm_state, vm_types],
|
|
../nimbus/utils/header,
|
|
../nimbus/vm/interpreter,
|
|
../nimbus/db/[db_chain, state_db]
|
|
|
|
proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus)
|
|
|
|
suite "vm json tests":
|
|
jsonTest("VMTests", testFixture)
|
|
|
|
|
|
proc stringFromBytes(x: ByteRange): string =
|
|
result = newString(x.len)
|
|
for i in 0 ..< x.len:
|
|
result[i] = char(x[i])
|
|
|
|
proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus) =
|
|
var fixture: JsonNode
|
|
for label, child in fixtures:
|
|
fixture = child
|
|
break
|
|
|
|
let fenv = fixture["env"]
|
|
var emptyRlpHash = keccak256.digest(rlp.encode("").toOpenArray)
|
|
let header = BlockHeader(
|
|
coinbase: fenv{"currentCoinbase"}.getStr.parseAddress,
|
|
difficulty: fromHex(UInt256, fenv{"currentDifficulty"}.getStr),
|
|
blockNumber: fenv{"currentNumber"}.getHexadecimalInt.u256,
|
|
gasLimit: fenv{"currentGasLimit"}.getHexadecimalInt.GasInt,
|
|
timestamp: fenv{"currentTimestamp"}.getHexadecimalInt.int64.fromUnix,
|
|
stateRoot: emptyRlpHash
|
|
)
|
|
|
|
var memDb = newMemDB()
|
|
var vmState = newBaseVMState(header, newBaseChainDB(trieDB memDb))
|
|
let fexec = fixture["exec"]
|
|
var code = ""
|
|
vmState.mutateStateDB:
|
|
setupStateDB(fixture{"pre"}, db)
|
|
let address = fexec{"address"}.getStr.parseAddress
|
|
code = stringFromBytes db.getCode(address)
|
|
|
|
code = fexec{"code"}.getStr
|
|
let toAddress = fexec{"address"}.getStr.parseAddress
|
|
let message = newMessage(
|
|
to = toAddress,
|
|
sender = fexec{"caller"}.getStr.parseAddress,
|
|
value = cast[uint64](fexec{"value"}.getHexadecimalInt).u256, # Cast workaround for negative value
|
|
data = fexec{"data"}.getStr.hexToSeqByte,
|
|
code = code,
|
|
gas = fexec{"gas"}.getHexadecimalInt,
|
|
gasPrice = fexec{"gasPrice"}.getHexadecimalInt,
|
|
options = newMessageOptions(origin=fexec{"origin"}.getStr.parseAddress,
|
|
createAddress = toAddress))
|
|
|
|
#echo fixture{"exec"}
|
|
var c = newCodeStreamFromUnescaped(code)
|
|
when defined(nimbusdebug):
|
|
c.displayDecompiled()
|
|
|
|
var computation = newBaseComputation(vmState, header.blockNumber, message)
|
|
computation.vmState = vmState
|
|
computation.precompiles = initTable[string, Opcode]()
|
|
|
|
computation.executeOpcodes()
|
|
|
|
if not fixture{"post"}.isNil:
|
|
# Success checks
|
|
check(not computation.isError)
|
|
if computation.isError:
|
|
echo "Computation error: ", computation.error.info
|
|
|
|
let logEntries = computation.getLogEntries()
|
|
if not fixture{"logs"}.isNil:
|
|
discard
|
|
# TODO hashLogEntries let actualLogsHash = hashLogEntries(logEntries)
|
|
# let expectedLogsHash = fixture{"logs"}.getStr
|
|
# check(expectedLogsHash == actualLogsHash)
|
|
elif logEntries.len > 0:
|
|
checkpoint(&"Got log entries: {logEntries}")
|
|
fail()
|
|
|
|
let expectedOutput = fixture{"out"}.getStr
|
|
check(computation.outputHex == expectedOutput)
|
|
let gasMeter = computation.gasMeter
|
|
|
|
let expectedGasRemaining = fixture{"gas"}.getHexadecimalInt
|
|
let actualGasRemaining = gasMeter.gasRemaining
|
|
checkpoint(&"Remaining: {actualGasRemaining} - Expected: {expectedGasRemaining}")
|
|
check(actualGasRemaining == expectedGasRemaining or
|
|
computation.code.hasSStore() and
|
|
(actualGasRemaining > expectedGasRemaining and (actualGasRemaining - expectedGasRemaining) mod 15_000 == 0 or
|
|
expectedGasRemaining > actualGasRemaining and (expectedGasRemaining - actualGasRemaining) mod 15_000 == 0))
|
|
|
|
if not fixture{"post"}.isNil:
|
|
verifyStateDb(fixture{"post"}, computation.vmState.readOnlyStateDB)
|
|
else:
|
|
# Error checks
|
|
check(computation.isError)
|
|
# TODO postState = fixture{"pre"}
|
|
|