1
0
Fork 0
forked from forks/go-ethereum

eth/tracers: hex-encode returnValue (#31216)

This is a **breaking change** to the opcode tracer. The top-level
`returnValue` field of a trace will be now hex-encoded. If the return
data is empty, this field will contain "0x".

Fixes #31196
This commit is contained in:
Sina M 2025-03-20 10:20:51 +01:00 committed by GitHub
parent 03cc2942c2
commit 43883c6456
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 24 additions and 25 deletions

View file

@ -354,7 +354,7 @@ func TestTraceCall(t *testing.T) {
},
config: nil,
expectErr: nil,
expect: `{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}`,
expect: `{"gas":21000,"failed":false,"returnValue":"0x","structLogs":[]}`,
},
// Standard JSON trace upon the head, plain transfer.
{
@ -366,7 +366,7 @@ func TestTraceCall(t *testing.T) {
},
config: nil,
expectErr: nil,
expect: `{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}`,
expect: `{"gas":21000,"failed":false,"returnValue":"0x","structLogs":[]}`,
},
// Upon the last state, default to the post block's state
{
@ -377,7 +377,7 @@ func TestTraceCall(t *testing.T) {
Value: (*hexutil.Big)(new(big.Int).Add(big.NewInt(params.Ether), big.NewInt(100))),
},
config: nil,
expect: `{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}`,
expect: `{"gas":21000,"failed":false,"returnValue":"0x","structLogs":[]}`,
},
// Before the first transaction, should be failed
{
@ -411,7 +411,7 @@ func TestTraceCall(t *testing.T) {
},
config: &TraceCallConfig{TxIndex: uintPtr(2)},
expectErr: nil,
expect: `{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}`,
expect: `{"gas":21000,"failed":false,"returnValue":"0x","structLogs":[]}`,
},
// Standard JSON trace upon the non-existent block, error expects
{
@ -435,7 +435,7 @@ func TestTraceCall(t *testing.T) {
},
config: nil,
expectErr: nil,
expect: `{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}`,
expect: `{"gas":21000,"failed":false,"returnValue":"0x","structLogs":[]}`,
},
// Tracing on 'pending' should fail:
{
@ -458,7 +458,7 @@ func TestTraceCall(t *testing.T) {
BlockOverrides: &override.BlockOverrides{Number: (*hexutil.Big)(big.NewInt(0x1337))},
},
expectErr: nil,
expect: ` {"gas":53018,"failed":false,"returnValue":"","structLogs":[
expect: ` {"gas":53018,"failed":false,"returnValue":"0x","structLogs":[
{"pc":0,"op":"NUMBER","gas":24946984,"gasCost":2,"depth":1,"stack":[]},
{"pc":1,"op":"STOP","gas":24946982,"gasCost":0,"depth":1,"stack":["0x1337"]}]}`,
},
@ -535,7 +535,7 @@ func TestTraceTransaction(t *testing.T) {
if !reflect.DeepEqual(have, &logger.ExecutionResult{
Gas: params.TxGas,
Failed: false,
ReturnValue: "",
ReturnValue: []byte{},
StructLogs: []json.RawMessage{},
}) {
t.Error("Transaction tracing result is different")
@ -596,7 +596,7 @@ func TestTraceBlock(t *testing.T) {
// Trace head block
{
blockNumber: rpc.BlockNumber(genBlocks),
want: fmt.Sprintf(`[{"txHash":"%v","result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}}]`, txHash),
want: fmt.Sprintf(`[{"txHash":"%v","result":{"gas":21000,"failed":false,"returnValue":"0x","structLogs":[]}}]`, txHash),
},
// Trace non-existent block
{
@ -606,12 +606,12 @@ func TestTraceBlock(t *testing.T) {
// Trace latest block
{
blockNumber: rpc.LatestBlockNumber,
want: fmt.Sprintf(`[{"txHash":"%v","result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}}]`, txHash),
want: fmt.Sprintf(`[{"txHash":"%v","result":{"gas":21000,"failed":false,"returnValue":"0x","structLogs":[]}}]`, txHash),
},
// Trace pending block
{
blockNumber: rpc.PendingBlockNumber,
want: fmt.Sprintf(`[{"txHash":"%v","result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}}]`, txHash),
want: fmt.Sprintf(`[{"txHash":"%v","result":{"gas":21000,"failed":false,"returnValue":"0x","structLogs":[]}}]`, txHash),
},
}
for i, tc := range testSuite {
@ -704,7 +704,7 @@ func TestTracingWithOverrides(t *testing.T) {
randomAccounts[0].addr: override.OverrideAccount{Balance: newRPCBalance(new(big.Int).Mul(big.NewInt(1), big.NewInt(params.Ether)))},
},
},
want: `{"gas":21000,"failed":false,"returnValue":""}`,
want: `{"gas":21000,"failed":false,"returnValue":"0x"}`,
},
// Invalid call without state overriding
{
@ -749,7 +749,7 @@ func TestTracingWithOverrides(t *testing.T) {
},
},
},
want: `{"gas":23347,"failed":false,"returnValue":"000000000000000000000000000000000000000000000000000000000000007b"}`,
want: `{"gas":23347,"failed":false,"returnValue":"0x000000000000000000000000000000000000000000000000000000000000007b"}`,
},
{ // Override blocknumber
blockNumber: rpc.LatestBlockNumber,
@ -761,7 +761,7 @@ func TestTracingWithOverrides(t *testing.T) {
config: &TraceCallConfig{
BlockOverrides: &override.BlockOverrides{Number: (*hexutil.Big)(big.NewInt(0x1337))},
},
want: `{"gas":59537,"failed":false,"returnValue":"0000000000000000000000000000000000000000000000000000000000001337"}`,
want: `{"gas":59537,"failed":false,"returnValue":"0x0000000000000000000000000000000000000000000000000000000000001337"}`,
},
{ // Override blocknumber, and query a blockhash
blockNumber: rpc.LatestBlockNumber,
@ -781,7 +781,7 @@ func TestTracingWithOverrides(t *testing.T) {
config: &TraceCallConfig{
BlockOverrides: &override.BlockOverrides{Number: (*hexutil.Big)(big.NewInt(0x1337))},
},
want: `{"gas":72666,"failed":false,"returnValue":"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}`,
want: `{"gas":72666,"failed":false,"returnValue":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}`,
},
/*
pragma solidity =0.8.12;
@ -815,7 +815,7 @@ func TestTracingWithOverrides(t *testing.T) {
},
},
},
want: `{"gas":44100,"failed":false,"returnValue":"0000000000000000000000000000000000000000000000000000000000000001"}`,
want: `{"gas":44100,"failed":false,"returnValue":"0x0000000000000000000000000000000000000000000000000000000000000001"}`,
},
{ // Same again, this time with storage override
blockNumber: rpc.LatestBlockNumber,
@ -833,7 +833,7 @@ func TestTracingWithOverrides(t *testing.T) {
},
},
//want: `{"gas":46900,"failed":false,"returnValue":"0000000000000000000000000000000000000000000000000000000000000539"}`,
want: `{"gas":44100,"failed":false,"returnValue":"0000000000000000000000000000000000000000000000000000000000000001"}`,
want: `{"gas":44100,"failed":false,"returnValue":"0x0000000000000000000000000000000000000000000000000000000000000001"}`,
},
{ // No state override
blockNumber: rpc.LatestBlockNumber,
@ -863,7 +863,7 @@ func TestTracingWithOverrides(t *testing.T) {
},
},
},
want: `{"gas":25288,"failed":false,"returnValue":"0000000000000000000000000000000000000000000000000000000000000077"}`,
want: `{"gas":25288,"failed":false,"returnValue":"0x0000000000000000000000000000000000000000000000000000000000000077"}`,
},
{ // Full state override
// The original storage is
@ -901,7 +901,7 @@ func TestTracingWithOverrides(t *testing.T) {
},
},
},
want: `{"gas":25288,"failed":false,"returnValue":"0000000000000000000000000000000000000000000000000000000000000011"}`,
want: `{"gas":25288,"failed":false,"returnValue":"0x0000000000000000000000000000000000000000000000000000000000000011"}`,
},
{ // Partial state override
// The original storage is
@ -939,7 +939,7 @@ func TestTracingWithOverrides(t *testing.T) {
},
},
},
want: `{"gas":25288,"failed":false,"returnValue":"0000000000000000000000000000000000000000000000000000000000000055"}`,
want: `{"gas":25288,"failed":false,"returnValue":"0x0000000000000000000000000000000000000000000000000000000000000055"}`,
},
{ // Call to precompile ECREC (0x01), but code was modified to add 1 to input
blockNumber: rpc.LatestBlockNumber,
@ -1084,7 +1084,7 @@ func TestTraceChain(t *testing.T) {
backend.relHook = func() { rel.Add(1) }
api := NewAPI(backend)
single := `{"txHash":"0x0000000000000000000000000000000000000000000000000000000000000000","result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}}`
single := `{"txHash":"0x0000000000000000000000000000000000000000000000000000000000000000","result":{"gas":21000,"failed":false,"returnValue":"0x","structLogs":[]}}`
var cases = []struct {
start uint64
end uint64
@ -1198,7 +1198,7 @@ func TestTraceBlockWithBasefee(t *testing.T) {
// Trace head block
{
blockNumber: rpc.BlockNumber(genBlocks),
want: fmt.Sprintf(`[{"txHash":"%#x","result":{"gas":21002,"failed":false,"returnValue":"","structLogs":[{"pc":0,"op":"BASEFEE","gas":84000,"gasCost":2,"depth":1,"stack":[]},{"pc":1,"op":"STOP","gas":83998,"gasCost":0,"depth":1,"stack":["%#x"]}]}}]`, txHash, baseFee),
want: fmt.Sprintf(`[{"txHash":"%#x","result":{"gas":21002,"failed":false,"returnValue":"0x","structLogs":[{"pc":0,"op":"BASEFEE","gas":84000,"gasCost":2,"depth":1,"stack":[]},{"pc":1,"op":"STOP","gas":83998,"gasCost":0,"depth":1,"stack":["%#x"]}]}}]`, txHash, baseFee),
},
}
for i, tc := range testSuite {

View file

@ -350,14 +350,13 @@ func (l *StructLogger) GetResult() (json.RawMessage, error) {
failed := l.err != nil
returnData := common.CopyBytes(l.output)
// Return data when successful and revert reason when reverted, otherwise empty.
returnVal := fmt.Sprintf("%x", returnData)
if failed && !errors.Is(l.err, vm.ErrExecutionReverted) {
returnVal = ""
returnData = []byte{}
}
return json.Marshal(&ExecutionResult{
Gas: l.usedGas,
Failed: failed,
ReturnValue: returnVal,
ReturnValue: returnData,
StructLogs: l.logs,
})
}
@ -527,6 +526,6 @@ func (t *mdLogger) OnFault(pc uint64, op byte, gas, cost uint64, scope tracing.O
type ExecutionResult struct {
Gas uint64 `json:"gas"`
Failed bool `json:"failed"`
ReturnValue string `json:"returnValue"`
ReturnValue hexutil.Bytes `json:"returnValue"`
StructLogs []json.RawMessage `json:"structLogs"`
}