more VM tracing

The existing vmState tracing is plugged into chronicles, at the TRACE
level, to facilitate state test debugging.

Some useful chronicles defines are added to "tests/nim.cfg" to simplify
the compile-and-run command for individual tests.
This commit is contained in:
Ștefan Talpalaru 2018-12-12 00:26:08 +01:00
parent d633bb9ebf
commit f91e69f7c7
No known key found for this signature in database
GPG Key ID: CBF7934204F1B6F9
5 changed files with 26 additions and 6 deletions

View File

@ -13,6 +13,9 @@ import
../vm_types, ../errors, precompiles, ../vm_types, ../errors, precompiles,
./stack, ./computation, terminal # Those are only needed for logging ./stack, ./computation, terminal # Those are only needed for logging
logScope:
topics = "vm opcode"
func invalidInstruction*(computation: var BaseComputation) {.inline.} = func invalidInstruction*(computation: var BaseComputation) {.inline.} =
raise newException(ValueError, "Invalid instruction, received an opcode not implemented in the current fork.") raise newException(ValueError, "Invalid instruction, received an opcode not implemented in the current fork.")
@ -186,7 +189,9 @@ proc opTableToCaseStmt(opTable: array[Op, NimNode], computation: NimNode): NimNo
for op, opImpl in opTable.pairs: for op, opImpl in opTable.pairs:
let branchStmt = block: let branchStmt = block:
if op == Stop: if op == Stop:
quote do: break quote do:
trace "op: Stop"
break
else: else:
let asOp = quote do: Op(`op`) # TODO: unfortunately when passing to runtime, ops are transformed into int let asOp = quote do: Op(`op`) # TODO: unfortunately when passing to runtime, ops are transformed into int
if BaseGasCosts[op].kind == GckFixed: if BaseGasCosts[op].kind == GckFixed:

View File

@ -1,8 +1,12 @@
import import
json, strutils, nimcrypto, eth_common, stint, json, strutils,
chronicles, nimcrypto, eth_common, stint,
../vm_types, memory, stack, ../db/[db_chain, state_db], ../vm_types, memory, stack, ../db/[db_chain, state_db],
eth_trie/hexary, ./message, ranges/typedranges eth_trie/hexary, ./message, ranges/typedranges
logScope:
topics = "vm opcode"
proc initTracer*(tracer: var TransactionTracer, flags: set[TracerFlags] = {}) = proc initTracer*(tracer: var TransactionTracer, flags: set[TracerFlags] = {}) =
tracer.trace = newJObject() tracer.trace = newJObject()
@ -47,7 +51,7 @@ proc traceOpCodeEnded*(tracer: var TransactionTracer, c: BaseComputation) =
let j = tracer.trace["structLogs"].elems[^1] let j = tracer.trace["structLogs"].elems[^1]
# TODO: figure out how to get storage # TODO: figure out how to get storage
# when contract excecution interrupted by exception # when contract execution interrupted by exception
if TracerFlags.DisableStorage notin tracer.flags: if TracerFlags.DisableStorage notin tracer.flags:
var storage = newJObject() var storage = newJObject()
var stateDB = c.vmState.chaindb.getStateDb(c.vmState.blockHeader.stateRoot, readOnly = true) var stateDB = c.vmState.chaindb.getStateDb(c.vmState.blockHeader.stateRoot, readOnly = true)
@ -62,6 +66,8 @@ proc traceOpCodeEnded*(tracer: var TransactionTracer, c: BaseComputation) =
j["returnValue"] = returnValue j["returnValue"] = returnValue
tracer.trace["returnValue"] = returnValue tracer.trace["returnValue"] = returnValue
trace "Op", json = j.pretty()
proc traceError*(tracer: var TransactionTracer, c: BaseComputation) = proc traceError*(tracer: var TransactionTracer, c: BaseComputation) =
let j = tracer.trace["structLogs"].elems[^1] let j = tracer.trace["structLogs"].elems[^1]
@ -72,3 +78,5 @@ proc traceError*(tracer: var TransactionTracer, c: BaseComputation) =
j["error"] = %(c.error.info) j["error"] = %(c.error.info)
tracer.trace["failed"] = %true tracer.trace["failed"] = %true
trace "Error", json = j.pretty()

3
tests/nim.cfg Normal file
View File

@ -0,0 +1,3 @@
-d:chronicles_line_numbers
-d:"chronicles_sinks=textblocks"

View File

@ -9,7 +9,7 @@ import
unittest, strformat, strutils, tables, json, ospaths, times, unittest, strformat, strutils, tables, json, ospaths, times,
byteutils, ranges/typedranges, nimcrypto/[keccak, hash], options, byteutils, ranges/typedranges, nimcrypto/[keccak, hash], options,
rlp, eth_trie/db, eth_common, rlp, eth_trie/db, eth_common,
eth_keys, eth_keys, chronicles,
./test_helpers, ./test_helpers,
../nimbus/[constants, errors], ../nimbus/[constants, errors],
../nimbus/[vm_state, vm_types, vm_state_transactions], ../nimbus/[vm_state, vm_types, vm_state_transactions],
@ -24,7 +24,11 @@ suite "generalstate json tests":
proc testFixtureIndexes(header: BlockHeader, pre: JsonNode, transaction: Transaction, sender: EthAddress, expectedHash: string, testStatusIMPL: var TestStatus, fork: Fork) = proc testFixtureIndexes(header: BlockHeader, pre: JsonNode, transaction: Transaction, sender: EthAddress, expectedHash: string, testStatusIMPL: var TestStatus, fork: Fork) =
var vmState = newBaseVMState(header, newBaseChainDB(newMemoryDb())) when enabledLogLevel <= TRACE:
let tracerFlags = {TracerFlags.EnableTracing}
else:
let tracerFlags: set[TracerFlags] = {}
var vmState = newBaseVMState(header, newBaseChainDB(newMemoryDb()), tracerFlags)
vmState.mutateStateDB: vmState.mutateStateDB:
setupStateDB(pre, db) setupStateDB(pre, db)