Add current computation to each EVM tracer interface (#1712)
This commit is contained in:
parent
7aead6151e
commit
91704cd3ae
|
@ -107,9 +107,11 @@ proc asyncProcessTransactionImpl(
|
||||||
vmState.stateDB.clearTransientStorage()
|
vmState.stateDB.clearTransientStorage()
|
||||||
|
|
||||||
# Execute the transaction.
|
# Execute the transaction.
|
||||||
|
vmState.captureTxStart(tx.gasLimit)
|
||||||
let
|
let
|
||||||
accTx = vmState.stateDB.beginSavepoint
|
accTx = vmState.stateDB.beginSavepoint
|
||||||
gasBurned = tx.txCallEvm(sender, vmState, fork)
|
gasBurned = tx.txCallEvm(sender, vmState, fork)
|
||||||
|
vmState.captureTxEnd(tx.gasLimit - gasBurned)
|
||||||
|
|
||||||
res = commitOrRollbackDependingOnGasUsed(vmState, accTx, header, tx, gasBurned, priorityFee)
|
res = commitOrRollbackDependingOnGasUsed(vmState, accTx, header, tx, gasBurned, priorityFee)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -390,16 +390,18 @@ proc tracingEnabled*(c: Computation): bool =
|
||||||
|
|
||||||
proc traceOpCodeStarted*(c: Computation, op: Op): int {.gcsafe, raises: [].} =
|
proc traceOpCodeStarted*(c: Computation, op: Op): int {.gcsafe, raises: [].} =
|
||||||
c.vmState.captureOpStart(
|
c.vmState.captureOpStart(
|
||||||
|
c,
|
||||||
c.code.pc - 1,
|
c.code.pc - 1,
|
||||||
op,
|
op,
|
||||||
c.gasMeter.gasRemaining,
|
c.gasMeter.gasRemaining,
|
||||||
c.msg.depth + 1)
|
c.msg.depth + 1)
|
||||||
|
|
||||||
proc traceCallFamilyGas*(c: Computation, op: Op, gas: GasInt) {.gcsafe, raises: [].} =
|
proc traceCallFamilyGas*(c: Computation, op: Op, gas: GasInt) {.gcsafe, raises: [].} =
|
||||||
c.vmState.callFamilyGas(op, gas, c.msg.depth + 1)
|
c.vmState.callFamilyGas(c, op, gas, c.msg.depth + 1)
|
||||||
|
|
||||||
proc traceOpCodeEnded*(c: Computation, op: Op, opIndex: int) {.gcsafe, raises: [].} =
|
proc traceOpCodeEnded*(c: Computation, op: Op, opIndex: int) {.gcsafe, raises: [].} =
|
||||||
c.vmState.captureOpEnd(
|
c.vmState.captureOpEnd(
|
||||||
|
c,
|
||||||
c.code.pc - 1,
|
c.code.pc - 1,
|
||||||
op,
|
op,
|
||||||
c.gasMeter.gasRemaining,
|
c.gasMeter.gasRemaining,
|
||||||
|
@ -410,6 +412,7 @@ proc traceOpCodeEnded*(c: Computation, op: Op, opIndex: int) {.gcsafe, raises: [
|
||||||
|
|
||||||
proc traceError*(c: Computation) {.gcsafe, raises: [].} =
|
proc traceError*(c: Computation) {.gcsafe, raises: [].} =
|
||||||
c.vmState.captureFault(
|
c.vmState.captureFault(
|
||||||
|
c,
|
||||||
c.code.pc - 1,
|
c.code.pc - 1,
|
||||||
c.instr,
|
c.instr,
|
||||||
c.gasMeter.gasRemaining,
|
c.gasMeter.gasRemaining,
|
||||||
|
@ -419,7 +422,7 @@ proc traceError*(c: Computation) {.gcsafe, raises: [].} =
|
||||||
some(c.error.info))
|
some(c.error.info))
|
||||||
|
|
||||||
proc prepareTracer*(c: Computation) =
|
proc prepareTracer*(c: Computation) =
|
||||||
c.vmState.capturePrepare(c.msg.depth)
|
c.vmState.capturePrepare(c, c.msg.depth)
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# End
|
# End
|
||||||
|
|
|
@ -190,7 +190,8 @@ proc beforeExec(c: Computation): bool
|
||||||
{.gcsafe, raises: [ValueError].} =
|
{.gcsafe, raises: [ValueError].} =
|
||||||
|
|
||||||
if c.msg.depth > 0:
|
if c.msg.depth > 0:
|
||||||
c.vmState.captureEnter(msgToOp(c.msg),
|
c.vmState.captureEnter(c,
|
||||||
|
msgToOp(c.msg),
|
||||||
c.msg.sender, c.msg.contractAddress,
|
c.msg.sender, c.msg.contractAddress,
|
||||||
c.msg.data, c.msg.gas,
|
c.msg.data, c.msg.gas,
|
||||||
c.msg.value)
|
c.msg.value)
|
||||||
|
@ -215,7 +216,7 @@ proc afterExec(c: Computation)
|
||||||
some(c.error.info)
|
some(c.error.info)
|
||||||
else:
|
else:
|
||||||
none(string)
|
none(string)
|
||||||
c.vmState.captureExit(c.output, gasUsed, error)
|
c.vmState.captureExit(c, c.output, gasUsed, error)
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Public functions
|
# Public functions
|
||||||
|
|
|
@ -363,56 +363,57 @@ proc captureTxEnd*(vmState: BaseVMState, restGas: GasInt) =
|
||||||
if vmState.tracingEnabled:
|
if vmState.tracingEnabled:
|
||||||
vmState.tracer.captureTxEnd(restGas)
|
vmState.tracer.captureTxEnd(restGas)
|
||||||
|
|
||||||
proc captureStart*(vmState: BaseVMState, c: Computation,
|
proc captureStart*(vmState: BaseVMState, comp: Computation,
|
||||||
sender: EthAddress, to: EthAddress,
|
sender: EthAddress, to: EthAddress,
|
||||||
create: bool, input: openArray[byte],
|
create: bool, input: openArray[byte],
|
||||||
gas: GasInt, value: UInt256) =
|
gasLimit: GasInt, value: UInt256) =
|
||||||
if vmState.tracingEnabled:
|
if vmState.tracingEnabled:
|
||||||
vmState.tracer.captureStart(c, sender, to, create, input, gas, value)
|
vmState.tracer.captureStart(comp, sender, to, create, input, gasLimit, value)
|
||||||
|
|
||||||
proc captureEnd*(vmState: BaseVMState, output: openArray[byte],
|
proc captureEnd*(vmState: BaseVMState, comp: Computation, output: openArray[byte],
|
||||||
gasUsed: GasInt, error: Option[string]) =
|
gasUsed: GasInt, error: Option[string]) =
|
||||||
if vmState.tracingEnabled:
|
if vmState.tracingEnabled:
|
||||||
vmState.tracer.captureEnd(output, gasUsed, error)
|
vmState.tracer.captureEnd(comp, output, gasUsed, error)
|
||||||
|
|
||||||
proc captureEnter*(vmState: BaseVMState, op: Op,
|
proc captureEnter*(vmState: BaseVMState, comp: Computation, op: Op,
|
||||||
sender: EthAddress, to: EthAddress,
|
sender: EthAddress, to: EthAddress,
|
||||||
input: openArray[byte], gas: GasInt,
|
input: openArray[byte], gasLimit: GasInt,
|
||||||
value: UInt256) =
|
value: UInt256) =
|
||||||
if vmState.tracingEnabled:
|
if vmState.tracingEnabled:
|
||||||
vmState.tracer.captureEnter(op, sender, to, input, gas, value)
|
vmState.tracer.captureEnter(comp, op, sender, to, input, gasLimit, value)
|
||||||
|
|
||||||
proc captureExit*(vmState: BaseVMState, output: openArray[byte],
|
proc captureExit*(vmState: BaseVMState, comp: Computation, output: openArray[byte],
|
||||||
gasUsed: GasInt, error: Option[string]) =
|
gasUsed: GasInt, error: Option[string]) =
|
||||||
if vmState.tracingEnabled:
|
if vmState.tracingEnabled:
|
||||||
vmState.tracer.captureExit(output, gasUsed, error)
|
vmState.tracer.captureExit(comp, output, gasUsed, error)
|
||||||
|
|
||||||
proc captureOpStart*(vmState: BaseVMState, pc: int,
|
proc captureOpStart*(vmState: BaseVMState, comp: Computation, pc: int,
|
||||||
op: Op, gas: GasInt,
|
op: Op, gas: GasInt,
|
||||||
depth: int): int =
|
depth: int): int =
|
||||||
if vmState.tracingEnabled:
|
if vmState.tracingEnabled:
|
||||||
result = vmState.tracer.captureOpStart(pc, op, gas, depth)
|
result = vmState.tracer.captureOpStart(comp, pc, op, gas, depth)
|
||||||
|
|
||||||
proc callFamilyGas*(vmState: BaseVMState,
|
proc callFamilyGas*(vmState: BaseVMState,
|
||||||
|
comp: Computation,
|
||||||
op: Op, gas: GasInt,
|
op: Op, gas: GasInt,
|
||||||
depth: int) =
|
depth: int) =
|
||||||
if vmState.tracingEnabled:
|
if vmState.tracingEnabled:
|
||||||
vmState.tracer.callFamilyGas(op, gas, depth)
|
vmState.tracer.callFamilyGas(comp, op, gas, depth)
|
||||||
|
|
||||||
proc captureOpEnd*(vmState: BaseVMState, pc: int,
|
proc captureOpEnd*(vmState: BaseVMState, comp: Computation, pc: int,
|
||||||
op: Op, gas: GasInt, refund: GasInt,
|
op: Op, gas: GasInt, refund: GasInt,
|
||||||
rData: openArray[byte],
|
rData: openArray[byte],
|
||||||
depth: int, opIndex: int) =
|
depth: int, opIndex: int) =
|
||||||
if vmState.tracingEnabled:
|
if vmState.tracingEnabled:
|
||||||
vmState.tracer.captureOpEnd(pc, op, gas, refund, rData, depth, opIndex)
|
vmState.tracer.captureOpEnd(comp, pc, op, gas, refund, rData, depth, opIndex)
|
||||||
|
|
||||||
proc captureFault*(vmState: BaseVMState, pc: int,
|
proc captureFault*(vmState: BaseVMState, comp: Computation, pc: int,
|
||||||
op: Op, gas: GasInt, refund: GasInt,
|
op: Op, gas: GasInt, refund: GasInt,
|
||||||
rData: openArray[byte],
|
rData: openArray[byte],
|
||||||
depth: int, error: Option[string]) =
|
depth: int, error: Option[string]) =
|
||||||
if vmState.tracingEnabled:
|
if vmState.tracingEnabled:
|
||||||
vmState.tracer.captureFault(pc, op, gas, refund, rData, depth, error)
|
vmState.tracer.captureFault(comp, pc, op, gas, refund, rData, depth, error)
|
||||||
|
|
||||||
proc capturePrepare*(vmState: BaseVMState, depth: int) =
|
proc capturePrepare*(vmState: BaseVMState, comp: Computation, depth: int) =
|
||||||
if vmState.tracingEnabled:
|
if vmState.tracingEnabled:
|
||||||
vmState.tracer.capturePrepare(depth)
|
vmState.tracer.capturePrepare(comp, depth)
|
||||||
|
|
|
@ -23,7 +23,6 @@ type
|
||||||
JsonTracer* = ref object of TracerRef
|
JsonTracer* = ref object of TracerRef
|
||||||
stream: Stream
|
stream: Stream
|
||||||
pretty: bool
|
pretty: bool
|
||||||
comp: Computation
|
|
||||||
gas: GasInt
|
gas: GasInt
|
||||||
pc: int
|
pc: int
|
||||||
stack: JsonNode
|
stack: JsonNode
|
||||||
|
@ -76,13 +75,12 @@ iterator storage(ctx: JsonTracer, compDepth: int): UInt256 =
|
||||||
for key in ctx.storageKeys[compDepth]:
|
for key in ctx.storageKeys[compDepth]:
|
||||||
yield key
|
yield key
|
||||||
|
|
||||||
proc captureOpImpl(ctx: JsonTracer, pc: int,
|
proc captureOpImpl(ctx: JsonTracer, c: Computation, pc: int,
|
||||||
op: Op, gas: GasInt, refund: GasInt,
|
op: Op, gas: GasInt, refund: GasInt,
|
||||||
rData: openArray[byte],
|
rData: openArray[byte],
|
||||||
depth: int, error: Option[string]) {.gcsafe.} =
|
depth: int, error: Option[string]) {.gcsafe.} =
|
||||||
let
|
let
|
||||||
gasCost = ctx.gas - gas
|
gasCost = ctx.gas - gas
|
||||||
c = ctx.comp
|
|
||||||
|
|
||||||
var res = %{
|
var res = %{
|
||||||
"pc": %(ctx.pc),
|
"pc": %(ctx.pc),
|
||||||
|
@ -139,7 +137,7 @@ proc newJsonTracer*(stream: Stream, flags: set[TracerFlags], pretty: bool): Json
|
||||||
pretty: pretty
|
pretty: pretty
|
||||||
)
|
)
|
||||||
|
|
||||||
method capturePrepare*(ctx: JsonTracer, depth: int) {.gcsafe.} =
|
method capturePrepare*(ctx: JsonTracer, comp: Computation, depth: int) {.gcsafe.} =
|
||||||
if depth >= ctx.storageKeys.len:
|
if depth >= ctx.storageKeys.len:
|
||||||
let prevLen = ctx.storageKeys.len
|
let prevLen = ctx.storageKeys.len
|
||||||
ctx.storageKeys.setLen(depth + 1)
|
ctx.storageKeys.setLen(depth + 1)
|
||||||
|
@ -149,13 +147,13 @@ method capturePrepare*(ctx: JsonTracer, depth: int) {.gcsafe.} =
|
||||||
ctx.storageKeys[depth] = initHashSet[UInt256]()
|
ctx.storageKeys[depth] = initHashSet[UInt256]()
|
||||||
|
|
||||||
# Top call frame
|
# Top call frame
|
||||||
method captureStart*(ctx: JsonTracer, c: Computation,
|
method captureStart*(ctx: JsonTracer, comp: Computation,
|
||||||
sender: EthAddress, to: EthAddress,
|
sender: EthAddress, to: EthAddress,
|
||||||
create: bool, input: openArray[byte],
|
create: bool, input: openArray[byte],
|
||||||
gas: GasInt, value: UInt256) {.gcsafe.} =
|
gasLimit: GasInt, value: UInt256) {.gcsafe.} =
|
||||||
ctx.comp = c
|
discard
|
||||||
|
|
||||||
method captureEnd*(ctx: JsonTracer, output: openArray[byte],
|
method captureEnd*(ctx: JsonTracer, comp: Computation, output: openArray[byte],
|
||||||
gasUsed: GasInt, error: Option[string]) {.gcsafe.} =
|
gasUsed: GasInt, error: Option[string]) {.gcsafe.} =
|
||||||
var res = %{
|
var res = %{
|
||||||
"output": %(output),
|
"output": %(output),
|
||||||
|
@ -166,21 +164,19 @@ method captureEnd*(ctx: JsonTracer, output: openArray[byte],
|
||||||
ctx.writeJson(res)
|
ctx.writeJson(res)
|
||||||
|
|
||||||
# Opcode level
|
# Opcode level
|
||||||
method captureOpStart*(ctx: JsonTracer, pc: int,
|
method captureOpStart*(ctx: JsonTracer, c: Computation, pc: int,
|
||||||
op: Op, gas: GasInt,
|
op: Op, gas: GasInt,
|
||||||
depth: int): int {.gcsafe.} =
|
depth: int): int {.gcsafe.} =
|
||||||
ctx.gas = gas
|
ctx.gas = gas
|
||||||
ctx.pc = pc
|
ctx.pc = pc
|
||||||
|
|
||||||
if TracerFlags.DisableStack notin ctx.flags:
|
if TracerFlags.DisableStack notin ctx.flags:
|
||||||
let c = ctx.comp
|
|
||||||
ctx.stack = newJArray()
|
ctx.stack = newJArray()
|
||||||
for v in c.stack.values:
|
for v in c.stack.values:
|
||||||
ctx.stack.add(%("0x" & v.dumpHex.stripLeadingZeros))
|
ctx.stack.add(%("0x" & v.dumpHex.stripLeadingZeros))
|
||||||
|
|
||||||
if TracerFlags.DisableStorage notin ctx.flags and op == SSTORE:
|
if TracerFlags.DisableStorage notin ctx.flags and op == SSTORE:
|
||||||
try:
|
try:
|
||||||
let c = ctx.comp
|
|
||||||
if c.stack.values.len > 1:
|
if c.stack.values.len > 1:
|
||||||
ctx.rememberStorageKey(c.msg.depth, c.stack[^1, UInt256])
|
ctx.rememberStorageKey(c.msg.depth, c.stack[^1, UInt256])
|
||||||
except InsufficientStack as ex:
|
except InsufficientStack as ex:
|
||||||
|
@ -190,7 +186,7 @@ method captureOpStart*(ctx: JsonTracer, pc: int,
|
||||||
|
|
||||||
if op in callFamily:
|
if op in callFamily:
|
||||||
try:
|
try:
|
||||||
ctx.captureOpImpl(pc, op, 0, 0, [], depth, none(string))
|
ctx.captureOpImpl(c, pc, op, 0, 0, [], depth, none(string))
|
||||||
except RlpError as ex:
|
except RlpError as ex:
|
||||||
error "JsonTracer captureOpEnd", msg=ex.msg
|
error "JsonTracer captureOpEnd", msg=ex.msg
|
||||||
|
|
||||||
|
@ -198,7 +194,7 @@ method captureOpStart*(ctx: JsonTracer, pc: int,
|
||||||
result = ctx.index
|
result = ctx.index
|
||||||
inc ctx.index
|
inc ctx.index
|
||||||
|
|
||||||
method callFamilyGas*(ctx: JsonTracer,
|
method callFamilyGas*(ctx: JsonTracer, comp: Computation,
|
||||||
op: Op, gas: GasInt,
|
op: Op, gas: GasInt,
|
||||||
depth: int) {.gcsafe.} =
|
depth: int) {.gcsafe.} =
|
||||||
doAssert(op in callFamily)
|
doAssert(op in callFamily)
|
||||||
|
@ -207,7 +203,7 @@ method callFamilyGas*(ctx: JsonTracer,
|
||||||
res["gasCost"] = encodeHexInt(gas)
|
res["gasCost"] = encodeHexInt(gas)
|
||||||
ctx.writeJson(res)
|
ctx.writeJson(res)
|
||||||
|
|
||||||
method captureOpEnd*(ctx: JsonTracer, pc: int,
|
method captureOpEnd*(ctx: JsonTracer, comp: Computation, pc: int,
|
||||||
op: Op, gas: GasInt, refund: GasInt,
|
op: Op, gas: GasInt, refund: GasInt,
|
||||||
rData: openArray[byte],
|
rData: openArray[byte],
|
||||||
depth: int, opIndex: int) {.gcsafe.} =
|
depth: int, opIndex: int) {.gcsafe.} =
|
||||||
|
@ -217,16 +213,16 @@ method captureOpEnd*(ctx: JsonTracer, pc: int,
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
ctx.captureOpImpl(pc, op, gas, refund, rData, depth, none(string))
|
ctx.captureOpImpl(comp, pc, op, gas, refund, rData, depth, none(string))
|
||||||
except RlpError as ex:
|
except RlpError as ex:
|
||||||
error "JsonTracer captureOpEnd", msg=ex.msg
|
error "JsonTracer captureOpEnd", msg=ex.msg
|
||||||
|
|
||||||
method captureFault*(ctx: JsonTracer, pc: int,
|
method captureFault*(ctx: JsonTracer, comp: Computation, pc: int,
|
||||||
op: Op, gas: GasInt, refund: GasInt,
|
op: Op, gas: GasInt, refund: GasInt,
|
||||||
rData: openArray[byte],
|
rData: openArray[byte],
|
||||||
depth: int, error: Option[string]) {.gcsafe.} =
|
depth: int, error: Option[string]) {.gcsafe.} =
|
||||||
try:
|
try:
|
||||||
ctx.captureOpImpl(pc, op, gas, refund, rData, depth, error)
|
ctx.captureOpImpl(comp, pc, op, gas, refund, rData, depth, error)
|
||||||
except RlpError as ex:
|
except RlpError as ex:
|
||||||
error "JsonTracer captureOpEnd", msg=ex.msg
|
error "JsonTracer captureOpEnd", msg=ex.msg
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,6 @@ type
|
||||||
trace: JsonNode
|
trace: JsonNode
|
||||||
accounts: HashSet[EthAddress]
|
accounts: HashSet[EthAddress]
|
||||||
storageKeys: seq[HashSet[UInt256]]
|
storageKeys: seq[HashSet[UInt256]]
|
||||||
comp: Computation
|
|
||||||
gas: GasInt
|
gas: GasInt
|
||||||
|
|
||||||
proc hash*(x: UInt256): Hash =
|
proc hash*(x: UInt256): Hash =
|
||||||
|
@ -62,7 +61,7 @@ proc newLegacyTracer*(flags: set[TracerFlags]): LegacyTracer =
|
||||||
trace: trace
|
trace: trace
|
||||||
)
|
)
|
||||||
|
|
||||||
method capturePrepare*(ctx: LegacyTracer, depth: int) {.gcsafe.} =
|
method capturePrepare*(ctx: LegacyTracer, comp: Computation, depth: int) {.gcsafe.} =
|
||||||
if depth >= ctx.storageKeys.len:
|
if depth >= ctx.storageKeys.len:
|
||||||
let prevLen = ctx.storageKeys.len
|
let prevLen = ctx.storageKeys.len
|
||||||
ctx.storageKeys.setLen(depth + 1)
|
ctx.storageKeys.setLen(depth + 1)
|
||||||
|
@ -71,25 +70,13 @@ method capturePrepare*(ctx: LegacyTracer, depth: int) {.gcsafe.} =
|
||||||
|
|
||||||
ctx.storageKeys[depth] = initHashSet[UInt256]()
|
ctx.storageKeys[depth] = initHashSet[UInt256]()
|
||||||
|
|
||||||
# Top call frame
|
|
||||||
method captureStart*(ctx: LegacyTracer, c: Computation,
|
|
||||||
sender: EthAddress, to: EthAddress,
|
|
||||||
create: bool, input: openArray[byte],
|
|
||||||
gas: GasInt, value: UInt256) {.gcsafe.} =
|
|
||||||
ctx.comp = c
|
|
||||||
|
|
||||||
method captureEnd*(ctx: LegacyTracer, output: openArray[byte],
|
|
||||||
gasUsed: GasInt, error: Option[string]) {.gcsafe.} =
|
|
||||||
discard
|
|
||||||
|
|
||||||
# Opcode level
|
# Opcode level
|
||||||
method captureOpStart*(ctx: LegacyTracer, pc: int,
|
method captureOpStart*(ctx: LegacyTracer, c: Computation, pc: int,
|
||||||
op: Op, gas: GasInt,
|
op: Op, gas: GasInt,
|
||||||
depth: int): int {.gcsafe.} =
|
depth: int): int {.gcsafe.} =
|
||||||
try:
|
try:
|
||||||
let
|
let
|
||||||
j = newJObject()
|
j = newJObject()
|
||||||
c = ctx.comp
|
|
||||||
ctx.trace["structLogs"].add(j)
|
ctx.trace["structLogs"].add(j)
|
||||||
|
|
||||||
j["op"] = %(($op).toUpperAscii)
|
j["op"] = %(($op).toUpperAscii)
|
||||||
|
@ -139,14 +126,13 @@ method captureOpStart*(ctx: LegacyTracer, pc: int,
|
||||||
except InsufficientStack as ex:
|
except InsufficientStack as ex:
|
||||||
error "LegacyTracer captureOpEnd", msg=ex.msg
|
error "LegacyTracer captureOpEnd", msg=ex.msg
|
||||||
|
|
||||||
method captureOpEnd*(ctx: LegacyTracer, pc: int,
|
method captureOpEnd*(ctx: LegacyTracer, c: Computation, pc: int,
|
||||||
op: Op, gas: GasInt, refund: GasInt,
|
op: Op, gas: GasInt, refund: GasInt,
|
||||||
rData: openArray[byte],
|
rData: openArray[byte],
|
||||||
depth: int, opIndex: int) {.gcsafe.} =
|
depth: int, opIndex: int) {.gcsafe.} =
|
||||||
try:
|
try:
|
||||||
let
|
let
|
||||||
j = ctx.trace["structLogs"].elems[opIndex]
|
j = ctx.trace["structLogs"].elems[opIndex]
|
||||||
c = ctx.comp
|
|
||||||
|
|
||||||
# TODO: figure out how to get storage
|
# TODO: figure out how to get storage
|
||||||
# when contract execution interrupted by exception
|
# when contract execution interrupted by exception
|
||||||
|
@ -170,15 +156,14 @@ method captureOpEnd*(ctx: LegacyTracer, pc: int,
|
||||||
except RlpError as ex:
|
except RlpError as ex:
|
||||||
error "LegacyTracer captureOpEnd", msg=ex.msg
|
error "LegacyTracer captureOpEnd", msg=ex.msg
|
||||||
|
|
||||||
method captureFault*(ctx: LegacyTracer, pc: int,
|
method captureFault*(ctx: LegacyTracer, comp: Computation, pc: int,
|
||||||
op: Op, gas: GasInt, refund: GasInt,
|
op: Op, gas: GasInt, refund: GasInt,
|
||||||
rData: openArray[byte],
|
rData: openArray[byte],
|
||||||
depth: int, error: Option[string]) {.gcsafe.} =
|
depth: int, error: Option[string]) {.gcsafe.} =
|
||||||
try:
|
try:
|
||||||
let c = ctx.comp
|
|
||||||
if ctx.trace["structLogs"].elems.len > 0:
|
if ctx.trace["structLogs"].elems.len > 0:
|
||||||
let j = ctx.trace["structLogs"].elems[^1]
|
let j = ctx.trace["structLogs"].elems[^1]
|
||||||
j["error"] = %(c.error.info)
|
j["error"] = %(comp.error.info)
|
||||||
j["gasCost"] = %(ctx.gas - gas)
|
j["gasCost"] = %(ctx.gas - gas)
|
||||||
|
|
||||||
ctx.trace["failed"] = %true
|
ctx.trace["failed"] = %true
|
||||||
|
|
|
@ -139,6 +139,7 @@ type
|
||||||
flags*: set[TracerFlags]
|
flags*: set[TracerFlags]
|
||||||
|
|
||||||
# Transaction level
|
# Transaction level
|
||||||
|
# This is called once fo each transaction
|
||||||
method captureTxStart*(ctx: TracerRef, gasLimit: GasInt) {.base, gcsafe.} =
|
method captureTxStart*(ctx: TracerRef, gasLimit: GasInt) {.base, gcsafe.} =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
|
@ -146,50 +147,50 @@ method captureTxEnd*(ctx: TracerRef, restGas: GasInt) {.base, gcsafe.} =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
# Top call frame
|
# Top call frame
|
||||||
method captureStart*(ctx: TracerRef, c: Computation,
|
method captureStart*(ctx: TracerRef, comp: Computation,
|
||||||
sender: EthAddress, to: EthAddress,
|
sender: EthAddress, to: EthAddress,
|
||||||
create: bool, input: openArray[byte],
|
create: bool, input: openArray[byte],
|
||||||
gas: GasInt, value: UInt256) {.base, gcsafe.} =
|
gasLimit: GasInt, value: UInt256) {.base, gcsafe.} =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
method captureEnd*(ctx: TracerRef, output: openArray[byte],
|
method captureEnd*(ctx: TracerRef, comp: Computation, output: openArray[byte],
|
||||||
gasUsed: GasInt, error: Option[string]) {.base, gcsafe.} =
|
gasUsed: GasInt, error: Option[string]) {.base, gcsafe.} =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
# Rest of call frames
|
# Rest of call frames
|
||||||
method captureEnter*(ctx: TracerRef, op: Op,
|
method captureEnter*(ctx: TracerRef, comp: Computation, op: Op,
|
||||||
sender: EthAddress, to: EthAddress,
|
sender: EthAddress, to: EthAddress,
|
||||||
input: openArray[byte], gas: GasInt,
|
input: openArray[byte], gasLimit: GasInt,
|
||||||
value: UInt256) {.base, gcsafe.} =
|
value: UInt256) {.base, gcsafe.} =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
method captureExit*(ctx: TracerRef, output: openArray[byte],
|
method captureExit*(ctx: TracerRef, comp: Computation, output: openArray[byte],
|
||||||
gasUsed: GasInt, error: Option[string]) {.base, gcsafe.} =
|
gasUsed: GasInt, error: Option[string]) {.base, gcsafe.} =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
# Opcode level
|
# Opcode level
|
||||||
method captureOpStart*(ctx: TracerRef, pc: int,
|
method captureOpStart*(ctx: TracerRef, comp: Computation, pc: int,
|
||||||
op: Op, gas: GasInt,
|
op: Op, gas: GasInt,
|
||||||
depth: int): int {.base, gcsafe.} =
|
depth: int): int {.base, gcsafe.} =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
method callFamilyGas*(ctx: TracerRef,
|
method callFamilyGas*(ctx: TracerRef, comp: Computation,
|
||||||
op: Op, gas: GasInt,
|
op: Op, gas: GasInt,
|
||||||
depth: int) {.base, gcsafe.} =
|
depth: int) {.base, gcsafe.} =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
method captureOpEnd*(ctx: TracerRef, pc: int,
|
method captureOpEnd*(ctx: TracerRef, comp: Computation, pc: int,
|
||||||
op: Op, gas: GasInt, refund: GasInt,
|
op: Op, gas: GasInt, refund: GasInt,
|
||||||
rData: openArray[byte],
|
rData: openArray[byte],
|
||||||
depth: int, opIndex: int) {.base, gcsafe.} =
|
depth: int, opIndex: int) {.base, gcsafe.} =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
method captureFault*(ctx: TracerRef, pc: int,
|
method captureFault*(ctx: TracerRef, comp: Computation, pc: int,
|
||||||
op: Op, gas: GasInt, refund: GasInt,
|
op: Op, gas: GasInt, refund: GasInt,
|
||||||
rData: openArray[byte],
|
rData: openArray[byte],
|
||||||
depth: int, error: Option[string]) {.base, gcsafe.} =
|
depth: int, error: Option[string]) {.base, gcsafe.} =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
|
|
||||||
method capturePrepare*(ctx: TracerRef, depth: int) {.base, gcsafe.} =
|
method capturePrepare*(ctx: TracerRef, comp: Computation, depth: int) {.base, gcsafe.} =
|
||||||
discard
|
discard
|
||||||
|
|
|
@ -283,7 +283,7 @@ proc finishRunningComputation(host: TransactionHost, call: CallParams): CallResu
|
||||||
else:
|
else:
|
||||||
none(string)
|
none(string)
|
||||||
|
|
||||||
host.vmState.captureEnd(c.output, gasUsed, error)
|
host.vmState.captureEnd(c, c.output, gasUsed, error)
|
||||||
|
|
||||||
result.isError = c.isError
|
result.isError = c.isError
|
||||||
result.gasUsed = call.gasLimit - gasRemaining
|
result.gasUsed = call.gasLimit - gasRemaining
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
{"pc":10,"op":96,"gas":"0x79bf79","gasCost":"0x3","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0"],"depth":1,"refund":0,"opName":"PUSH1"}
|
{"pc":10,"op":96,"gas":"0x79bf79","gasCost":"0x3","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0"],"depth":1,"refund":0,"opName":"PUSH1"}
|
||||||
{"pc":12,"op":90,"gas":"0x79bf76","gasCost":"0x2","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0","0xf3"],"depth":1,"refund":0,"opName":"GAS"}
|
{"pc":12,"op":90,"gas":"0x79bf76","gasCost":"0x2","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0","0xf3"],"depth":1,"refund":0,"opName":"GAS"}
|
||||||
{"pc":13,"op":241,"gas":"0x79bf74","gasCost":"0x77d89f","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0","0xf3","0x79bf74"],"depth":1,"refund":0,"opName":"CALL"}
|
{"pc":13,"op":241,"gas":"0x79bf74","gasCost":"0x77d89f","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0","0xf3","0x79bf74"],"depth":1,"refund":0,"opName":"CALL"}
|
||||||
{"pc":0,"op":11,"gas":"0x77ce77","gasCost":"0x5","memSize":0,"stack":["0x0"],"depth":2,"refund":0,"opName":"SIGNEXTEND","error":"Opcode Dispatch Error: Stack underflow, expect 2, got 0, depth=2"}
|
{"pc":0,"op":11,"gas":"0x77ce77","gasCost":"0x5","memSize":0,"stack":[],"depth":2,"refund":0,"opName":"SIGNEXTEND","error":"Opcode Dispatch Error: Stack underflow, expect 2, got 0, depth=2"}
|
||||||
{"pc":14,"op":80,"gas":"0x1e6d5","gasCost":"0x2","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"POP"}
|
{"pc":14,"op":80,"gas":"0x1e6d5","gasCost":"0x2","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"POP"}
|
||||||
{"pc":15,"op":152,"gas":"0x1e6d3","gasCost":"0x3","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"SWAP9","error":"Opcode Dispatch Error: Stack underflow for SWAP9, depth=1"}
|
{"pc":15,"op":152,"gas":"0x1e6d3","gasCost":"0x3","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"SWAP9","error":"Opcode Dispatch Error: Stack underflow for SWAP9, depth=1"}
|
||||||
{"output":"","gasUsed":"0x79bf88","error":"Opcode Dispatch Error: Stack underflow for SWAP9, depth=1"}
|
{"output":"","gasUsed":"0x79bf88","error":"Opcode Dispatch Error: Stack underflow for SWAP9, depth=1"}
|
||||||
|
|
Loading…
Reference in New Issue