|
7 | 7 | from pyethereum.chainmanager import chain_manager
|
8 | 8 | from pyethereum.peermanager import peer_manager
|
9 | 9 | import pyethereum.dispatch as dispatch
|
10 |
| -from pyethereum.blocks import block_structure |
| 10 | +from pyethereum.blocks import block_structure, Block |
11 | 11 | import pyethereum.signals as signals
|
12 | 12 | from pyethereum.transactions import Transaction
|
| 13 | +import pyethereum.processblock as processblock |
| 14 | +import pyethereum.utils as utils |
| 15 | +import pyethereum.rlp as rlp |
13 | 16 |
|
14 | 17 | logger = logging.getLogger(__name__)
|
15 | 18 | base_url = '/api/v02a'
|
@@ -176,6 +179,61 @@ def get_pending():
|
176 | 179 |
|
177 | 180 |
|
178 | 181 |
|
| 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 | + |
179 | 237 | # ######## Accounts ############
|
180 | 238 | @app.get(base_url + '/accounts/')
|
181 | 239 | def accounts():
|
|
0 commit comments