diff --git a/eth/filters/api_test.go b/eth/filters/api_test.go index 0a80d0f8d..822bc826f 100644 --- a/eth/filters/api_test.go +++ b/eth/filters/api_test.go @@ -56,7 +56,7 @@ func TestUnmarshalJSONNewFilterArgs(t *testing.T) { // from, to block number 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 { t.Fatal(err) } diff --git a/eth/filters/filter.go b/eth/filters/filter.go index 8ba482817..122676e96 100644 --- a/eth/filters/filter.go +++ b/eth/filters/filter.go @@ -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. func (f *Filter) pendingLogs() ([]*types.Log, error) { 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) { var unfiltered []*types.Log for _, r := range receipts { diff --git a/eth/filters/filter_test.go b/eth/filters/filter_test.go index d10e0f1d9..0e42c798e 100644 --- a/eth/filters/filter_test.go +++ b/eth/filters/filter_test.go @@ -29,6 +29,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rpc" ) func makeReceipt(addr common.Address) *types.Receipt { @@ -179,7 +180,7 @@ func TestFilters(t *testing.T) { // Set block 998 as Finalized (-3) 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()) if len(logs) != 4 { 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}}), []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}, }, { sys.NewRangeFilter(1, 10, nil, [][]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, }, { - 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, }, { - 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, }, { - 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()) diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go index 09d3f37d1..59e95f629 100644 --- a/ethclient/ethclient.go +++ b/ethclient/ethclient.go @@ -592,19 +592,15 @@ func toBlockNumArg(number *big.Int) string { if number == nil { return "latest" } - pending := big.NewInt(-1) - if number.Cmp(pending) == 0 { - return "pending" + if number.Sign() >= 0 { + return hexutil.EncodeBig(number) } - finalized := big.NewInt(int64(rpc.FinalizedBlockNumber)) - if number.Cmp(finalized) == 0 { - return "finalized" + // It's negative. + if number.IsInt64() { + return rpc.BlockNumber(number.Int64()).String() } - safe := big.NewInt(int64(rpc.SafeBlockNumber)) - if number.Cmp(safe) == 0 { - return "safe" - } - return hexutil.EncodeBig(number) + // It's negative and large, which is invalid. + return fmt.Sprintf("", number) } func toCallArg(msg ethereum.CallMsg) interface{} { diff --git a/ethclient/gethclient/gethclient.go b/ethclient/gethclient/gethclient.go index 718cdfea4..c02961167 100644 --- a/ethclient/gethclient/gethclient.go +++ b/ethclient/gethclient/gethclient.go @@ -20,6 +20,7 @@ package gethclient import ( "context" "encoding/json" + "fmt" "math/big" "runtime" "runtime/debug" @@ -207,19 +208,15 @@ func toBlockNumArg(number *big.Int) string { if number == nil { return "latest" } - pending := big.NewInt(-1) - if number.Cmp(pending) == 0 { - return "pending" + if number.Sign() >= 0 { + return hexutil.EncodeBig(number) } - finalized := big.NewInt(int64(rpc.FinalizedBlockNumber)) - if number.Cmp(finalized) == 0 { - return "finalized" + // It's negative. + if number.IsInt64() { + return rpc.BlockNumber(number.Int64()).String() } - safe := big.NewInt(int64(rpc.SafeBlockNumber)) - if number.Cmp(safe) == 0 { - return "safe" - } - return hexutil.EncodeBig(number) + // It's negative and large, which is invalid. + return fmt.Sprintf("", number) } func toCallArg(msg ethereum.CallMsg) interface{} { diff --git a/rpc/types.go b/rpc/types.go index 55d11fbaa..34a1451de 100644 --- a/rpc/types.go +++ b/rpc/types.go @@ -65,8 +65,8 @@ type BlockNumber int64 const ( SafeBlockNumber = BlockNumber(-4) FinalizedBlockNumber = BlockNumber(-3) - PendingBlockNumber = BlockNumber(-2) - LatestBlockNumber = BlockNumber(-1) + LatestBlockNumber = BlockNumber(-2) + PendingBlockNumber = BlockNumber(-1) EarliestBlockNumber = BlockNumber(0) ) @@ -111,28 +111,36 @@ func (bn *BlockNumber) UnmarshalJSON(data []byte) error { return nil } +// Int64 returns the block number as int64. +func (bn BlockNumber) Int64() int64 { + return (int64)(bn) +} + // MarshalText implements encoding.TextMarshaler. It marshals: // - "safe", "finalized", "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 - case FinalizedBlockNumber: - return []byte("finalized"), nil - case SafeBlockNumber: - return []byte("safe"), nil - default: - return hexutil.Uint64(bn).MarshalText() - } + return []byte(bn.String()), nil } -func (bn BlockNumber) Int64() int64 { - return (int64)(bn) +func (bn BlockNumber) String() string { + switch bn { + case EarliestBlockNumber: + return "earliest" + case LatestBlockNumber: + return "latest" + case PendingBlockNumber: + return "pending" + case FinalizedBlockNumber: + return "finalized" + case SafeBlockNumber: + return "safe" + default: + if bn < 0 { + return fmt.Sprintf("", bn) + } + return hexutil.Uint64(bn).String() + } } type BlockNumberOrHash struct {