Skip to content

Commit 49f3b1c

Browse files
wangerethkclowes
andauthored
feat(geth): Add debug_traceTransaction RPC method to Geth module (#3334)
* feat(geth): Add debug_traceTransaction RPC method to Geth module * fix(lint): add type for new formatters * Add GoEthereumDebugModuleTest and GoEthereumAsyncDebugModuleTest to integration tests * fix: use txn_hash_with_log fixtures * Update API permissions in integration tests and benchmarking code * add doc for debug module * Add prestate tracer, and a few tests * Allow default tracer instead of forcing callTracer * Raise TransactionNotFound if appropriate * Add pretrace formatters --------- Co-authored-by: kclowes <[email protected]>
1 parent 3c412f8 commit 49f3b1c

20 files changed

+615
-6
lines changed

docs/web3.geth.rst

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,3 +367,175 @@ The following methods are available on the ``web3.geth.txpool`` namespace.
367367
}
368368
}
369369
}
370+
371+
.. py:module:: web3.geth.debug
372+
373+
GethDebug API
374+
~~~~~~~~~~~~~~
375+
376+
The ``web3.geth.debug`` object exposes methods to interact with the RPC APIs under the
377+
``debug_`` namespace. These methods are only exposed under the ``geth`` namespace.
378+
Full documentation around options can be found in the
379+
`Geth docs <https://geth.ethereum.org/docs/developers/evm-tracing/built-in-tracers>`_.
380+
381+
.. py:method:: Debug.trace_transaction(transaction_hash)
382+
383+
* Delegates to ``debug_traceTransaction`` RPC Method
384+
385+
Returns the trace of the transaction with the given ``transaction_hash`` and ``trace_config``.
386+
387+
.. code-block:: python
388+
389+
>>> web3.geth.debug.trace_transaction('0x96014f00980a25dc7275a5eb5ed25ce0dd79c9233628c421ae373601236949b3')
390+
AttributeDict({
391+
'gas': 21000,
392+
'failed': False,
393+
'returnValue': '',
394+
'structLogs': []
395+
})
396+
397+
>>> web3.geth.debug.trace_transaction('0x96014f00980a25dc7275a5eb5ed25ce0dd79c9233628c421ae373601236949b3', {
398+
"tracer": "prestateTracer",
399+
})
400+
AttributeDict({
401+
'0x0000000000000000000000000000000000000000': AttributeDict({'balance': 0}),
402+
'0x7fE3e4C21bDE162214B715AabcE05391301e9F5B': AttributeDict({'balance': 115792089237316195423570985008687907853269984665640564039457584007913129639927}),
403+
'0x91fe3039271d43d3f8479f60Cc5293Bc8A461b75': AttributeDict({'balance': 0})
404+
})
405+
406+
>>> web3.geth.debug.trace_transaction('0x96014f00980a25dc7275a5eb5ed25ce0dd79c9233628c421ae373601236949b3', {
407+
"tracer": "prestateTracer",
408+
"traceConfig": {"diffMode": True}
409+
})
410+
AttributeDict({
411+
'post': AttributeDict({
412+
'0x0000000000000000000000000000000000000000': AttributeDict({'balance': 63000}),
413+
'0xcF888Cc4FAe8a3D774e574Ef8C6a261958287d04': AttributeDict({
414+
'balance': 115792089237316195423570985008687907853269984665640564039457583959368602105927,
415+
'nonce': 3
416+
}),
417+
'0xD2593D3445a9F0f4c776715f5206FBf4CA6A0475': AttributeDict({'balance': 100000})}),
418+
'pre': AttributeDict({
419+
'0x0000000000000000000000000000000000000000': AttributeDict({'balance': 42000}),
420+
'0xcF888Cc4FAe8a3D774e574Ef8C6a261958287d04': AttributeDict({
421+
'balance': 115792089237316195423570985008687907853269984665640564039457583973451623990927,
422+
'nonce': 2
423+
}),
424+
'0xD2593D3445a9F0f4c776715f5206FBf4CA6A0475': AttributeDict({'balance': 0})
425+
})
426+
})
427+
428+
>>> web3.geth.debug.trace_transaction('0x96014f00980a25dc7275a5eb5ed25ce0dd79c9233628c421ae373601236949b3', {
429+
"tracer": "callTracer",
430+
"tracerConfig": {"withLog": False},
431+
})
432+
AttributeDict({'calls': [AttributeDict({'from': '0xa0457775a08b175Cbb444eD923556Dc67Ec5Dc11',
433+
'gas': 154003,
434+
'gasUsed': 275,
435+
'input': HexBytes('0xad5c4648'),
436+
'output': HexBytes('0x000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2'),
437+
'to': '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D',
438+
'type': 'STATICCALL'}),
439+
AttributeDict({'from': '0xa0457775a08b175Cbb444eD923556Dc67Ec5Dc11',
440+
'gas': 150633,
441+
'gasUsed': 24678,
442+
'input': HexBytes('0x095ea7b30000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d000000000000000000000000000000000000007e37be2022c0914b2680000000'),
443+
'output': HexBytes('0x0000000000000000000000000000000000000000000000000000000000000001'),
444+
'to': '0xec4cF8dCB526080792bC98E1Ef41fB4775777b6B',
445+
'type': 'CALL',
446+
'value': 0}),
447+
AttributeDict({'calls': [AttributeDict({'from': '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D',
448+
'gas': 121167,
449+
'gasUsed': 27504,
450+
'input': HexBytes('0x23b872dd000000000000000000000000a0457775a08b175cbb444ed923556dc67ec5dc1100000000000000000000000036f0548a77bfb1d5935483d25cc40633b46e2f4d000000000000000000000000000000000000007e37be2022c0914b2680000000'),
451+
'output': HexBytes('0x0000000000000000000000000000000000000000000000000000000000000001'),
452+
'to': '0xec4cF8dCB526080792bC98E1Ef41fB4775777b6B',
453+
'type': 'CALL',
454+
'value': 0}),
455+
AttributeDict({'from': '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D',
456+
'gas': 89911,
457+
'gasUsed': 2504,
458+
'input': HexBytes('0x0902f1ac'),
459+
'output': HexBytes('0x00000000000000000000000000000000000000000000000053f54ccde429ceb70000000000000000000000000000000000000000001635eb93ecdb339a7dc022000000000000000000000000000000000000000000000000000000006641f6cf'),
460+
'to': '0x36f0548a77BFb1d5935483D25cc40633b46e2f4d',
461+
'type': 'STATICCALL'}),
462+
AttributeDict({'from': '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D',
463+
'gas': 86926,
464+
'gasUsed': 621,
465+
'input': HexBytes('0x70a0823100000000000000000000000036f0548a77bfb1d5935483d25cc40633b46e2f4d'),
466+
'output': HexBytes('0x000000000000000000000000000000000000007e37d4560e547e265a1a7dc022'),
467+
'to': '0xec4cF8dCB526080792bC98E1Ef41fB4775777b6B',
468+
'type': 'STATICCALL'}),
469+
AttributeDict({'calls': [AttributeDict({'from': '0x36f0548a77BFb1d5935483D25cc40633b46e2f4d',
470+
'gas': 70279,
471+
'gasUsed': 29962,
472+
'input': HexBytes('0xa9059cbb0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d00000000000000000000000000000000000000000000000053f53dfc545d56a6'),
473+
'output': HexBytes('0x0000000000000000000000000000000000000000000000000000000000000001'),
474+
'to': '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
475+
'type': 'CALL',
476+
'value': 0}),
477+
AttributeDict({'from': '0x36f0548a77BFb1d5935483D25cc40633b46e2f4d',
478+
'gas': 40164,
479+
'gasUsed': 534,
480+
'input': HexBytes('0x70a0823100000000000000000000000036f0548a77bfb1d5935483d25cc40633b46e2f4d'),
481+
'output': HexBytes('0x00000000000000000000000000000000000000000000000000000ed18fcc7811'),
482+
'to': '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
483+
'type': 'STATICCALL'}),
484+
AttributeDict({'from': '0x36f0548a77BFb1d5935483D25cc40633b46e2f4d',
485+
'gas': 39233,
486+
'gasUsed': 621,
487+
'input': HexBytes('0x70a0823100000000000000000000000036f0548a77bfb1d5935483d25cc40633b46e2f4d'),
488+
'output': HexBytes('0x000000000000000000000000000000000000007e37d4560e547e265a1a7dc022'),
489+
'to': '0xec4cF8dCB526080792bC98E1Ef41fB4775777b6B',
490+
'type': 'STATICCALL'})],
491+
'from': '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D',
492+
'gas': 84769,
493+
'gasUsed': 64940,
494+
'input': HexBytes('0x022c0d9f00000000000000000000000000000000000000000000000053f53dfc545d56a600000000000000000000000000000000000000000000000000000000000000000000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000'),
495+
'to': '0x36f0548a77BFb1d5935483D25cc40633b46e2f4d',
496+
'type': 'CALL',
497+
'value': 0}),
498+
AttributeDict({'from': '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D',
499+
'gas': 20382,
500+
'gasUsed': 534,
501+
'input': HexBytes('0x70a082310000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d'),
502+
'output': HexBytes('0x00000000000000000000000000000000000000000000000053f53dfc545d56a6'),
503+
'to': '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
504+
'type': 'STATICCALL'}),
505+
AttributeDict({'calls': [AttributeDict({'from': '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
506+
'gas': 2300,
507+
'gasUsed': 83,
508+
'input': HexBytes('0x'),
509+
'to': '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D',
510+
'type': 'CALL',
511+
'value': 6049809828398585510})],
512+
'from': '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D',
513+
'gas': 19432,
514+
'gasUsed': 9223,
515+
'input': HexBytes('0x2e1a7d4d00000000000000000000000000000000000000000000000053f53dfc545d56a6'),
516+
'to': '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
517+
'type': 'CALL',
518+
'value': 0}),
519+
AttributeDict({'from': '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D',
520+
'gas': 3353,
521+
'gasUsed': 0,
522+
'input': HexBytes('0x'),
523+
'to': '0xE11418f9961248da36b1008b1090235f680AE8f5',
524+
'type': 'CALL',
525+
'value': 6049809828398585510})],
526+
'from': '0xa0457775a08b175Cbb444eD923556Dc67Ec5Dc11',
527+
'gas': 125270,
528+
'gasUsed': 122013,
529+
'input': HexBytes('0x791ac947000000000000000000000000000000000000007e37be2022c0914b2680000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000e11418f9961248da36b1008b1090235f680ae8f5000000000000000000000000000000000000000000000000000000006641fe7f0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000ec4cf8dcb526080792bc98e1ef41fb4775777b6b000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2'),
530+
'to': '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D',
531+
'type': 'CALL',
532+
'value': 0})],
533+
'from': '0xE11418f9961248da36b1008b1090235f680AE8f5',
534+
'gas': 185574,
535+
'gasUsed': 144300,
536+
'input': HexBytes('0x56feb11b000000000000000000000000ec4cf8dcb526080792bc98e1ef41fb4775777b6b000000000000000000000000000000000000007e37be2022c0914b2680000000'),
537+
'to': '0xa0457775a08b175Cbb444eD923556Dc67Ec5Dc11',
538+
'type': 'CALL',
539+
'value': 0})
540+
541+
>>> w3.geth.debug.trace_transaction(tx_hash, {'tracer': '4byteTracer'})

