Skip to content

Commit b532903

Browse files
holimanGrapeBaBa
authored andcommitted
eth/tracers/logger: make structlog/json-log stack hex again (ethereum#28628)
* common/hexutil: define hex wrappers for uint256.Int * eth/tracers/logger: make structlog/json-log stack hex again * common/hexutil: goimports
1 parent 86a9f94 commit b532903

File tree

4 files changed

+118
-4
lines changed

4 files changed

+118
-4
lines changed

common/hexutil/json.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,16 @@ import (
2323
"math/big"
2424
"reflect"
2525
"strconv"
26+
27+
"github.com/holiman/uint256"
2628
)
2729

2830
var (
2931
bytesT = reflect.TypeOf(Bytes(nil))
3032
bigT = reflect.TypeOf((*Big)(nil))
3133
uintT = reflect.TypeOf(Uint(0))
3234
uint64T = reflect.TypeOf(Uint64(0))
35+
u256T = reflect.TypeOf((*uint256.Int)(nil))
3336
)
3437

3538
// Bytes marshals/unmarshals as a JSON string with 0x prefix.
@@ -225,6 +228,48 @@ func (b *Big) UnmarshalGraphQL(input interface{}) error {
225228
return err
226229
}
227230

231+
// U256 marshals/unmarshals as a JSON string with 0x prefix.
232+
// The zero value marshals as "0x0".
233+
type U256 uint256.Int
234+
235+
// MarshalText implements encoding.TextMarshaler
236+
func (b U256) MarshalText() ([]byte, error) {
237+
u256 := (*uint256.Int)(&b)
238+
return []byte(u256.Hex()), nil
239+
}
240+
241+
// UnmarshalJSON implements json.Unmarshaler.
242+
func (b *U256) UnmarshalJSON(input []byte) error {
243+
// The uint256.Int.UnmarshalJSON method accepts "dec", "0xhex"; we must be
244+
// more strict, hence we check string and invoke SetFromHex directly.
245+
if !isString(input) {
246+
return errNonString(u256T)
247+
}
248+
// The hex decoder needs to accept empty string ("") as '0', which uint256.Int
249+
// would reject.
250+
if len(input) == 2 {
251+
(*uint256.Int)(b).Clear()
252+
return nil
253+
}
254+
err := (*uint256.Int)(b).SetFromHex(string(input[1 : len(input)-1]))
255+
if err != nil {
256+
return &json.UnmarshalTypeError{Value: err.Error(), Type: u256T}
257+
}
258+
return nil
259+
}
260+
261+
// UnmarshalText implements encoding.TextUnmarshaler
262+
func (b *U256) UnmarshalText(input []byte) error {
263+
// The uint256.Int.UnmarshalText method accepts "dec", "0xhex"; we must be
264+
// more strict, hence we check string and invoke SetFromHex directly.
265+
return (*uint256.Int)(b).SetFromHex(string(input))
266+
}
267+
268+
// String returns the hex encoding of b.
269+
func (b *U256) String() string {
270+
return (*uint256.Int)(b).Hex()
271+
}
272+
228273
// Uint64 marshals/unmarshals as a JSON string with 0x prefix.
229274
// The zero value marshals as "0x0".
230275
type Uint64 uint64

common/hexutil/json_test.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import (
2323
"errors"
2424
"math/big"
2525
"testing"
26+
27+
"github.com/holiman/uint256"
2628
)
2729

2830
func checkError(t *testing.T, input string, got, want error) bool {
@@ -176,6 +178,64 @@ func TestUnmarshalBig(t *testing.T) {
176178
}
177179
}
178180

181+
var unmarshalU256Tests = []unmarshalTest{
182+
// invalid encoding
183+
{input: "", wantErr: errJSONEOF},
184+
{input: "null", wantErr: errNonString(u256T)},
185+
{input: "10", wantErr: errNonString(u256T)},
186+
{input: `"0"`, wantErr: wrapTypeError(ErrMissingPrefix, u256T)},
187+
{input: `"0x"`, wantErr: wrapTypeError(ErrEmptyNumber, u256T)},
188+
{input: `"0x01"`, wantErr: wrapTypeError(ErrLeadingZero, u256T)},
189+
{input: `"0xx"`, wantErr: wrapTypeError(ErrSyntax, u256T)},
190+
{input: `"0x1zz01"`, wantErr: wrapTypeError(ErrSyntax, u256T)},
191+
{
192+
input: `"0x10000000000000000000000000000000000000000000000000000000000000000"`,
193+
wantErr: wrapTypeError(ErrBig256Range, u256T),
194+
},
195+
196+
// valid encoding
197+
{input: `""`, want: big.NewInt(0)},
198+
{input: `"0x0"`, want: big.NewInt(0)},
199+
{input: `"0x2"`, want: big.NewInt(0x2)},
200+
{input: `"0x2F2"`, want: big.NewInt(0x2f2)},
201+
{input: `"0X2F2"`, want: big.NewInt(0x2f2)},
202+
{input: `"0x1122aaff"`, want: big.NewInt(0x1122aaff)},
203+
{input: `"0xbBb"`, want: big.NewInt(0xbbb)},
204+
{input: `"0xfffffffff"`, want: big.NewInt(0xfffffffff)},
205+
{
206+
input: `"0x112233445566778899aabbccddeeff"`,
207+
want: referenceBig("112233445566778899aabbccddeeff"),
208+
},
209+
{
210+
input: `"0xffffffffffffffffffffffffffffffffffff"`,
211+
want: referenceBig("ffffffffffffffffffffffffffffffffffff"),
212+
},
213+
{
214+
input: `"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"`,
215+
want: referenceBig("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
216+
},
217+
}
218+
219+
func TestUnmarshalU256(t *testing.T) {
220+
for _, test := range unmarshalU256Tests {
221+
var v U256
222+
err := json.Unmarshal([]byte(test.input), &v)
223+
if !checkError(t, test.input, err, test.wantErr) {
224+
continue
225+
}
226+
if test.want == nil {
227+
continue
228+
}
229+
want := new(uint256.Int)
230+
want.SetFromBig(test.want.(*big.Int))
231+
have := (*uint256.Int)(&v)
232+
if want.Cmp(have) != 0 {
233+
t.Errorf("input %s: value mismatch: have %x, want %x", test.input, have, want)
234+
continue
235+
}
236+
}
237+
}
238+
179239
func BenchmarkUnmarshalBig(b *testing.B) {
180240
input := []byte(`"0x123456789abcdef123456789abcdef"`)
181241
for i := 0; i < b.N; i++ {

eth/tracers/logger/gen_structlog.go

Lines changed: 12 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

eth/tracers/logger/logger.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ type structLogMarshaling struct {
8383
GasCost math.HexOrDecimal64
8484
Memory hexutil.Bytes
8585
ReturnData hexutil.Bytes
86+
Stack []hexutil.U256
8687
OpName string `json:"opName"` // adds call to OpName() in MarshalJSON
8788
ErrorString string `json:"error,omitempty"` // adds call to ErrorString() in MarshalJSON
8889
}

0 commit comments

Comments
 (0)