diff --git a/coreth/eth/tracers/api.go b/coreth/eth/tracers/api.go index 0e0f7b2f..0e46e5cc 100644 --- a/coreth/eth/tracers/api.go +++ b/coreth/eth/tracers/api.go @@ -221,6 +221,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 } @@ -350,13 +351,13 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed } res, err := api.traceTx(ctx, msg, txctx, blockCtx, task.statedb, 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} } // Tracing state is used up, queue it for de-referencing reler.add(task.release) @@ -690,10 +691,10 @@ func (api *baseAPI) traceBlock(ctx context.Context, block *types.Block, config * } res, err := api.traceTx(ctx, msg, txctx, blockCtx, task.statedb, 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/coreth/eth/tracers/api_test.go b/coreth/eth/tracers/api_test.go index be367340..7557be53 100644 --- a/coreth/eth/tracers/api_test.go +++ b/coreth/eth/tracers/api_test.go @@ -390,12 +390,15 @@ 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, new(big.Int).Add(b.BaseFee(), big.NewInt(int64(500*params.GWei))), nil), signer, accounts[0].key) b.AddTx(tx) + txHash = tx.Hash() })) var testSuite = []struct { @@ -412,7 +415,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 { @@ -422,12 +425,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 { @@ -688,7 +691,7 @@ func TestTraceChain(t *testing.T) { backend.relHook = func() { atomic.AddUint32(&rel, 1) } api := NewAPI(backend) - single := `{"result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}}` + single := `{"txHash":"0x0000000000000000000000000000000000000000000000000000000000000000","result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}}` var cases = []struct { start uint64 end uint64 @@ -706,16 +709,17 @@ func TestTraceChain(t *testing.T) { next := c.start + 1 for result := range resCh { - if next != uint64(result.Block) { - t.Error("Unexpected tracing block") + if have, want := uint64(result.Block), next; have != want { + t.Fatalf("unexpected tracing block, have %d want %d", have, want) } - if len(result.Traces) != int(next) { - t.Error("Unexpected tracing result") + if have, want := len(result.Traces), int(next); have != want { + t.Fatalf("unexpected result length, have %d want %d", have, want) } for _, trace := range result.Traces { + trace.TxHash = common.Hash{} blob, _ := json.Marshal(trace) - if string(blob) != single { - t.Error("Unexpected tracing result") + if have, want := string(blob), single; have != want { + t.Fatalf("unexpected tracing result, have\n%v\nwant:\n%v", have, want) } } next += 1