feat(proxyd): support eip-1898 in tag rewritting
This commit is contained in:
parent
92058943d8
commit
22b7237389
@ -66,25 +66,26 @@ func RewriteRequest(rctx RewriteContext, req *RPCReq, res *RPCRes) (RewriteResul
|
|||||||
"eth_newFilter":
|
"eth_newFilter":
|
||||||
return rewriteRange(rctx, req, res, 0)
|
return rewriteRange(rctx, req, res, 0)
|
||||||
case "debug_getRawReceipts", "consensus_getReceipts":
|
case "debug_getRawReceipts", "consensus_getReceipts":
|
||||||
return rewriteParam(rctx, req, res, 0, true)
|
return rewriteParam(rctx, req, res, 0, true, false)
|
||||||
case "eth_getBalance",
|
case "eth_getBalance",
|
||||||
"eth_getCode",
|
"eth_getCode",
|
||||||
"eth_getTransactionCount",
|
"eth_getTransactionCount",
|
||||||
"eth_call":
|
"eth_call":
|
||||||
return rewriteParam(rctx, req, res, 1, false)
|
return rewriteParam(rctx, req, res, 1, false, true)
|
||||||
case "eth_getStorageAt":
|
case "eth_getStorageAt",
|
||||||
return rewriteParam(rctx, req, res, 2, false)
|
"eth_getProof":
|
||||||
|
return rewriteParam(rctx, req, res, 2, false, true)
|
||||||
case "eth_getBlockTransactionCountByNumber",
|
case "eth_getBlockTransactionCountByNumber",
|
||||||
"eth_getUncleCountByBlockNumber",
|
"eth_getUncleCountByBlockNumber",
|
||||||
"eth_getBlockByNumber",
|
"eth_getBlockByNumber",
|
||||||
"eth_getTransactionByBlockNumberAndIndex",
|
"eth_getTransactionByBlockNumberAndIndex",
|
||||||
"eth_getUncleByBlockNumberAndIndex":
|
"eth_getUncleByBlockNumberAndIndex":
|
||||||
return rewriteParam(rctx, req, res, 0, false)
|
return rewriteParam(rctx, req, res, 0, false, false)
|
||||||
}
|
}
|
||||||
return RewriteNone, nil
|
return RewriteNone, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func rewriteParam(rctx RewriteContext, req *RPCReq, res *RPCRes, pos int, required bool) (RewriteResult, error) {
|
func rewriteParam(rctx RewriteContext, req *RPCReq, res *RPCRes, pos int, required bool, blockNrOrHash bool) (RewriteResult, error) {
|
||||||
var p []interface{}
|
var p []interface{}
|
||||||
err := json.Unmarshal(req.Params, &p)
|
err := json.Unmarshal(req.Params, &p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -99,13 +100,38 @@ func rewriteParam(rctx RewriteContext, req *RPCReq, res *RPCRes, pos int, requir
|
|||||||
return RewriteNone, nil
|
return RewriteNone, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
s, ok := p[pos].(string)
|
// support for https://eips.ethereum.org/EIPS/eip-1898
|
||||||
if !ok {
|
var val interface{}
|
||||||
return RewriteOverrideError, errors.New("expected string")
|
var rw bool
|
||||||
}
|
if blockNrOrHash {
|
||||||
val, rw, err := rewriteTag(rctx, s)
|
bnh, err := remarshalBlockNumberOrHash(p[pos])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return RewriteOverrideError, err
|
// fallback to string
|
||||||
|
s, ok := p[pos].(string)
|
||||||
|
if ok {
|
||||||
|
val, rw, err = rewriteTag(rctx, s)
|
||||||
|
if err != nil {
|
||||||
|
return RewriteOverrideError, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return RewriteOverrideError, errors.New("expected BlockNumberOrHash or string")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val, rw, err = rewriteTagBlockNumberOrHash(rctx, bnh)
|
||||||
|
if err != nil {
|
||||||
|
return RewriteOverrideError, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
s, ok := p[pos].(string)
|
||||||
|
if !ok {
|
||||||
|
return RewriteOverrideError, errors.New("expected string")
|
||||||
|
}
|
||||||
|
|
||||||
|
val, rw, err = rewriteTag(rctx, s)
|
||||||
|
if err != nil {
|
||||||
|
return RewriteOverrideError, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if rw {
|
if rw {
|
||||||
@ -210,14 +236,23 @@ func rewriteTagMap(rctx RewriteContext, m map[string]interface{}, key string) (b
|
|||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func rewriteTag(rctx RewriteContext, current string) (string, bool, error) {
|
func remarshalBlockNumberOrHash(current interface{}) (*rpc.BlockNumberOrHash, error) {
|
||||||
jv, err := json.Marshal(current)
|
jv, err := json.Marshal(current)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", false, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var bnh rpc.BlockNumberOrHash
|
var bnh rpc.BlockNumberOrHash
|
||||||
err = bnh.UnmarshalJSON(jv)
|
err = bnh.UnmarshalJSON(jv)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &bnh, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func rewriteTag(rctx RewriteContext, current string) (string, bool, error) {
|
||||||
|
bnh, err := remarshalBlockNumberOrHash(current)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", false, err
|
return "", false, err
|
||||||
}
|
}
|
||||||
@ -245,3 +280,31 @@ func rewriteTag(rctx RewriteContext, current string) (string, bool, error) {
|
|||||||
|
|
||||||
return current, false, nil
|
return current, false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func rewriteTagBlockNumberOrHash(rctx RewriteContext, current *rpc.BlockNumberOrHash) (*rpc.BlockNumberOrHash, bool, error) {
|
||||||
|
// this is a hash, not a block number
|
||||||
|
if current.BlockNumber == nil {
|
||||||
|
return current, false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
switch *current.BlockNumber {
|
||||||
|
case rpc.PendingBlockNumber,
|
||||||
|
rpc.EarliestBlockNumber:
|
||||||
|
return current, false, nil
|
||||||
|
case rpc.FinalizedBlockNumber:
|
||||||
|
bn := rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(rctx.finalized))
|
||||||
|
return &bn, true, nil
|
||||||
|
case rpc.SafeBlockNumber:
|
||||||
|
bn := rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(rctx.safe))
|
||||||
|
return &bn, true, nil
|
||||||
|
case rpc.LatestBlockNumber:
|
||||||
|
bn := rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(rctx.latest))
|
||||||
|
return &bn, true, nil
|
||||||
|
default:
|
||||||
|
if current.BlockNumber.Int64() > int64(rctx.latest) {
|
||||||
|
return nil, false, ErrRewriteBlockOutOfRange
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return current, false, nil
|
||||||
|
}
|
||||||
|
@ -5,7 +5,9 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -282,12 +284,14 @@ func TestRewriteRequest(t *testing.T) {
|
|||||||
},
|
},
|
||||||
expected: RewriteOverrideRequest,
|
expected: RewriteOverrideRequest,
|
||||||
check: func(t *testing.T, args args) {
|
check: func(t *testing.T, args args) {
|
||||||
var p []string
|
var p []interface{}
|
||||||
err := json.Unmarshal(args.req.Params, &p)
|
err := json.Unmarshal(args.req.Params, &p)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
require.Equal(t, 2, len(p))
|
require.Equal(t, 2, len(p))
|
||||||
require.Equal(t, "0x123", p[0])
|
require.Equal(t, "0x123", p[0])
|
||||||
require.Equal(t, hexutil.Uint64(100).String(), p[1])
|
bnh, err := remarshalBlockNumberOrHash(p[1])
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, rpc.BlockNumberOrHashWithNumber(100), *bnh)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -314,12 +318,14 @@ func TestRewriteRequest(t *testing.T) {
|
|||||||
},
|
},
|
||||||
expected: RewriteOverrideRequest,
|
expected: RewriteOverrideRequest,
|
||||||
check: func(t *testing.T, args args) {
|
check: func(t *testing.T, args args) {
|
||||||
var p []string
|
var p []interface{}
|
||||||
err := json.Unmarshal(args.req.Params, &p)
|
err := json.Unmarshal(args.req.Params, &p)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
require.Equal(t, 2, len(p))
|
require.Equal(t, 2, len(p))
|
||||||
require.Equal(t, "0x123", p[0])
|
require.Equal(t, "0x123", p[0])
|
||||||
require.Equal(t, hexutil.Uint64(100).String(), p[1])
|
bnh, err := remarshalBlockNumberOrHash(p[1])
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, rpc.BlockNumberOrHashWithNumber(100), *bnh)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -359,13 +365,15 @@ func TestRewriteRequest(t *testing.T) {
|
|||||||
},
|
},
|
||||||
expected: RewriteOverrideRequest,
|
expected: RewriteOverrideRequest,
|
||||||
check: func(t *testing.T, args args) {
|
check: func(t *testing.T, args args) {
|
||||||
var p []string
|
var p []interface{}
|
||||||
err := json.Unmarshal(args.req.Params, &p)
|
err := json.Unmarshal(args.req.Params, &p)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
require.Equal(t, 3, len(p))
|
require.Equal(t, 3, len(p))
|
||||||
require.Equal(t, "0x123", p[0])
|
require.Equal(t, "0x123", p[0])
|
||||||
require.Equal(t, "5", p[1])
|
require.Equal(t, "5", p[1])
|
||||||
require.Equal(t, hexutil.Uint64(100).String(), p[2])
|
bnh, err := remarshalBlockNumberOrHash(p[2])
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, rpc.BlockNumberOrHashWithNumber(100), *bnh)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -377,13 +385,15 @@ func TestRewriteRequest(t *testing.T) {
|
|||||||
},
|
},
|
||||||
expected: RewriteOverrideRequest,
|
expected: RewriteOverrideRequest,
|
||||||
check: func(t *testing.T, args args) {
|
check: func(t *testing.T, args args) {
|
||||||
var p []string
|
var p []interface{}
|
||||||
err := json.Unmarshal(args.req.Params, &p)
|
err := json.Unmarshal(args.req.Params, &p)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
require.Equal(t, 3, len(p))
|
require.Equal(t, 3, len(p))
|
||||||
require.Equal(t, "0x123", p[0])
|
require.Equal(t, "0x123", p[0])
|
||||||
require.Equal(t, "5", p[1])
|
require.Equal(t, "5", p[1])
|
||||||
require.Equal(t, hexutil.Uint64(100).String(), p[2])
|
bnh, err := remarshalBlockNumberOrHash(p[2])
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, rpc.BlockNumberOrHashWithNumber(100), *bnh)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -517,6 +527,88 @@ func TestRewriteRequest(t *testing.T) {
|
|||||||
},
|
},
|
||||||
expected: RewriteNone,
|
expected: RewriteNone,
|
||||||
},
|
},
|
||||||
|
// eip1898
|
||||||
|
{
|
||||||
|
name: "eth_getStorageAt using rpc.BlockNumberOrHash at genesis (blockNumber)",
|
||||||
|
args: args{
|
||||||
|
rctx: RewriteContext{latest: hexutil.Uint64(100)},
|
||||||
|
req: &RPCReq{Method: "eth_getStorageAt", Params: mustMarshalJSON([]interface{}{
|
||||||
|
"0xae851f927ee40de99aabb7461c00f9622ab91d60",
|
||||||
|
"10",
|
||||||
|
map[string]interface{}{
|
||||||
|
"blockNumber": "0x0",
|
||||||
|
}})},
|
||||||
|
res: nil,
|
||||||
|
},
|
||||||
|
expected: RewriteNone,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "eth_getStorageAt using rpc.BlockNumberOrHash at genesis (hash)",
|
||||||
|
args: args{
|
||||||
|
rctx: RewriteContext{latest: hexutil.Uint64(100)},
|
||||||
|
req: &RPCReq{Method: "eth_getStorageAt", Params: mustMarshalJSON([]interface{}{
|
||||||
|
"0xae851f927ee40de99aabb7461c00f9622ab91d60",
|
||||||
|
"10",
|
||||||
|
map[string]interface{}{
|
||||||
|
"blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3",
|
||||||
|
"requireCanonical": true,
|
||||||
|
}})},
|
||||||
|
res: nil,
|
||||||
|
},
|
||||||
|
expected: RewriteNone,
|
||||||
|
check: func(t *testing.T, args args) {
|
||||||
|
var p []interface{}
|
||||||
|
err := json.Unmarshal(args.req.Params, &p)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, 3, len(p))
|
||||||
|
require.Equal(t, "0xae851f927ee40de99aabb7461c00f9622ab91d60", p[0])
|
||||||
|
require.Equal(t, "10", p[1])
|
||||||
|
bnh, err := remarshalBlockNumberOrHash(p[2])
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, rpc.BlockNumberOrHashWithHash(common.HexToHash("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"), true), *bnh)
|
||||||
|
require.True(t, bnh.RequireCanonical)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "eth_getStorageAt using rpc.BlockNumberOrHash at latest (blockNumber)",
|
||||||
|
args: args{
|
||||||
|
rctx: RewriteContext{latest: hexutil.Uint64(100)},
|
||||||
|
req: &RPCReq{Method: "eth_getStorageAt", Params: mustMarshalJSON([]interface{}{
|
||||||
|
"0xae851f927ee40de99aabb7461c00f9622ab91d60",
|
||||||
|
"10",
|
||||||
|
map[string]interface{}{
|
||||||
|
"blockNumber": "latest",
|
||||||
|
}})},
|
||||||
|
res: nil,
|
||||||
|
},
|
||||||
|
expected: RewriteOverrideRequest,
|
||||||
|
check: func(t *testing.T, args args) {
|
||||||
|
var p []interface{}
|
||||||
|
err := json.Unmarshal(args.req.Params, &p)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, 3, len(p))
|
||||||
|
require.Equal(t, "0xae851f927ee40de99aabb7461c00f9622ab91d60", p[0])
|
||||||
|
require.Equal(t, "10", p[1])
|
||||||
|
bnh, err := remarshalBlockNumberOrHash(p[2])
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, rpc.BlockNumberOrHashWithNumber(100), *bnh)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "eth_getStorageAt using rpc.BlockNumberOrHash out of range",
|
||||||
|
args: args{
|
||||||
|
rctx: RewriteContext{latest: hexutil.Uint64(100)},
|
||||||
|
req: &RPCReq{Method: "eth_getStorageAt", Params: mustMarshalJSON([]interface{}{
|
||||||
|
"0xae851f927ee40de99aabb7461c00f9622ab91d60",
|
||||||
|
"10",
|
||||||
|
map[string]interface{}{
|
||||||
|
"blockNumber": "0x111",
|
||||||
|
}})},
|
||||||
|
res: nil,
|
||||||
|
},
|
||||||
|
expected: RewriteOverrideError,
|
||||||
|
expectedErr: ErrRewriteBlockOutOfRange,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// generalize tests for other methods with same interface and behavior
|
// generalize tests for other methods with same interface and behavior
|
||||||
@ -528,6 +620,7 @@ func TestRewriteRequest(t *testing.T) {
|
|||||||
tests = generalize(tests, "eth_getBlockByNumber", "eth_getUncleCountByBlockNumber")
|
tests = generalize(tests, "eth_getBlockByNumber", "eth_getUncleCountByBlockNumber")
|
||||||
tests = generalize(tests, "eth_getBlockByNumber", "eth_getTransactionByBlockNumberAndIndex")
|
tests = generalize(tests, "eth_getBlockByNumber", "eth_getTransactionByBlockNumberAndIndex")
|
||||||
tests = generalize(tests, "eth_getBlockByNumber", "eth_getUncleByBlockNumberAndIndex")
|
tests = generalize(tests, "eth_getBlockByNumber", "eth_getUncleByBlockNumberAndIndex")
|
||||||
|
tests = generalize(tests, "eth_getStorageSlotAt", "eth_getProof")
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
Loading…
Reference in New Issue
Block a user