Merge pull request #1037 from Tarunshrma/fix-blocknumber-hex-unmarshal

rpc: support decimal integer as block number
This commit is contained in:
Wanwiset Peerapatanapokin 2025-06-03 07:12:58 +04:00 committed by GitHub
commit 29cc718d4a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 42 additions and 5 deletions

View file

@ -60,7 +60,7 @@ func Decode(input string) ([]byte, error) {
if len(input) == 0 { if len(input) == 0 {
return nil, ErrEmptyString return nil, ErrEmptyString
} }
if !has0xPrefix(input) { if !Has0xPrefix(input) {
return nil, ErrMissingPrefix return nil, ErrMissingPrefix
} }
b, err := hex.DecodeString(input[2:]) 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') 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 { if len(input) == 0 {
return "", ErrEmptyString return "", ErrEmptyString
} }
if !has0xPrefix(input) { if !Has0xPrefix(input) {
return "", ErrMissingPrefix return "", ErrMissingPrefix
} }
input = input[2:] input = input[2:]

View file

@ -22,6 +22,11 @@ import (
"testing" "testing"
) )
type hexValidityTest struct {
input string
want bool
}
type marshalTest struct { type marshalTest struct {
input interface{} input interface{}
want string want string
@ -134,6 +139,12 @@ var (
{input: `0xbbb`, want: uint64(0xbbb)}, {input: `0xbbb`, want: uint64(0xbbb)},
{input: `0xffffffffffffffff`, want: uint64(0xffffffffffffffff)}, {input: `0xffffffffffffffff`, want: uint64(0xffffffffffffffff)},
} }
hexStringValidityTest = []hexValidityTest{
{"0x", true},
{"asdcc", false},
{"0x00000102", true},
}
) )
func TestEncode(t *testing.T) { 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) { func BenchmarkEncodeBig(b *testing.B) {
for _, bench := range encodeBigTests { for _, bench := range encodeBigTests {
b.Run(bench.want, func(b *testing.B) { b.Run(bench.want, func(b *testing.B) {

View file

@ -22,6 +22,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"math" "math"
"strconv"
"strings" "strings"
"github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/common"
@ -99,10 +100,21 @@ func (bn *BlockNumber) UnmarshalJSON(data []byte) error {
return nil 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 { if err != nil {
return err return err
} }
if blckNum > math.MaxInt64 { if blckNum > math.MaxInt64 {
return errors.New("block number larger than int64") return errors.New("block number larger than int64")
} }

View file

@ -42,7 +42,7 @@ func TestBlockNumberJSONUnmarshal(t *testing.T) {
6: {`"0x12"`, false, BlockNumber(18)}, 6: {`"0x12"`, false, BlockNumber(18)},
7: {`"0x7fffffffffffffff"`, false, BlockNumber(math.MaxInt64)}, 7: {`"0x7fffffffffffffff"`, false, BlockNumber(math.MaxInt64)},
8: {`"0x8000000000000000"`, true, BlockNumber(0)}, 8: {`"0x8000000000000000"`, true, BlockNumber(0)},
9: {"0", true, BlockNumber(0)}, 9: {"0", false, BlockNumber(0)},
10: {`"ff"`, true, BlockNumber(0)}, 10: {`"ff"`, true, BlockNumber(0)},
11: {`"pending"`, false, PendingBlockNumber}, 11: {`"pending"`, false, PendingBlockNumber},
12: {`"latest"`, false, LatestBlockNumber}, 12: {`"latest"`, false, LatestBlockNumber},
@ -52,6 +52,11 @@ func TestBlockNumberJSONUnmarshal(t *testing.T) {
16: {`someString`, true, BlockNumber(0)}, 16: {`someString`, true, BlockNumber(0)},
17: {`""`, true, BlockNumber(0)}, 17: {`""`, true, BlockNumber(0)},
18: {``, 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 { for i, test := range tests {