From 562be5f7527aafde7f5e7e0132b4450128a9eb14 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Thu, 4 May 2023 10:39:00 +0200 Subject: [PATCH 1/8] ethclient: fix discrepancy between latest/pending blocknumbers --- ethclient/ethclient.go | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go index 47beaf63cc0e..47b9eda16b57 100644 --- a/ethclient/ethclient.go +++ b/ethclient/ethclient.go @@ -582,19 +582,16 @@ func (ec *Client) SendTransaction(ctx context.Context, tx *types.Transaction) er } func toBlockNumArg(number *big.Int) string { - if number == nil { + if number == nil || number.Cmp(big.NewInt(int64(rpc.LatestBlockNumber))) == 0 { return "latest" } - pending := big.NewInt(-1) - if number.Cmp(pending) == 0 { + if number.Cmp(big.NewInt(int64(rpc.PendingBlockNumber))) == 0 { return "pending" } - finalized := big.NewInt(int64(rpc.FinalizedBlockNumber)) - if number.Cmp(finalized) == 0 { + if number.Cmp(big.NewInt(int64(rpc.FinalizedBlockNumber))) == 0 { return "finalized" } - safe := big.NewInt(int64(rpc.SafeBlockNumber)) - if number.Cmp(safe) == 0 { + if number.Cmp(big.NewInt(int64(rpc.SafeBlockNumber))) == 0 { return "safe" } return hexutil.EncodeBig(number) From 11ad739488dd26e64670f14af65e98d96096fbd1 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Wed, 10 May 2023 16:25:21 +0200 Subject: [PATCH 2/8] rpc: swap rpc.Latest and rpc.Pending block number (internal) constant --- rpc/types.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rpc/types.go b/rpc/types.go index 55d11fbaaf14..5582fa199eb9 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) ) From d64678ec652bfa5b58309b4c1fe5d0fab701a97f Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Thu, 11 May 2023 11:00:50 +0200 Subject: [PATCH 3/8] eth/filters: use constants instead of magic, handle missing pending state --- eth/filters/filter.go | 3 +++ eth/filters/filter_test.go | 27 +++++++++++++++------------ 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/eth/filters/filter.go b/eth/filters/filter.go index 8ba482817e0c..122676e96c81 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 d10e0f1d9482..0e42c798ec9e 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()) From 3ea8e2b08534642556dbffa623c1ba407816a250 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Tue, 16 May 2023 16:37:34 +0200 Subject: [PATCH 4/8] rpc: add String method for BlockNumber --- rpc/types.go | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/rpc/types.go b/rpc/types.go index 5582fa199eb9..34a1451deaa7 100644 --- a/rpc/types.go +++ b/rpc/types.go @@ -111,30 +111,38 @@ 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) { + return []byte(bn.String()), nil +} + +func (bn BlockNumber) String() string { switch bn { case EarliestBlockNumber: - return []byte("earliest"), nil + return "earliest" case LatestBlockNumber: - return []byte("latest"), nil + return "latest" case PendingBlockNumber: - return []byte("pending"), nil + return "pending" case FinalizedBlockNumber: - return []byte("finalized"), nil + return "finalized" case SafeBlockNumber: - return []byte("safe"), nil + return "safe" default: - return hexutil.Uint64(bn).MarshalText() + if bn < 0 { + return fmt.Sprintf("", bn) + } + return hexutil.Uint64(bn).String() } } -func (bn BlockNumber) Int64() int64 { - return (int64)(bn) -} - type BlockNumberOrHash struct { BlockNumber *BlockNumber `json:"blockNumber,omitempty"` BlockHash *common.Hash `json:"blockHash,omitempty"` From 236358ec7044c9e5985d3ac073e0c3bd608f4d40 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Tue, 16 May 2023 16:37:50 +0200 Subject: [PATCH 5/8] ethclient: improve toBlockNumArg - avoid creating big.Int just to compare with BlockNumber - use String method of BlockNumber --- ethclient/ethclient.go | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go index 47b9eda16b57..11c2f6d2192b 100644 --- a/ethclient/ethclient.go +++ b/ethclient/ethclient.go @@ -582,19 +582,18 @@ func (ec *Client) SendTransaction(ctx context.Context, tx *types.Transaction) er } func toBlockNumArg(number *big.Int) string { - if number == nil || number.Cmp(big.NewInt(int64(rpc.LatestBlockNumber))) == 0 { + if number == nil { return "latest" } - if number.Cmp(big.NewInt(int64(rpc.PendingBlockNumber))) == 0 { - return "pending" + if number.Sign() >= 0 { + return hexutil.EncodeBig(number) } - if number.Cmp(big.NewInt(int64(rpc.FinalizedBlockNumber))) == 0 { - return "finalized" + // It's negative. + if number.IsInt64() { + return rpc.BlockNumber(number.Int64()).String() } - if number.Cmp(big.NewInt(int64(rpc.SafeBlockNumber))) == 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{} { From c0cf2ac9c059f9ba18a2abab4b10dd5fa7ca0dce Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Tue, 16 May 2023 18:38:03 +0200 Subject: [PATCH 6/8] ethclient/gethclient: copy new toBlockNumArg --- ethclient/gethclient/gethclient.go | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/ethclient/gethclient/gethclient.go b/ethclient/gethclient/gethclient.go index 718cdfea426a..c029611678f0 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{} { From 48f68ab1e907973b3e060ea07cede5cb82e8d271 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Tue, 23 May 2023 11:02:30 +0200 Subject: [PATCH 7/8] eth/filters: fix test --- eth/filters/api_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/eth/filters/api_test.go b/eth/filters/api_test.go index 0a80d0f8ddbd..73a757cc4d3f 100644 --- a/eth/filters/api_test.go +++ b/eth/filters/api_test.go @@ -56,7 +56,8 @@ 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) + t.Logf("vector: %s", vector) if err := json.Unmarshal([]byte(vector), &test1); err != nil { t.Fatal(err) } From 025270c7712b9d8525b95d3092836ce25a4eea89 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Tue, 23 May 2023 11:13:11 +0200 Subject: [PATCH 8/8] eth/filters: remove log --- eth/filters/api_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/eth/filters/api_test.go b/eth/filters/api_test.go index 73a757cc4d3f..822bc826f6b0 100644 --- a/eth/filters/api_test.go +++ b/eth/filters/api_test.go @@ -57,7 +57,6 @@ func TestUnmarshalJSONNewFilterArgs(t *testing.T) { // from, to block number var test1 FilterCriteria vector := fmt.Sprintf(`{"fromBlock":"%v","toBlock":"%v"}`, fromBlock, toBlock) - t.Logf("vector: %s", vector) if err := json.Unmarshal([]byte(vector), &test1); err != nil { t.Fatal(err) }