From 32c2d48a3b685d5f9f33d1f54a66acbfa54fc3d1 Mon Sep 17 00:00:00 2001 From: Ryan Schneider Date: Mon, 3 Oct 2022 13:37:18 -0700 Subject: [PATCH 1/2] eth: Fix for eth_getLogs failing w/ finalized and safe tags. --- eth/filters/filter.go | 38 +++++++++++++++++++++++++------ eth/filters/filter_system_test.go | 7 ++++++ eth/filters/filter_test.go | 31 +++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 7 deletions(-) diff --git a/eth/filters/filter.go b/eth/filters/filter.go index 0a70c9ece1d..fbbb4a7aab8 100644 --- a/eth/filters/filter.go +++ b/eth/filters/filter.go @@ -119,20 +119,44 @@ func (f *Filter) Logs(ctx context.Context) ([]*types.Log, error) { return nil, nil } var ( - head = header.Number.Uint64() - end = uint64(f.end) + err error + head = header.Number.Int64() pending = f.end == rpc.PendingBlockNumber.Int64() ) - if f.begin == rpc.LatestBlockNumber.Int64() { - f.begin = int64(head) + resolveSpecial := func(number int64) (int64, error) { + var hdr *types.Header + switch number { + case rpc.LatestBlockNumber.Int64(): + return head, nil + case rpc.PendingBlockNumber.Int64(): + // we should return head here since we've already captured + // that we need to get the pending logs in the pending boolean above + return head, nil + case rpc.FinalizedBlockNumber.Int64(): + hdr, _ = f.sys.backend.HeaderByNumber(ctx, rpc.FinalizedBlockNumber) + if hdr == nil { + return 0, errors.New("finalized header not found") + } + case rpc.SafeBlockNumber.Int64(): + hdr, _ = f.sys.backend.HeaderByNumber(ctx, rpc.SafeBlockNumber) + if hdr == nil { + return 0, errors.New("safe header not found") + } + default: + return number, nil + } + return hdr.Number.Int64(), nil } - if f.end == rpc.LatestBlockNumber.Int64() || f.end == rpc.PendingBlockNumber.Int64() { - end = head + if f.begin, err = resolveSpecial(f.begin); err != nil { + return nil, err + } + if f.end, err = resolveSpecial(f.end); err != nil { + return nil, err } // Gather all indexed logs, and finish with non indexed ones var ( logs []*types.Log - err error + end = uint64(f.end) size, sections = f.sys.backend.BloomStatus() ) if indexed := sections * size; indexed > uint64(f.begin) { diff --git a/eth/filters/filter_system_test.go b/eth/filters/filter_system_test.go index 73a4ab2d4fc..f38274ba68f 100644 --- a/eth/filters/filter_system_test.go +++ b/eth/filters/filter_system_test.go @@ -65,6 +65,13 @@ func (b *testBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumbe return nil, nil } num = *number + } else if blockNr == rpc.FinalizedBlockNumber { + hash = rawdb.ReadFinalizedBlockHash(b.db) + number := rawdb.ReadHeaderNumber(b.db, hash) + if number == nil { + return nil, nil + } + num = *number } else { num = uint64(blockNr) hash = rawdb.ReadCanonicalHash(b.db, num) diff --git a/eth/filters/filter_test.go b/eth/filters/filter_test.go index 39ed46cec76..d519d80fbe2 100644 --- a/eth/filters/filter_test.go +++ b/eth/filters/filter_test.go @@ -170,6 +170,9 @@ func TestFilters(t *testing.T) { rawdb.WriteReceipts(db, block.Hash(), block.NumberU64(), receipts[i]) } + // 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}}) logs, _ := filter.Logs(context.Background()) @@ -224,4 +227,32 @@ func TestFilters(t *testing.T) { if len(logs) != 0 { t.Error("expected 0 log, got", len(logs)) } + + filter = sys.NewRangeFilter(-1, -1, nil, nil) + + logs, _ = filter.Logs(context.Background()) + if len(logs) != 1 { + t.Error("expected 1 log, got", len(logs)) + } + + filter = sys.NewRangeFilter(-3, -1, nil, nil) + + logs, _ = filter.Logs(context.Background()) + if len(logs) != 2 { + t.Error("expected 2 log, got", len(logs)) + } + + filter = sys.NewRangeFilter(-3, -3, nil, nil) + + logs, _ = filter.Logs(context.Background()) + if len(logs) != 1 { + t.Error("expected 1 log, got", len(logs)) + } + + filter = sys.NewRangeFilter(-1, -3, nil, nil) + + logs, _ = filter.Logs(context.Background()) + if len(logs) != 0 { + t.Error("expected 0 log, got", len(logs)) + } } From 4684596e19f262be753d618343f49b29ce95b03a Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Wed, 5 Oct 2022 12:16:35 +0200 Subject: [PATCH 2/2] accounts/abi/bind/backends, eth/filters: handle rpc safe block, restructure tests --- accounts/abi/bind/backends/simulated.go | 23 ++++- eth/filters/filter_system_test.go | 10 +- eth/filters/filter_test.go | 128 ++++++++++-------------- 3 files changed, 80 insertions(+), 81 deletions(-) diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go index 21c94d7e17e..277850e3b57 100644 --- a/accounts/abi/bind/backends/simulated.go +++ b/accounts/abi/bind/backends/simulated.go @@ -844,11 +844,28 @@ func (fb *filterBackend) ChainDb() ethdb.Database { return fb.db } func (fb *filterBackend) EventMux() *event.TypeMux { panic("not supported") } -func (fb *filterBackend) HeaderByNumber(ctx context.Context, block rpc.BlockNumber) (*types.Header, error) { - if block == rpc.LatestBlockNumber { +func (fb *filterBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) { + switch number { + case rpc.PendingBlockNumber: + if block := fb.backend.pendingBlock; block != nil { + return block.Header(), nil + } + return nil, nil + case rpc.LatestBlockNumber: return fb.bc.CurrentHeader(), nil + case rpc.FinalizedBlockNumber: + if block := fb.bc.CurrentFinalizedBlock(); block != nil { + return block.Header(), nil + } + return nil, errors.New("finalized block not found") + case rpc.SafeBlockNumber: + if block := fb.bc.CurrentSafeBlock(); block != nil { + return block.Header(), nil + } + return nil, errors.New("safe block not found") + default: + return fb.bc.GetHeaderByNumber(uint64(number.Int64())), nil } - return fb.bc.GetHeaderByNumber(uint64(block.Int64())), nil } func (fb *filterBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { diff --git a/eth/filters/filter_system_test.go b/eth/filters/filter_system_test.go index f38274ba68f..4386f0e5bde 100644 --- a/eth/filters/filter_system_test.go +++ b/eth/filters/filter_system_test.go @@ -18,6 +18,7 @@ package filters import ( "context" + "errors" "fmt" "math/big" "math/rand" @@ -58,21 +59,24 @@ func (b *testBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumbe hash common.Hash num uint64 ) - if blockNr == rpc.LatestBlockNumber { + switch blockNr { + case rpc.LatestBlockNumber: hash = rawdb.ReadHeadBlockHash(b.db) number := rawdb.ReadHeaderNumber(b.db, hash) if number == nil { return nil, nil } num = *number - } else if blockNr == rpc.FinalizedBlockNumber { + case rpc.FinalizedBlockNumber: hash = rawdb.ReadFinalizedBlockHash(b.db) number := rawdb.ReadHeaderNumber(b.db, hash) if number == nil { return nil, nil } num = *number - } else { + case rpc.SafeBlockNumber: + return nil, errors.New("safe block not found") + default: num = uint64(blockNr) hash = rawdb.ReadCanonicalHash(b.db, num) } diff --git a/eth/filters/filter_test.go b/eth/filters/filter_test.go index d519d80fbe2..2a4dfd90ad8 100644 --- a/eth/filters/filter_test.go +++ b/eth/filters/filter_test.go @@ -19,6 +19,7 @@ package filters import ( "context" "math/big" + "reflect" "testing" "github.com/ethereum/go-ethereum/common" @@ -174,85 +175,62 @@ func TestFilters(t *testing.T) { rawdb.WriteFinalizedBlockHash(db, chain[998].Hash()) filter := sys.NewRangeFilter(0, -1, []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)) } - filter = sys.NewRangeFilter(900, 999, []common.Address{addr}, [][]common.Hash{{hash3}}) - logs, _ = filter.Logs(context.Background()) - if len(logs) != 1 { - t.Error("expected 1 log, got", len(logs)) - } - if len(logs) > 0 && logs[0].Topics[0] != hash3 { - t.Errorf("expected log[0].Topics[0] to be %x, got %x", hash3, logs[0].Topics[0]) - } - - filter = sys.NewRangeFilter(990, -1, []common.Address{addr}, [][]common.Hash{{hash3}}) - logs, _ = filter.Logs(context.Background()) - if len(logs) != 1 { - t.Error("expected 1 log, got", len(logs)) - } - if len(logs) > 0 && logs[0].Topics[0] != hash3 { - t.Errorf("expected log[0].Topics[0] to be %x, got %x", hash3, logs[0].Topics[0]) - } - - filter = sys.NewRangeFilter(1, 10, nil, [][]common.Hash{{hash1, hash2}}) - - logs, _ = filter.Logs(context.Background()) - if len(logs) != 2 { - t.Error("expected 2 log, got", len(logs)) - } - - failHash := common.BytesToHash([]byte("fail")) - filter = sys.NewRangeFilter(0, -1, nil, [][]common.Hash{{failHash}}) - - logs, _ = filter.Logs(context.Background()) - if len(logs) != 0 { - t.Error("expected 0 log, got", len(logs)) - } - - failAddr := common.BytesToAddress([]byte("failmenow")) - filter = sys.NewRangeFilter(0, -1, []common.Address{failAddr}, nil) - - logs, _ = filter.Logs(context.Background()) - if len(logs) != 0 { - t.Error("expected 0 log, got", len(logs)) - } - - filter = sys.NewRangeFilter(0, -1, nil, [][]common.Hash{{failHash}, {hash1}}) - - logs, _ = filter.Logs(context.Background()) - if len(logs) != 0 { - t.Error("expected 0 log, got", len(logs)) - } - - filter = sys.NewRangeFilter(-1, -1, nil, nil) - - logs, _ = filter.Logs(context.Background()) - if len(logs) != 1 { - t.Error("expected 1 log, got", len(logs)) - } - - filter = sys.NewRangeFilter(-3, -1, nil, nil) - - logs, _ = filter.Logs(context.Background()) - if len(logs) != 2 { - t.Error("expected 2 log, got", len(logs)) - } - - filter = sys.NewRangeFilter(-3, -3, nil, nil) - - logs, _ = filter.Logs(context.Background()) - if len(logs) != 1 { - t.Error("expected 1 log, got", len(logs)) - } - - filter = sys.NewRangeFilter(-1, -3, nil, nil) - - logs, _ = filter.Logs(context.Background()) - if len(logs) != 0 { - t.Error("expected 0 log, got", len(logs)) + for i, tc := range []struct { + f *Filter + wantHashes []common.Hash + }{ + { + sys.NewRangeFilter(900, 999, []common.Address{addr}, [][]common.Hash{{hash3}}), + []common.Hash{hash3}, + }, { + sys.NewRangeFilter(990, -1, []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"))}}), + nil, + }, { + sys.NewRangeFilter(0, -1, []common.Address{common.BytesToAddress([]byte("failmenow"))}, nil), + nil, + }, { + sys.NewRangeFilter(0, -1, nil, [][]common.Hash{{common.BytesToHash([]byte("fail"))}, {hash1}}), + nil, + }, { + sys.NewRangeFilter(-1, -1, nil, nil), []common.Hash{hash4}, + }, { + sys.NewRangeFilter(-3, -1, nil, nil), []common.Hash{hash3, hash4}, + }, { + sys.NewRangeFilter(-3, -3, nil, nil), []common.Hash{hash3}, + }, { + sys.NewRangeFilter(-1, -3, nil, nil), nil, + }, { + sys.NewRangeFilter(-4, -1, nil, nil), nil, + }, { + sys.NewRangeFilter(-4, -4, nil, nil), nil, + }, { + sys.NewRangeFilter(-1, -4, nil, nil), nil, + }, + } { + logs, _ := tc.f.Logs(context.Background()) + var haveHashes []common.Hash + for _, l := range logs { + haveHashes = append(haveHashes, l.Topics[0]) + } + if have, want := len(haveHashes), len(tc.wantHashes); have != want { + t.Fatalf("test %d, have %d logs, want %d", i, have, want) + } + if len(haveHashes) == 0 { + continue + } + if !reflect.DeepEqual(tc.wantHashes, haveHashes) { + t.Fatalf("test %d, have %v want %v", i, haveHashes, tc.wantHashes) + } } }