newsfragments/3334.feature.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add support for Geth Debug traceTransaction.

tests/integration/go_ethereum/common.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
AsyncNetModuleTest,
1313
EthModuleTest,
1414
GoEthereumAdminModuleTest,
15+
GoEthereumAsyncDebugModuleTest,
1516
GoEthereumAsyncTxPoolModuleTest,
17+
GoEthereumDebugModuleTest,
1618
GoEthereumTxPoolModuleTest,
1719
NetModuleTest,
1820
Web3ModuleTest,

tests/integration/go_ethereum/test_goethereum_http.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@
1818

1919
from .common import (
2020
GoEthereumAdminModuleTest,
21+
GoEthereumAsyncDebugModuleTest,
2122
GoEthereumAsyncEthModuleTest,
2223
GoEthereumAsyncNetModuleTest,
2324
GoEthereumAsyncTxPoolModuleTest,
2425
GoEthereumAsyncWeb3ModuleTest,
26+
GoEthereumDebugModuleTest,
2527
GoEthereumEthModuleTest,
2628
GoEthereumNetModuleTest,
2729
GoEthereumTxPoolModuleTest,
@@ -51,7 +53,7 @@ def _geth_command_arguments(rpc_port, base_geth_command_arguments, geth_version)
5153
"--http.port",
5254
rpc_port,
5355
"--http.api",
54-
"admin,eth,net,web3,txpool",
56+
"admin,debug,eth,net,web3,txpool",
5557
"--ipcdisable",
5658
)
5759
else:
@@ -95,6 +97,10 @@ def test_admin_start_stop_ws(self, w3: "Web3") -> None:
9597
super().test_admin_start_stop_ws(w3)
9698

9799

100+
class TestGoEthereumDebugModuleTest(GoEthereumDebugModuleTest):
101+
pass
102+
103+
98104
class TestGoEthereumEthModuleTest(GoEthereumEthModuleTest):
99105
pass
100106

@@ -144,6 +150,10 @@ async def test_admin_start_stop_ws(self, async_w3: "AsyncWeb3") -> None:
144150
await super().test_admin_start_stop_ws(async_w3)
145151

146152

153+
class TestGoEthereumAsyncDebugModuleTest(GoEthereumAsyncDebugModuleTest):
154+
pass
155+
156+
147157
class TestGoEthereumAsyncNetModuleTest(GoEthereumAsyncNetModuleTest):
148158
pass
149159

tests/integration/go_ethereum/test_goethereum_ipc.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@
1515

1616
from .common import (
1717
GoEthereumAdminModuleTest,
18+
GoEthereumAsyncDebugModuleTest,
1819
GoEthereumAsyncEthModuleTest,
1920
GoEthereumAsyncNetModuleTest,
2021
GoEthereumAsyncWeb3ModuleTest,
22+
GoEthereumDebugModuleTest,
2123
GoEthereumEthModuleTest,
2224
GoEthereumNetModuleTest,
2325
GoEthereumWeb3ModuleTest,
@@ -61,6 +63,10 @@ class TestGoEthereumWeb3ModuleTest(GoEthereumWeb3ModuleTest):
6163
pass
6264

6365

66+
class TestGoEthereumDebugModuleTest(GoEthereumDebugModuleTest):
67+
pass
68+
69+
6470
class TestGoEthereumEthModuleTest(GoEthereumEthModuleTest):
6571
pass
6672

@@ -103,6 +109,10 @@ class TestGoEthereumAsyncWeb3ModuleTest(GoEthereumAsyncWeb3ModuleTest):
103109
pass
104110

105111

112+
class TestGoEthereumAsyncDebugModuleTest(GoEthereumAsyncDebugModuleTest):
113+
pass
114+
115+
106116
class TestGoEthereumAsyncEthModuleTest(GoEthereumAsyncEthModuleTest):
107117
pass
108118

tests/integration/go_ethereum/test_goethereum_legacy_ws.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
from .common import (
1717
GoEthereumAdminModuleTest,
18+
GoEthereumDebugModuleTest,
1819
GoEthereumEthModuleTest,
1920
GoEthereumNetModuleTest,
2021
GoEthereumWeb3ModuleTest,
@@ -41,7 +42,7 @@ def _geth_command_arguments(ws_port, base_geth_command_arguments, geth_version):
4142
"--ws.port",
4243
ws_port,
4344
"--ws.api",
44-
"admin,eth,net,web3",
45+
"admin,debug,eth,net,web3",
4546
"--ws.origins",
4647
"*",
4748
"--ipcdisable",
@@ -97,6 +98,10 @@ def test_admin_start_stop_ws(self, w3: "Web3") -> None:
9798
super().test_admin_start_stop_ws(w3)
9899

99100

101+
class TestGoEthereumDebugModuleTest(GoEthereumDebugModuleTest):
102+
pass
103+
104+
100105
class TestGoEthereumEthModuleTest(GoEthereumEthModuleTest):
101106
pass
102107

tests/integration/go_ethereum/test_goethereum_ws/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def _geth_command_arguments(ws_port, base_geth_command_arguments, geth_version):
2828
"--ws.port",
2929
ws_port,
3030
"--ws.api",
31-
"admin,eth,net,web3",
31+
"admin,debug,eth,net,web3",
3232
"--ws.origins",
3333
"*",
3434
"--ipcdisable",

tests/integration/go_ethereum/test_goethereum_ws/test_async_await_w3.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
)
1515

1616
from ..common import (
17+
GoEthereumAsyncDebugModuleTest,
1718
GoEthereumAsyncEthModuleTest,
1819
GoEthereumAsyncNetModuleTest,
1920
GoEthereumAsyncWeb3ModuleTest,
@@ -71,3 +72,7 @@ class TestGoEthereumAsyncEthModuleTest(GoEthereumAsyncEthModuleTest):
7172

7273
class TestGoEthereumAsyncNetModuleTest(GoEthereumAsyncNetModuleTest):
7374
pass
75+
76+
77+
class TestGoEthereumAsyncDebugModuleTest(GoEthereumAsyncDebugModuleTest):
78+
pass

tests/integration/go_ethereum/test_goethereum_ws/test_async_ctx_manager_w3.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
)
1515

1616
from ..common import (
17+
GoEthereumAsyncDebugModuleTest,
1718
GoEthereumAsyncEthModuleTest,
1819
GoEthereumAsyncNetModuleTest,
1920
GoEthereumAsyncWeb3ModuleTest,
@@ -72,3 +73,7 @@ class TestGoEthereumAsyncEthModuleTest(GoEthereumAsyncEthModuleTest):
7273

7374
class TestGoEthereumAsyncNetModuleTest(GoEthereumAsyncNetModuleTest):
7475
pass
76+
77+
78+
class TestGoEthereumAsyncDebugModuleTest(GoEthereumAsyncDebugModuleTest):
79+
pass

tests/integration/go_ethereum/test_goethereum_ws/test_async_iterator_w3.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
)
1515

1616
from ..common import (
17+
GoEthereumAsyncDebugModuleTest,
1718
GoEthereumAsyncEthModuleTest,
1819
GoEthereumAsyncNetModuleTest,
1920
GoEthereumAsyncWeb3ModuleTest,
@@ -72,3 +73,7 @@ class TestGoEthereumAsyncEthModuleTest(GoEthereumAsyncEthModuleTest):
7273

7374
class TestGoEthereumAsyncNetModuleTest(GoEthereumAsyncNetModuleTest):
7475
pass
76+
77+
78+
class TestGoEthereumAsyncDebugModuleTest(GoEthereumAsyncDebugModuleTest):
79+
pass

0 commit comments

Comments
 (0)