diff --git a/common/hexutil/hexutil.go b/common/hexutil/hexutil.go index 81e6804650..7b62045328 100644 --- a/common/hexutil/hexutil.go +++ b/common/hexutil/hexutil.go @@ -60,7 +60,7 @@ func Decode(input string) ([]byte, error) { if len(input) == 0 { return nil, ErrEmptyString } - if !has0xPrefix(input) { + if !Has0xPrefix(input) { return nil, ErrMissingPrefix } b, err := hex.DecodeString(input[2:]) @@ -185,7 +185,7 @@ func EncodeBig(bigint *big.Int) string { } } -func has0xPrefix(input string) bool { +func Has0xPrefix(input string) bool { return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X') } @@ -193,7 +193,7 @@ func checkNumber(input string) (raw string, err error) { if len(input) == 0 { return "", ErrEmptyString } - if !has0xPrefix(input) { + if !Has0xPrefix(input) { return "", ErrMissingPrefix } input = input[2:] diff --git a/common/hexutil/hexutil_test.go b/common/hexutil/hexutil_test.go index f2b800d82c..24dce185e7 100644 --- a/common/hexutil/hexutil_test.go +++ b/common/hexutil/hexutil_test.go @@ -22,6 +22,11 @@ import ( "testing" ) +type hexValidityTest struct { + input string + want bool +} + type marshalTest struct { input interface{} want string @@ -134,6 +139,12 @@ var ( {input: `0xbbb`, want: uint64(0xbbb)}, {input: `0xffffffffffffffff`, want: uint64(0xffffffffffffffff)}, } + + hexStringValidityTest = []hexValidityTest{ + {"0x", true}, + {"asdcc", false}, + {"0x00000102", true}, + } ) func TestEncode(t *testing.T) { @@ -202,6 +213,15 @@ func TestDecodeUint64(t *testing.T) { } } +func TestHas0xPrefix(t *testing.T) { + for _, test := range hexStringValidityTest { + actual := Has0xPrefix(test.input) + if actual != test.want { + t.Errorf("input %s: value mismatch: got %t, want %t", test.input, actual, test.want) + } + } +} + func BenchmarkEncodeBig(b *testing.B) { for _, bench := range encodeBigTests { b.Run(bench.want, func(b *testing.B) { diff --git a/rpc/types.go b/rpc/types.go index f7e8e4b867..62384c8264 100644 --- a/rpc/types.go +++ b/rpc/types.go @@ -22,6 +22,7 @@ import ( "errors" "fmt" "math" + "strconv" "strings" "github.com/XinFinOrg/XDPoSChain/common" @@ -99,10 +100,21 @@ func (bn *BlockNumber) UnmarshalJSON(data []byte) error { return nil } - blckNum, err := hexutil.DecodeUint64(input) + var blckNum uint64 + var err error + + //Check if input is valid hex string before converting. + if hexutil.Has0xPrefix(input) { + blckNum, err = hexutil.DecodeUint64(input) + } else { + //Else try converting input directly into uint64 value + blckNum, err = strconv.ParseUint(input, 10, 64) + } + if err != nil { return err } + if blckNum > math.MaxInt64 { return errors.New("block number larger than int64") } diff --git a/rpc/types_test.go b/rpc/types_test.go index e48db859d4..5ace764f22 100644 --- a/rpc/types_test.go +++ b/rpc/types_test.go @@ -42,7 +42,7 @@ func TestBlockNumberJSONUnmarshal(t *testing.T) { 6: {`"0x12"`, false, BlockNumber(18)}, 7: {`"0x7fffffffffffffff"`, false, BlockNumber(math.MaxInt64)}, 8: {`"0x8000000000000000"`, true, BlockNumber(0)}, - 9: {"0", true, BlockNumber(0)}, + 9: {"0", false, BlockNumber(0)}, 10: {`"ff"`, true, BlockNumber(0)}, 11: {`"pending"`, false, PendingBlockNumber}, 12: {`"latest"`, false, LatestBlockNumber}, @@ -52,6 +52,11 @@ func TestBlockNumberJSONUnmarshal(t *testing.T) { 16: {`someString`, true, BlockNumber(0)}, 17: {`""`, true, BlockNumber(0)}, 18: {``, true, BlockNumber(0)}, + 19: {`88439993`, false, BlockNumber(88439993)}, + 20: {`-1`, true, BlockNumber(0)}, + 21: {`9223372036854775807`, false, BlockNumber(9223372036854775807)}, + 22: {`-9223372036854775808`, true, BlockNumber(0)}, + 23: {`18446744073709551615`, true, BlockNumber(0)}, } for i, test := range tests {