diff --git a/eth/tracers/api.go b/eth/tracers/api.go index 286d1e7dde..2e99b5c379 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -205,6 +205,7 @@ type StdTraceConfig struct { // txTraceResult is the result of a single transaction trace. type txTraceResult struct { + TxHash common.Hash `json:"txHash"` // transaction hash Result interface{} `json:"result,omitempty"` // Trace results produced by the tracer Error string `json:"error,omitempty"` // Trace failure produced by the tracer } @@ -322,13 +323,13 @@ func (api *API) traceChain(ctx context.Context, start, end *types.Block, config vmRunner := api.backend.NewEVMRunner(task.block.Header(), task.statedb) res, err := api.traceTx(localctx, msg, txctx, blockCtx, vmRunner, task.statedb, sysCtx, config) if err != nil { - task.results[i] = &txTraceResult{Error: err.Error()} + task.results[i] = &txTraceResult{TxHash: tx.Hash(), Error: err.Error()} log.Warn("Tracing failed", "hash", tx.Hash(), "block", task.block.NumberU64(), "err", err) break } // Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect task.statedb.Finalise(api.backend.ChainConfig().IsEIP158(task.block.Number())) - task.results[i] = &txTraceResult{Result: res} + task.results[i] = &txTraceResult{TxHash: tx.Hash(), Result: res} } // Stream the result back to the user or abort on teardown select { @@ -667,10 +668,10 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac vmRunner := api.backend.NewEVMRunner(block.Header(), task.statedb) res, err := api.traceTx(ctx, msg, txctx, blockCtx, vmRunner, task.statedb, sysCtx, config) if err != nil { - results[task.index] = &txTraceResult{Error: err.Error()} + results[task.index] = &txTraceResult{TxHash: txs[task.index].Hash(), Error: err.Error()} continue } - results[task.index] = &txTraceResult{Result: res} + results[task.index] = &txTraceResult{TxHash: txs[task.index].Hash(), Result: res} } }() } diff --git a/eth/tracers/api_test.go b/eth/tracers/api_test.go index da354bccce..0524114c7c 100644 --- a/eth/tracers/api_test.go +++ b/eth/tracers/api_test.go @@ -366,12 +366,14 @@ func TestTraceBlock(t *testing.T) { }} genBlocks := 10 signer := types.HomesteadSigner{} + var txHash common.Hash api := NewAPI(newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) { // Transfer from account[0] to account[1] // value: 1000 wei // fee: 0 wei tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[1].addr, big.NewInt(1000), params.TxGas, b.MinimumGasPrice(nil), nil), signer, accounts[0].key) b.AddTx(tx) + txHash = tx.Hash() })) var testSuite = []struct { @@ -388,7 +390,7 @@ func TestTraceBlock(t *testing.T) { // Trace head block { blockNumber: rpc.BlockNumber(genBlocks), - want: `[{"result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}}]`, + want: fmt.Sprintf(`[{"txHash":"%v","result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}}]`, txHash), }, // Trace non-existent block { @@ -398,12 +400,12 @@ func TestTraceBlock(t *testing.T) { // Trace latest block { blockNumber: rpc.LatestBlockNumber, - want: `[{"result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}}]`, + want: fmt.Sprintf(`[{"txHash":"%v","result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}}]`, txHash), }, // Trace pending block { blockNumber: rpc.PendingBlockNumber, - want: `[{"result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}}]`, + want: fmt.Sprintf(`[{"txHash":"%v","result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}}]`, txHash), }, } for i, tc := range testSuite {