add debugging caps to gst

This commit is contained in:
andri lim 2019-03-18 08:55:02 +07:00
parent 5060f4aaca
commit 2bd5c99b27
No known key found for this signature in database
GPG Key ID: 31702AE10541E6B9
3 changed files with 90 additions and 37 deletions

View File

@ -6,63 +6,100 @@
# 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,
unittest, strformat, strutils, tables, json, ospaths, times, os,
byteutils, ranges/typedranges, nimcrypto, options,
eth/[rlp, common, keys], eth/trie/db, chronicles,
eth/[rlp, common, keys], eth/trie/[db, trie_defs], chronicles,
./test_helpers, ../nimbus/p2p/executor,
../nimbus/[constants, errors, transaction],
../nimbus/[vm_state, vm_types, vm_state_transactions, utils],
../nimbus/vm/interpreter,
../nimbus/db/[db_chain, state_db]
proc hashLogEntries(logs: seq[Log]): string =
toLowerAscii("0x" & $keccakHash(rlp.encode(logs)))
type
Tester = object
name: string
header: BlockHeader
pre: JsonNode
tx: Transaction
expectedHash: string
expectedLogs: string
fork: Fork
debugMode: bool
proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus)
proc dumpAccount(accountDb: ReadOnlyStateDB, address: EthAddress, name: string): JsonNode =
result = %{
"name": %name,
"address": %($address),
"nonce": %toHex(accountDb.getNonce(address)),
"balance": %accountDb.getBalance(address).toHex(),
"codehash": %($accountDb.getCodeHash(address)),
"storageRoot": %($accountDb.getStorageRoot(address))
}
suite "generalstate json tests":
jsonTest("GeneralStateTests", testFixture)
proc dumpDebugData(tester: Tester, vmState: BaseVMState, sender: EthAddress, gasUsed: GasInt) =
let recipient = tester.tx.getRecipient()
let miner = tester.header.coinbase
var accounts = newJObject()
proc testFixtureIndexes(prevStateRoot: Hash256, header: BlockHeader, pre: JsonNode, tx: Transaction,
expectedHash, expectedLogs: 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)
accounts[$miner] = dumpAccount(vmState.readOnlyStateDB, miner, "miner")
accounts[$sender] = dumpAccount(vmState.readOnlyStateDB, sender, "sender")
accounts[$recipient] = dumpAccount(vmState.readOnlyStateDB, recipient, "recipient")
let accountList = [sender, miner, recipient]
var i = 0
for ac, _ in tester.pre:
let account = ethAddressFromHex(ac)
if account notin accountList:
accounts[$account] = dumpAccount(vmState.readOnlyStateDB, account, "pre" & $i)
inc i
let debugData = %{
"gasUsed": %gasUsed,
"structLogs": vmState.getTracingResult(),
"accounts": accounts
}
writeFile("debug_" & tester.name & ".json", debugData.pretty())
proc testFixtureIndexes(tester: Tester, testStatusIMPL: var TestStatus) =
var tracerFlags: set[TracerFlags] = if tester.debugMode: {TracerFlags.EnableTracing} else : {}
var vmState = newBaseVMState(emptyRlpHash, tester.header, newBaseChainDB(newMemoryDb()), tracerFlags)
vmState.mutateStateDB:
setupStateDB(pre, db)
setupStateDB(tester.pre, db)
defer:
#echo vmState.readOnlyStateDB.dumpAccount("c94f5374fce5edbc8e2a8697c15331677e6ebf0b")
let obtainedHash = "0x" & `$`(vmState.readOnlyStateDB.rootHash).toLowerAscii
check obtainedHash == expectedHash
check obtainedHash == tester.expectedHash
let logEntries = vmState.getAndClearLogEntries()
let actualLogsHash = hashLogEntries(logEntries)
let expectedLogsHash = toLowerAscii(expectedLogs)
let expectedLogsHash = toLowerAscii(tester.expectedLogs)
check(expectedLogsHash == actualLogsHash)
let sender = tx.getSender()
if not validateTransaction(vmState, tx, sender):
let sender = tester.tx.getSender()
if not validateTransaction(vmState, tester.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)
db.addBalance(tester.header.coinbase, 0.u256)
return
var gasUsed: GasInt
vmState.mutateStateDB:
let gasUsed = tx.processTransaction(sender, vmState, some(fork))
db.addBalance(header.coinbase, gasUsed.u256 * tx.gasPrice.u256)
gasUsed = tester.tx.processTransaction(sender, vmState, some(tester.fork))
db.addBalance(tester.header.coinbase, gasUsed.u256 * tester.tx.gasPrice.u256)
proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus) =
if tester.debugMode:
tester.dumpDebugData(vmState, sender, gasUsed)
proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus, debugMode = false) =
var tester: Tester
var fixture: JsonNode
for label, child in fixtures:
fixture = child
tester.name = label
break
let fenv = fixture["env"]
var emptyRlpHash = keccak256.digest(rlp.encode(""))
let header = BlockHeader(
tester.header = BlockHeader(
coinbase: fenv["currentCoinbase"].getStr.ethAddressFromHex,
difficulty: fromHex(UInt256, fenv{"currentDifficulty"}.getStr),
blockNumber: fenv{"currentNumber"}.getHexadecimalInt.u256,
@ -71,18 +108,34 @@ proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus) =
stateRoot: emptyRlpHash
)
tester.debugMode = debugMode
let ftrans = fixture["transaction"]
for fork in supportedForks:
if fixture["post"].hasKey(forkNames[fork]):
# echo "[fork: ", forkNames[fork], "]"
for expectation in fixture["post"][forkNames[fork]]:
tester.expectedHash = expectation["hash"].getStr
tester.expectedLogs = expectation["logs"].getStr
let
expectedHash = expectation["hash"].getStr
expectedLogs = expectation["logs"].getStr
indexes = expectation["indexes"]
dataIndex = indexes["data"].getInt
gasIndex = indexes["gas"].getInt
valueIndex = indexes["value"].getInt
let transaction = ftrans.getFixtureTransaction(dataIndex, gasIndex, valueIndex)
testFixtureIndexes(emptyRlpHash, header, fixture["pre"], transaction,
expectedHash, expectedLogs, testStatusIMPL, fork)
tester.tx = ftrans.getFixtureTransaction(dataIndex, gasIndex, valueIndex)
tester.pre = fixture["pre"]
tester.fork = fork
testFixtureIndexes(tester, testStatusIMPL)
proc main() =
if paramCount() == 0:
# run all test fixtures
suite "generalstate json tests":
jsonTest("GeneralStateTests", testFixture)
else:
# execute single test in debug mode
let path = "tests" / "fixtures" / "GeneralStateTests"
let n = json.parseFile(path / paramStr(1))
var testStatusIMPL: TestStatus
testFixture(n, testStatusIMPL, true)
main()

