rpc: change BlockNumber constant values to match ethclient (#27219)

ethclient accepts certain negative block number values as specifiers for the "pending",
"safe" and "finalized" block. In case of "pending", the value accepted by ethclient (-1)
did not match rpc.PendingBlockNumber (-2).

This wasn't really a problem, but other values accepted by ethclient did match the
definitions in package rpc, and it's weird to have this one special case where they don't.

To fix it, we decided to change the values of the constants rather than changing ethclient.
The constant values are not otherwise significant. This is a breaking API change, but we
believe not a dangerous one.

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
pull/27329/head
Martin Holst Swende 1 year ago committed by GitHub
parent 1a18283e85
commit 9231770811
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      eth/filters/api_test.go
  2. 3
      eth/filters/filter.go
  3. 27
      eth/filters/filter_test.go
  4. 18
      ethclient/ethclient.go
  5. 19
      ethclient/gethclient/gethclient.go
  6. 32
      rpc/types.go

@ -56,7 +56,7 @@ func TestUnmarshalJSONNewFilterArgs(t *testing.T) {
// from, to block number // from, to block number
var test1 FilterCriteria var test1 FilterCriteria
vector := fmt.Sprintf(`{"fromBlock":"%#x","toBlock":"%#x"}`, fromBlock, toBlock) vector := fmt.Sprintf(`{"fromBlock":"%v","toBlock":"%v"}`, fromBlock, toBlock)
if err := json.Unmarshal([]byte(vector), &test1); err != nil { if err := json.Unmarshal([]byte(vector), &test1); err != nil {
t.Fatal(err) t.Fatal(err)
} }

@ -296,6 +296,9 @@ func (f *Filter) checkMatches(ctx context.Context, header *types.Header) ([]*typ
// pendingLogs returns the logs matching the filter criteria within the pending block. // pendingLogs returns the logs matching the filter criteria within the pending block.
func (f *Filter) pendingLogs() ([]*types.Log, error) { func (f *Filter) pendingLogs() ([]*types.Log, error) {
block, receipts := f.sys.backend.PendingBlockAndReceipts() block, receipts := f.sys.backend.PendingBlockAndReceipts()
if block == nil {
return nil, errors.New("pending state not available")
}
if bloomFilter(block.Bloom(), f.addresses, f.topics) { if bloomFilter(block.Bloom(), f.addresses, f.topics) {
var unfiltered []*types.Log var unfiltered []*types.Log
for _, r := range receipts { for _, r := range receipts {

@ -29,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
) )
func makeReceipt(addr common.Address) *types.Receipt { func makeReceipt(addr common.Address) *types.Receipt {
@ -179,7 +180,7 @@ func TestFilters(t *testing.T) {
// Set block 998 as Finalized (-3) // Set block 998 as Finalized (-3)
rawdb.WriteFinalizedBlockHash(db, chain[998].Hash()) rawdb.WriteFinalizedBlockHash(db, chain[998].Hash())
filter := sys.NewRangeFilter(0, -1, []common.Address{addr}, [][]common.Hash{{hash1, hash2, hash3, hash4}}) filter := sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), []common.Address{addr}, [][]common.Hash{{hash1, hash2, hash3, hash4}})
logs, _ := filter.Logs(context.Background()) logs, _ := filter.Logs(context.Background())
if len(logs) != 4 { if len(logs) != 4 {
t.Error("expected 4 log, got", len(logs)) t.Error("expected 4 log, got", len(logs))
@ -193,34 +194,36 @@ func TestFilters(t *testing.T) {
sys.NewRangeFilter(900, 999, []common.Address{addr}, [][]common.Hash{{hash3}}), sys.NewRangeFilter(900, 999, []common.Address{addr}, [][]common.Hash{{hash3}}),
[]common.Hash{hash3}, []common.Hash{hash3},
}, { }, {
sys.NewRangeFilter(990, -1, []common.Address{addr}, [][]common.Hash{{hash3}}), sys.NewRangeFilter(990, int64(rpc.LatestBlockNumber), []common.Address{addr}, [][]common.Hash{{hash3}}),
[]common.Hash{hash3}, []common.Hash{hash3},
}, { }, {
sys.NewRangeFilter(1, 10, nil, [][]common.Hash{{hash1, hash2}}), sys.NewRangeFilter(1, 10, nil, [][]common.Hash{{hash1, hash2}}),
[]common.Hash{hash1, hash2}, []common.Hash{hash1, hash2},
}, { }, {
sys.NewRangeFilter(0, -1, nil, [][]common.Hash{{common.BytesToHash([]byte("fail"))}}), sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), nil, [][]common.Hash{{common.BytesToHash([]byte("fail"))}}),
nil, nil,
}, { }, {
sys.NewRangeFilter(0, -1, []common.Address{common.BytesToAddress([]byte("failmenow"))}, nil), sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), []common.Address{common.BytesToAddress([]byte("failmenow"))}, nil),
nil, nil,
}, { }, {
sys.NewRangeFilter(0, -1, nil, [][]common.Hash{{common.BytesToHash([]byte("fail"))}, {hash1}}), sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), nil, [][]common.Hash{{common.BytesToHash([]byte("fail"))}, {hash1}}),
nil, nil,
}, { }, {
sys.NewRangeFilter(-1, -1, nil, nil), []common.Hash{hash4}, sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.LatestBlockNumber), nil, nil), []common.Hash{hash4},
}, { }, {
sys.NewRangeFilter(-3, -1, nil, nil), []common.Hash{hash3, hash4}, sys.NewRangeFilter(int64(rpc.FinalizedBlockNumber), int64(rpc.LatestBlockNumber), nil, nil), []common.Hash{hash3, hash4},
}, { }, {
sys.NewRangeFilter(-3, -3, nil, nil), []common.Hash{hash3}, sys.NewRangeFilter(int64(rpc.FinalizedBlockNumber), int64(rpc.FinalizedBlockNumber), nil, nil), []common.Hash{hash3},
}, { }, {
sys.NewRangeFilter(-1, -3, nil, nil), nil, sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.FinalizedBlockNumber), nil, nil), nil,
}, { }, {
sys.NewRangeFilter(-4, -1, nil, nil), nil, sys.NewRangeFilter(int64(rpc.SafeBlockNumber), int64(rpc.LatestBlockNumber), nil, nil), nil,
}, { }, {
sys.NewRangeFilter(-4, -4, nil, nil), nil, sys.NewRangeFilter(int64(rpc.SafeBlockNumber), int64(rpc.SafeBlockNumber), nil, nil), nil,
}, { }, {
sys.NewRangeFilter(-1, -4, nil, nil), nil, sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.SafeBlockNumber), nil, nil), nil,
}, {
sys.NewRangeFilter(int64(rpc.PendingBlockNumber), int64(rpc.PendingBlockNumber), nil, nil), nil,
}, },
} { } {
logs, _ := tc.f.Logs(context.Background()) logs, _ := tc.f.Logs(context.Background())

@ -592,19 +592,15 @@ func toBlockNumArg(number *big.Int) string {
if number == nil { if number == nil {
return "latest" return "latest"
} }
pending := big.NewInt(-1) if number.Sign() >= 0 {
if number.Cmp(pending) == 0 { return hexutil.EncodeBig(number)
return "pending"
} }
finalized := big.NewInt(int64(rpc.FinalizedBlockNumber)) // It's negative.
if number.Cmp(finalized) == 0 { if number.IsInt64() {
return "finalized" return rpc.BlockNumber(number.Int64()).String()
} }
safe := big.NewInt(int64(rpc.SafeBlockNumber)) // It's negative and large, which is invalid.
if number.Cmp(safe) == 0 { return fmt.Sprintf("<invalid %d>", number)
return "safe"
}
return hexutil.EncodeBig(number)
} }
func toCallArg(msg ethereum.CallMsg) interface{} { func toCallArg(msg ethereum.CallMsg) interface{} {

@ -20,6 +20,7 @@ package gethclient
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"fmt"
"math/big" "math/big"
"runtime" "runtime"
"runtime/debug" "runtime/debug"
@ -207,19 +208,15 @@ func toBlockNumArg(number *big.Int) string {
if number == nil { if number == nil {
return "latest" return "latest"
} }
pending := big.NewInt(-1) if number.Sign() >= 0 {
if number.Cmp(pending) == 0 { return hexutil.EncodeBig(number)
return "pending"
} }
finalized := big.NewInt(int64(rpc.FinalizedBlockNumber)) // It's negative.
if number.Cmp(finalized) == 0 { if number.IsInt64() {
return "finalized" return rpc.BlockNumber(number.Int64()).String()
} }
safe := big.NewInt(int64(rpc.SafeBlockNumber)) // It's negative and large, which is invalid.
if number.Cmp(safe) == 0 { return fmt.Sprintf("<invalid %d>", number)
return "safe"
}
return hexutil.EncodeBig(number)
} }
func toCallArg(msg ethereum.CallMsg) interface{} { func toCallArg(msg ethereum.CallMsg) interface{} {

@ -65,8 +65,8 @@ type BlockNumber int64
const ( const (
SafeBlockNumber = BlockNumber(-4) SafeBlockNumber = BlockNumber(-4)
FinalizedBlockNumber = BlockNumber(-3) FinalizedBlockNumber = BlockNumber(-3)
PendingBlockNumber = BlockNumber(-2) LatestBlockNumber = BlockNumber(-2)
LatestBlockNumber = BlockNumber(-1) PendingBlockNumber = BlockNumber(-1)
EarliestBlockNumber = BlockNumber(0) EarliestBlockNumber = BlockNumber(0)
) )
@ -111,30 +111,38 @@ func (bn *BlockNumber) UnmarshalJSON(data []byte) error {
return nil return nil
} }
// Int64 returns the block number as int64.
func (bn BlockNumber) Int64() int64 {
return (int64)(bn)
}
// MarshalText implements encoding.TextMarshaler. It marshals: // MarshalText implements encoding.TextMarshaler. It marshals:
// - "safe", "finalized", "latest", "earliest" or "pending" as strings // - "safe", "finalized", "latest", "earliest" or "pending" as strings
// - other numbers as hex // - other numbers as hex
func (bn BlockNumber) MarshalText() ([]byte, error) { func (bn BlockNumber) MarshalText() ([]byte, error) {
return []byte(bn.String()), nil
}
func (bn BlockNumber) String() string {
switch bn { switch bn {
case EarliestBlockNumber: case EarliestBlockNumber:
return []byte("earliest"), nil return "earliest"
case LatestBlockNumber: case LatestBlockNumber:
return []byte("latest"), nil return "latest"
case PendingBlockNumber: case PendingBlockNumber:
return []byte("pending"), nil return "pending"
case FinalizedBlockNumber: case FinalizedBlockNumber:
return []byte("finalized"), nil return "finalized"
case SafeBlockNumber: case SafeBlockNumber:
return []byte("safe"), nil return "safe"
default: default:
return hexutil.Uint64(bn).MarshalText() if bn < 0 {
return fmt.Sprintf("<invalid %d>", bn)
}
return hexutil.Uint64(bn).String()
} }
} }
func (bn BlockNumber) Int64() int64 {
return (int64)(bn)
}
type BlockNumberOrHash struct { type BlockNumberOrHash struct {
BlockNumber *BlockNumber `json:"blockNumber,omitempty"` BlockNumber *BlockNumber `json:"blockNumber,omitempty"`
BlockHash *common.Hash `json:"blockHash,omitempty"` BlockHash *common.Hash `json:"blockHash,omitempty"`

Loading…
Cancel
Save