Initial TransactionTracer impl

This commit is contained in:
Yuriy Glukhov 2018-10-28 14:11:19 +02:00 committed by tersec
parent 5095bfa8d8
commit bac452f589
3 changed files with 57 additions and 2 deletions

View File

@ -11,7 +11,7 @@ import
./interpreter/[opcode_values, opcodes_impl, vm_forks, gas_costs, gas_meter, utils/macros_gen_opcodes],
./code_stream,
../vm_types, ../errors,
./stack, ./computation, terminal # Those are only needed for logging
./stack, ./computation, ./transaction_tracer, terminal # Those are only needed for logging
func invalidInstruction*(computation: var BaseComputation) {.inline.} =
raise newException(ValueError, "Invalid instruction, received an opcode not implemented in the current fork.")
@ -191,12 +191,20 @@ proc opTableToCaseStmt(opTable: array[Op, NimNode], computation: NimNode): NimNo
let asOp = quote do: Op(`op`) # TODO: unfortunately when passing to runtime, ops are transformed into int
if BaseGasCosts[op].kind == GckFixed:
quote do:
if `computation`.tracingEnabled:
`computation`.tracer.traceOpCodeStarted(`computation`, $`asOp`)
`computation`.gasMeter.consumeGas(`computation`.gasCosts[`asOp`].cost, reason = $`asOp`)
`opImpl`(`computation`)
if `computation`.tracingEnabled:
`computation`.tracer.traceOpCodeEnded(`computation`)
`instr` = `computation`.code.next()
else:
quote do:
if `computation`.tracingEnabled:
`computation`.tracer.traceOpCodeStarted(`computation`, $`asOp`)
`opImpl`(`computation`)
if `computation`.tracingEnabled:
`computation`.tracer.traceOpCodeEnded(`computation`)
when `asOp` in {Return, Revert, SelfDestruct}:
break
else:

View File

@ -0,0 +1,40 @@
import
json, strutils,
eth_common, stint, byteutils,
../vm_types, memory, stack
proc initTrace(t: var TransactionTracer) =
t.trace = newJObject()
t.trace["structLogs"] = newJArray()
proc traceOpCodeStarted*(t: var TransactionTracer, c: BaseComputation, op: string) =
if unlikely t.trace.isNil:
t.initTrace()
let j = newJObject()
t.trace["structLogs"].add(j)
j["op"] = %op.toUpperAscii
j["pc"] = %(c.code.pc - 1)
j["depth"] = %1 # stub
j["gas"] = %c.gasMeter.gasRemaining
t.gasRemaining = c.gasMeter.gasRemaining
# log stack
let st = newJArray()
for v in c.stack.values:
st.add(%v.dumpHex())
j["stack"] = st
# log memory
let mem = newJArray()
const chunkLen = 32
let numChunks = c.memory.len div chunkLen
for i in 0 ..< numChunks:
mem.add(%c.memory.bytes.toOpenArray(i * chunkLen, (i + 1) * chunkLen - 1).toHex())
j["memory"] = mem
# TODO: log storage
proc traceOpCodeEnded*(t: var TransactionTracer, c: BaseComputation) =
let j = t.trace["structLogs"].elems[^1]
j["gasCost"] = %(t.gasRemaining - c.gasMeter.gasRemaining)

View File

@ -6,7 +6,7 @@
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
tables,
tables, json,
eth_common,
./constants, ./vm_state,
./vm/[memory, stack, code_stream],
@ -35,6 +35,8 @@ type
precompiles*: Table[string, Opcode]
gasCosts*: GasCosts # TODO - will be hidden at a lower layer
opCodeExec*: OpcodeExecutor
tracingEnabled*: bool
tracer*: TransactionTracer
Error* = ref object
info*: string
@ -105,3 +107,8 @@ type
createAddress*: EthAddress
codeAddress*: EthAddress
flags*: MsgFlags
TransactionTracer* = object
trace*: JsonNode
gasRemaining*: GasInt