Skip to content

Commit

Permalink
Change balance and nonce in zero's tracer output from decimal to hex (#…
Browse files Browse the repository at this point in the history
…1350)

* Change balance and nonce in zero's tracer output from decimal to hex

* test: add unit test for TxnTrace_MarshalJSON

---------

Co-authored-by: Stefan Negovanović <[email protected]>
  • Loading branch information
cffls and Stefan-Ethernal authored Oct 25, 2024
1 parent 2723db7 commit 6ff23b3
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 0 deletions.
48 changes: 48 additions & 0 deletions core/types/trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
package types

import (
"encoding/json"

"github.com/holiman/uint256"
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon-lib/common/hexutility"
Expand All @@ -18,6 +20,17 @@ type ContractCodeUsage struct {
Write HexBytes `json:"write,omitempty"`
}

type Uint256 struct {
uint256.Int
}

// MarshalJSON implements the json.Marshaler interface
// It returns the hex representation of the uint256.Int.
// We need to do this because the uint256.Int will be marshalled in decimal format by default.
func (u *Uint256) MarshalJSON() ([]byte, error) {
return json.Marshal(u.Hex())
}

type TxnTrace struct {
Balance *uint256.Int `json:"balance,omitempty"`
Nonce *uint256.Int `json:"nonce,omitempty"`
Expand All @@ -28,6 +41,41 @@ type TxnTrace struct {
StorageReadMap map[libcommon.Hash]struct{} `json:"-"`
}

type TxnTraceHex struct {
Balance *Uint256 `json:"balance,omitempty"`
Nonce *Uint256 `json:"nonce,omitempty"`
StorageRead []libcommon.Hash `json:"storage_read,omitempty"`
StorageWritten map[libcommon.Hash]*Uint256 `json:"storage_written,omitempty"`
CodeUsage *ContractCodeUsage `json:"code_usage,omitempty"`
SelfDestructed *bool `json:"self_destructed,omitempty"`
StorageReadMap map[libcommon.Hash]struct{} `json:"-"`
}

func (t *TxnTrace) MarshalJSON() ([]byte, error) {
tHex := TxnTraceHex{
StorageRead: t.StorageRead,
StorageWritten: make(map[libcommon.Hash]*Uint256),
CodeUsage: t.CodeUsage,
SelfDestructed: t.SelfDestructed,
StorageReadMap: t.StorageReadMap,
}

if t.Balance != nil {
tHex.Balance = &Uint256{*t.Balance}
}
if t.Nonce != nil {
tHex.Nonce = &Uint256{*t.Nonce}
}

for k, v := range t.StorageWritten {
if v != nil {
tHex.StorageWritten[k] = &Uint256{*v}
}
}

return json.Marshal(tHex)
}

type TxnMeta struct {
ByteCode HexBytes `json:"byte_code,omitempty"`
NewTxnTrieNode HexBytes `json:"new_txn_trie_node_byte,omitempty"`
Expand Down
49 changes: 49 additions & 0 deletions core/types/trace_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package types

import (
"encoding/json"
"testing"

"github.com/holiman/uint256"
"github.com/ledgerwatch/erigon-lib/common"
"github.com/stretchr/testify/require"
)

func TestTxnTrace_MarshalJSON(t *testing.T) {
balance := uint256.NewInt(32)
nonce := uint256.NewInt(64)
storageRead := []common.Hash{common.HexToHash("0x1")}
selfDestructed := false
codeRead := common.HexToHash("0x6")

trace := TxnTrace{
Balance: balance,
Nonce: nonce,
StorageRead: storageRead,
StorageWritten: map[common.Hash]*uint256.Int{
common.HexToHash("0x7"): uint256.NewInt(7),
common.HexToHash("0x8"): uint256.NewInt(8),
common.HexToHash("0x9"): uint256.NewInt(9),
},
CodeUsage: &ContractCodeUsage{
Read: &codeRead,
},
SelfDestructed: &selfDestructed,
}

traceJSON, err := trace.MarshalJSON()
require.NoError(t, err)

// Parse the JSON output into a generic map and assert balance and nonce are hex encoded
var genericTraceResult map[string]interface{}
err = json.Unmarshal(traceJSON, &genericTraceResult)
require.NoError(t, err)

require.Equal(t, balance.Hex(), genericTraceResult["balance"])
require.Equal(t, nonce.Hex(), genericTraceResult["nonce"])

var resultTrace TxnTrace
err = json.Unmarshal(traceJSON, &resultTrace)
require.NoError(t, err)
require.Equal(t, trace, resultTrace)
}

0 comments on commit 6ff23b3

Please sign in to comment.