View File

@ -7,10 +7,10 @@
import
os, macros, json, strformat, strutils, parseutils, ospaths, tables,
byteutils, eth/[common, keys], ranges/typedranges,
byteutils, eth/[common, keys, rlp], ranges/typedranges,
../nimbus/[vm_state, constants],
../nimbus/db/[db_chain, state_db],
../nimbus/transaction,
../nimbus/[transaction, utils],
../nimbus/vm/interpreter/[gas_costs, vm_forks],
../tests/test_generalstate_failing
@ -290,3 +290,7 @@ proc getFixtureTransaction*(j: JsonNode, dataIndex, gasIndex, valueIndex: int):
result.R = fromBytesBE(Uint256, raw[0..31])
result.S = fromBytesBE(Uint256, raw[32..63])
result.V = raw[64] + 27.byte
proc hashLogEntries*(logs: seq[Log]): string =
toLowerAscii("0x" & $keccakHash(rlp.encode(logs)))

View File

@ -16,15 +16,11 @@ import
../nimbus/vm/interpreter,
../nimbus/db/[db_chain, state_db]
proc hashLogEntries(logs: seq[Log]): string =
toLowerAscii("0x" & $keccakHash(rlp.encode(logs)))
proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus)
suite "vm json tests":
jsonTest("VMTests", testFixture)
proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus) =
var fixture: JsonNode
for label, child in fixtures: