Skip to content
This repository was archived by the owner on May 23, 2023. It is now read-only.

Commit fcc9bbe

Browse files
committed
add: trace tx via the api
1 parent 1ddeabf commit fcc9bbe

File tree

2 files changed

+66
-2
lines changed

2 files changed

+66
-2
lines changed

pyethereum/apiserver.py

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@
77
from pyethereum.chainmanager import chain_manager
88
from pyethereum.peermanager import peer_manager
99
import pyethereum.dispatch as dispatch
10-
from pyethereum.blocks import block_structure
10+
from pyethereum.blocks import block_structure, Block
1111
import pyethereum.signals as signals
1212
from pyethereum.transactions import Transaction
13+
import pyethereum.processblock as processblock
14+
import pyethereum.utils as utils
15+
import pyethereum.rlp as rlp
1316

1417
logger = logging.getLogger(__name__)
1518
base_url = '/api/v02a'
@@ -176,6 +179,61 @@ def get_pending():
176179

177180

178181

182+
# ########### Trace ############
183+
184+
class TraceLogHandler(logging.Handler):
185+
def __init__(self):
186+
logging.Handler.__init__(self)
187+
self.buffer = []
188+
189+
def emit(self, record):
190+
self.buffer.append(record)
191+
192+
193+
@app.get(base_url + '/trace/<txhash>')
194+
def trace(txhash):
195+
"""
196+
/trace/<hexhash> return trace for transaction
197+
"""
198+
logger.debug('GET trace/ %s', txhash)
199+
try: # index
200+
tx, blk = chain_manager.index.get_transaction(txhash.decode('hex'))
201+
except (KeyError, TypeError):
202+
return bottle.abort(404, 'Unknown Transaction %s' % txhash)
203+
204+
# get the state we had before this transaction
205+
test_blk = Block.init_from_parent(blk.get_parent(),
206+
blk.coinbase,
207+
extra_data=blk.extra_data,
208+
timestamp=blk.timestamp,
209+
uncles=blk.uncles)
210+
pre_state = test_blk.state_root
211+
for i in range(blk.transaction_count):
212+
tx_lst_serialized, sr, _ = blk.get_transaction(i)
213+
if utils.sha3(rlp.encode(tx_lst_serialized)) == tx.hash:
214+
break
215+
else:
216+
pre_state = sr
217+
test_blk.state.root_hash = pre_state
218+
219+
# collect debug output
220+
tl = TraceLogHandler()
221+
tl.setLevel(logging.DEBUG)
222+
processblock.logger.addHandler(tl)
223+
224+
# apply tx (thread? we don't want logs from other invocations)
225+
processblock.apply_transaction(test_blk, tx)
226+
227+
# stop collecting debug output
228+
processblock.logger.removeHandler(tl)
229+
230+
# format
231+
formatter = logging.Formatter('%(name)s:%(message)s')
232+
res = '\n'.join(formatter.format(l) for l in tl.buffer)
233+
return dict(trace=res)
234+
235+
236+
179237
# ######## Accounts ############
180238
@app.get(base_url + '/accounts/')
181239
def accounts():

pyethereum/ethclient.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,11 @@ def gettx(self, id):
9595
def getpending(self):
9696
return self.json_get_request(path='/pending/')
9797

98+
def trace(self, id):
99+
res = self.json_get_request(path='/trace/%s' % id)
100+
if 'trace' in res:
101+
return res['trace']
102+
return res
98103

99104
doc = \
100105
"""ethclient
@@ -115,7 +120,7 @@ def getpending(self):
115120
pyethclient getblock [options] <blockid_hex_or_num>
116121
pyethclient gettx [options] <txid_hex>
117122
pyethclient getpending [options]
118-
123+
pyethclient trace [options] <txid_hex>
119124
120125
Options:
121126
-h --help Show this screen
@@ -155,6 +160,7 @@ def main():
155160
getblock=(api.getblock, arguments['<blockid_hex_or_num>']),
156161
gettx=(api.gettx, arguments['<txid_hex>']),
157162
trace=(api.trace, arguments['<txid_hex>']),
163+
getpending=(api.getpending,)
158164
)
159165
for k in cmd_map:
160166
if arguments.get(k):

0 commit comments

Comments
 (0)