Unverified Commit 7c4cad06 authored by Dmitry Zenovich's avatar Dmitry Zenovich Committed by GitHub

rpc: add BlockNumber.MarshalText (#23324)

Currently rpc.BlockNumber is marshalled to JSON as a numeric value, which is
wrong because BlockNumber.UnmarshalJSON() wants it to either be hex-encoded
or string "earliest"/"latest"/"pending". As a result, the call chain

    rpc.BlockNumberOrHashWithNumber(123) -> json.Marshal() -> json.Unmarshal()

fails with error "cannot unmarshal object into Go value of type string".
parent 154b525c
...@@ -98,6 +98,22 @@ func (bn *BlockNumber) UnmarshalJSON(data []byte) error { ...@@ -98,6 +98,22 @@ func (bn *BlockNumber) UnmarshalJSON(data []byte) error {
return nil return nil
} }
// MarshalText implements encoding.TextMarshaler. It marshals:
// - "latest", "earliest" or "pending" as strings
// - other numbers as hex
func (bn BlockNumber) MarshalText() ([]byte, error) {
switch bn {
case EarliestBlockNumber:
return []byte("earliest"), nil
case LatestBlockNumber:
return []byte("latest"), nil
case PendingBlockNumber:
return []byte("pending"), nil
default:
return hexutil.Uint64(bn).MarshalText()
}
}
func (bn BlockNumber) Int64() int64 { func (bn BlockNumber) Int64() int64 {
return (int64)(bn) return (int64)(bn)
} }
......
...@@ -18,6 +18,7 @@ package rpc ...@@ -18,6 +18,7 @@ package rpc
import ( import (
"encoding/json" "encoding/json"
"reflect"
"testing" "testing"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
...@@ -122,3 +123,33 @@ func TestBlockNumberOrHash_UnmarshalJSON(t *testing.T) { ...@@ -122,3 +123,33 @@ func TestBlockNumberOrHash_UnmarshalJSON(t *testing.T) {
} }
} }
} }
func TestBlockNumberOrHash_WithNumber_MarshalAndUnmarshal(t *testing.T) {
tests := []struct {
name string
number int64
}{
{"max", math.MaxInt64},
{"pending", int64(PendingBlockNumber)},
{"latest", int64(LatestBlockNumber)},
{"earliest", int64(EarliestBlockNumber)},
}
for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
bnh := BlockNumberOrHashWithNumber(BlockNumber(test.number))
marshalled, err := json.Marshal(bnh)
if err != nil {
t.Fatal("cannot marshal:", err)
}
var unmarshalled BlockNumberOrHash
err = json.Unmarshal(marshalled, &unmarshalled)
if err != nil {
t.Fatal("cannot unmarshal:", err)
}
if !reflect.DeepEqual(bnh, unmarshalled) {
t.Fatalf("wrong result: expected %v, got %v", bnh, unmarshalled)
}
})
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment