“trace” Module Overview¶
The trace module is for getting a deeper insight into transaction processing. It includes two sets of calls; the transaction trace filtering API and the ad-hoc tracing API. You can find the documentation for the supported methods here.
It’s good to mention that
trace_* methods are nothing more than aliases to some existing
debug_* methods. The reason for creating those aliases, was to reach compatibility with OpenEthereum’s (aka Parity) trace module, which has been requested by the community in order they can fully use core-geth. For achieving this, the
trace_* methods set the default tracer to
callTracerParity if none is set.
In order to use the Transaction-Trace Filtering API, core-geth must be fully synced using
--syncmode=full --gcmode=archive. Otherwise, you can set the number of blocks to
reexec back for rebuilding the state, though taking longer for a trace call to finish.
The ad-hoc tracing API allows you to perform a number of different diagnostics on calls or transactions, either historical ones from the chain or hypothetical ones not yet mined.
- trace_call (alias to debug_traceCall)
These APIs allow you to get a full externality trace on any transaction executed throughout the blockchain.
- trace_block (alias to debug_traceBlock)
- trace_transaction (alias to debug_traceTransaction)
- trace_filter (doesn’t support address filtering yet)
callTracerParityTransaction trace returning a response equivalent to OpenEthereum’s (aka Parity) response schema. For documentation on this response value see here.
vmTraceVirtual Machine execution trace. Provides a full trace of the VM’s state throughout the execution of the transaction, including for any subcalls. (Not implemented yet)
stateDiffTracerState difference. Provides information detailing all altered portions of the Ethereum state made due to the execution of the transaction. For documentation on this response value see here.
Example trace_* API method config (last method argument)
1 2 3 4 5 6
Tracers’ output documentation¶
The output result is an array including the outer transaction (first object in the array), as well the internal transactions (next objects in the array) that were being triggered.
Each object that represents an internal transaction consists of:
actionobject with all the call args,
resutlsobject with the outcome as well the gas used,
subtracesfield, representing the number of internal transactions that were being triggered by the current transaction,
traceAddressfield, representing the exact nesting location in the call trace [index in root, index in first CALL, index in second CALL, …].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
Provides information detailing all altered portions of the Ethereum state made due to the execution of the transaction.
Each address object provides the state differences for
storage. Actually, under the
storage object, we can find the state differences for each contract’s storage key.
Special symbols explanation:
+, when we have a new entry in the state DB,
-, when we have a removal from the state DB,
*, when existing data have changed in the state DB, providing the
from(old) and the
=, when the data remained the same.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
“stateDiff” tracer differences with OpenEthereum¶
- SSTORE in some edge cases persists data in state but are not being returned on stateDiff storage results on OpenEthereum output.
Happens only on 2 transactions on Mordor testnet, as of block 2,519,999. (TX hashes: 0xab73afe7b92ad9b537df3f168de0d06f275ed34edf9e19b36362ac6fa304c0bf, 0x15a7c727a9bbfdd43d09805288668cc4a0ec647772d717957e882a71ace80b1a)
- When error ErrInsufficientFundsForTransfer happens, OpenEthereum leaves the tracer run producing negative balances, though using safe math for overflows it returns 0 balance, on the other hand the
toaccount receives the full amount. Core-geth removes only the gas cost from the sender and adds it to the coinbase balance.
- Same as in 2, but on top of that, the sender account doesn’t have to pay for the gas cost even. In this case, core-geth returns an empty JSON, as in reality this transaction will remain in the tx_pool and never be executed, neither change the state.
- On OpenEthereum the block gasLimit is set to be U256::max(), which leads into problems on contracts using it for pseudo-randomness. On core-geth, we believe that the user utilising the trace_ wants to see what will happen in reality, though we leave the block untouched to its true values*.
- When an internal call fails with out of gas, and its state is not being persisted, we don’t add it in stateDiff output, as it happens on OpenEthereum.