nimbus-eth1/tests/test_generalstate_json.nim

90 lines
3.7 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, tables, json, ospaths, times,
byteutils, ranges/typedranges, nimcrypto/[keccak, hash], options,
eth/[rlp, common, keys], eth/trie/db, chronicles,
./test_helpers, ../nimbus/p2p/executor,
../nimbus/[constants, errors],
../nimbus/[vm_state, vm_types, vm_state_transactions, utils],
../nimbus/vm/interpreter,
../nimbus/db/[db_chain, state_db]
proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus)
suite "generalstate json tests":
jsonTest("GeneralStateTests", testFixture)
proc testFixtureIndexes(prevStateRoot: Hash256, header: BlockHeader, pre: JsonNode, tx: Transaction, sender: EthAddress, expectedHash: string, testStatusIMPL: var TestStatus, fork: Fork) =
when enabledLogLevel <= TRACE:
let tracerFlags = {TracerFlags.EnableTracing}
else:
let tracerFlags: set[TracerFlags] = {}
var vmState = newBaseVMState(prevStateRoot, header, newBaseChainDB(newMemoryDb()), tracerFlags)
vmState.mutateStateDB:
setupStateDB(pre, db)
defer:
#echo vmState.readOnlyStateDB.dumpAccount("c94f5374fce5edbc8e2a8697c15331677e6ebf0b")
let obtainedHash = "0x" & `$`(vmState.readOnlyStateDB.rootHash).toLowerAscii
check obtainedHash == expectedHash
if not validateTransaction(vmState, tx, sender):
vmState.mutateStateDB:
# pre-EIP158 (e.g., Byzantium) should ensure currentCoinbase exists
# in later forks, don't create at all
db.addBalance(header.coinbase, 0.u256)
return
let gasCost = tx.gasLimit.u256 * tx.gasPrice.u256
vmState.mutateStateDB:
db.incNonce(sender)
db.subBalance(sender, gasCost)
if tx.isContractCreation and tx.payload.len > 0:
vmState.mutateStateDB:
let createGasUsed = applyCreateTransaction(tx, vmState, sender, some(fork))
db.addBalance(header.coinbase, createGasUsed.u256 * tx.gasPrice.u256)
return
vmState.mutateStateDB:
let gasUsed = contractCall(tx, vmState, sender, some(fork))
db.addBalance(header.coinbase, gasUsed.u256 * tx.gasPrice.u256)
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(""))
let header = BlockHeader(
coinbase: fenv["currentCoinbase"].getStr.ethAddressFromHex,
difficulty: fromHex(UInt256, fenv{"currentDifficulty"}.getStr),
blockNumber: fenv{"currentNumber"}.getHexadecimalInt.u256,
gasLimit: fenv{"currentGasLimit"}.getHexadecimalInt.GasInt,
timestamp: fenv{"currentTimestamp"}.getHexadecimalInt.int64.fromUnix,
stateRoot: emptyRlpHash
)
let ftrans = fixture["transaction"]
for fork in supportedForks:
if fixture["post"].has_key(forkNames[fork]):
# echo "[fork: ", forkNames[fork], "]"
for expectation in fixture["post"][forkNames[fork]]:
let
expectedHash = expectation["hash"].getStr
indexes = expectation["indexes"]
dataIndex = indexes["data"].getInt
gasIndex = indexes["gas"].getInt
valueIndex = indexes["value"].getInt
let transaction = ftrans.getFixtureTransaction(dataIndex, gasIndex, valueIndex)
let sender = ftrans.getFixtureTransactionSender
testFixtureIndexes(emptyRlpHash, header, fixture["pre"], transaction, sender, expectedHash, testStatusIMPL, fork)