github.com/ethereum/go-ethereum@v1.16.1/eth/filters/filter_test.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package filters 18 19 import ( 20 "context" 21 "encoding/json" 22 "math/big" 23 "strings" 24 "testing" 25 "time" 26 27 "github.com/ethereum/go-ethereum/accounts/abi" 28 "github.com/ethereum/go-ethereum/common" 29 "github.com/ethereum/go-ethereum/consensus/ethash" 30 "github.com/ethereum/go-ethereum/core" 31 "github.com/ethereum/go-ethereum/core/filtermaps" 32 "github.com/ethereum/go-ethereum/core/rawdb" 33 "github.com/ethereum/go-ethereum/core/types" 34 "github.com/ethereum/go-ethereum/crypto" 35 "github.com/ethereum/go-ethereum/params" 36 "github.com/ethereum/go-ethereum/rpc" 37 "github.com/ethereum/go-ethereum/triedb" 38 ) 39 40 func makeReceipt(addr common.Address) *types.Receipt { 41 receipt := types.NewReceipt(nil, false, 0) 42 receipt.Logs = []*types.Log{ 43 {Address: addr}, 44 } 45 receipt.Bloom = types.CreateBloom(receipt) 46 return receipt 47 } 48 49 func BenchmarkFiltersIndexed(b *testing.B) { 50 benchmarkFilters(b, 0, false) 51 } 52 53 func BenchmarkFiltersHalfIndexed(b *testing.B) { 54 benchmarkFilters(b, 50000, false) 55 } 56 57 func BenchmarkFiltersUnindexed(b *testing.B) { 58 benchmarkFilters(b, 0, true) 59 } 60 61 func benchmarkFilters(b *testing.B, history uint64, noHistory bool) { 62 var ( 63 db = rawdb.NewMemoryDatabase() 64 backend, sys = newTestFilterSystem(db, Config{}) 65 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 66 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 67 addr2 = common.BytesToAddress([]byte("jeff")) 68 addr3 = common.BytesToAddress([]byte("ethereum")) 69 addr4 = common.BytesToAddress([]byte("random addresses please")) 70 71 gspec = &core.Genesis{ 72 Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(1000000)}}, 73 BaseFee: big.NewInt(params.InitialBaseFee), 74 Config: params.TestChainConfig, 75 } 76 ) 77 defer db.Close() 78 _, chain, receipts := core.GenerateChainWithGenesis(gspec, ethash.NewFaker(), 100010, func(i int, gen *core.BlockGen) { 79 switch i { 80 case 2403: 81 receipt := makeReceipt(addr1) 82 gen.AddUncheckedReceipt(receipt) 83 gen.AddUncheckedTx(types.NewTransaction(999, common.HexToAddress("0x999"), big.NewInt(999), 999, gen.BaseFee(), nil)) 84 case 1034: 85 receipt := makeReceipt(addr2) 86 gen.AddUncheckedReceipt(receipt) 87 gen.AddUncheckedTx(types.NewTransaction(999, common.HexToAddress("0x999"), big.NewInt(999), 999, gen.BaseFee(), nil)) 88 case 34: 89 receipt := makeReceipt(addr3) 90 gen.AddUncheckedReceipt(receipt) 91 gen.AddUncheckedTx(types.NewTransaction(999, common.HexToAddress("0x999"), big.NewInt(999), 999, gen.BaseFee(), nil)) 92 case 99999: 93 receipt := makeReceipt(addr4) 94 gen.AddUncheckedReceipt(receipt) 95 gen.AddUncheckedTx(types.NewTransaction(999, common.HexToAddress("0x999"), big.NewInt(999), 999, gen.BaseFee(), nil)) 96 } 97 }) 98 // The test txs are not properly signed, can't simply create a chain 99 // and then import blocks. TODO(rjl493456442) try to get rid of the 100 // manual database writes. 101 gspec.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults)) 102 103 for i, block := range chain { 104 rawdb.WriteBlock(db, block) 105 rawdb.WriteCanonicalHash(db, block.Hash(), block.NumberU64()) 106 rawdb.WriteHeadBlockHash(db, block.Hash()) 107 rawdb.WriteReceipts(db, block.Hash(), block.NumberU64(), receipts[i]) 108 } 109 backend.startFilterMaps(history, noHistory, filtermaps.DefaultParams) 110 defer backend.stopFilterMaps() 111 112 b.ResetTimer() 113 114 filter := sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), []common.Address{addr1, addr2, addr3, addr4}, nil) 115 116 for i := 0; i < b.N; i++ { 117 filter.begin = 0 118 logs, _ := filter.Logs(context.Background()) 119 if len(logs) != 4 { 120 b.Fatal("expected 4 logs, got", len(logs)) 121 } 122 } 123 } 124 125 func TestFiltersIndexed(t *testing.T) { 126 testFilters(t, 0, false) 127 } 128 129 func TestFiltersHalfIndexed(t *testing.T) { 130 testFilters(t, 500, false) 131 } 132 133 func TestFiltersUnindexed(t *testing.T) { 134 testFilters(t, 0, true) 135 } 136 137 func testFilters(t *testing.T, history uint64, noHistory bool) { 138 var ( 139 db = rawdb.NewMemoryDatabase() 140 backend, sys = newTestFilterSystem(db, Config{}) 141 // Sender account 142 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 143 addr = crypto.PubkeyToAddress(key1.PublicKey) 144 signer = types.NewLondonSigner(big.NewInt(1)) 145 // Logging contract 146 contract = common.Address{0xfe} 147 contract2 = common.Address{0xff} 148 abiStr = `[{"inputs":[],"name":"log0","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"t1","type":"uint256"}],"name":"log1","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"t1","type":"uint256"},{"internalType":"uint256","name":"t2","type":"uint256"}],"name":"log2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"t1","type":"uint256"},{"internalType":"uint256","name":"t2","type":"uint256"},{"internalType":"uint256","name":"t3","type":"uint256"}],"name":"log3","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"t1","type":"uint256"},{"internalType":"uint256","name":"t2","type":"uint256"},{"internalType":"uint256","name":"t3","type":"uint256"},{"internalType":"uint256","name":"t4","type":"uint256"}],"name":"log4","outputs":[],"stateMutability":"nonpayable","type":"function"}]` 149 /* 150 // SPDX-License-Identifier: GPL-3.0 151 pragma solidity >=0.7.0 <0.9.0; 152 153 contract Logger { 154 function log0() external { 155 assembly { 156 log0(0, 0) 157 } 158 } 159 160 function log1(uint t1) external { 161 assembly { 162 log1(0, 0, t1) 163 } 164 } 165 166 function log2(uint t1, uint t2) external { 167 assembly { 168 log2(0, 0, t1, t2) 169 } 170 } 171 172 function log3(uint t1, uint t2, uint t3) external { 173 assembly { 174 log3(0, 0, t1, t2, t3) 175 } 176 } 177 178 function log4(uint t1, uint t2, uint t3, uint t4) external { 179 assembly { 180 log4(0, 0, t1, t2, t3, t4) 181 } 182 } 183 } 184 */ 185 bytecode = common.FromHex("608060405234801561001057600080fd5b50600436106100575760003560e01c80630aa731851461005c5780632a4c08961461006657806378b9a1f314610082578063c670f8641461009e578063c683d6a3146100ba575b600080fd5b6100646100d6565b005b610080600480360381019061007b9190610143565b6100dc565b005b61009c60048036038101906100979190610196565b6100e8565b005b6100b860048036038101906100b391906101d6565b6100f2565b005b6100d460048036038101906100cf9190610203565b6100fa565b005b600080a0565b808284600080a3505050565b8082600080a25050565b80600080a150565b80828486600080a450505050565b600080fd5b6000819050919050565b6101208161010d565b811461012b57600080fd5b50565b60008135905061013d81610117565b92915050565b60008060006060848603121561015c5761015b610108565b5b600061016a8682870161012e565b935050602061017b8682870161012e565b925050604061018c8682870161012e565b9150509250925092565b600080604083850312156101ad576101ac610108565b5b60006101bb8582860161012e565b92505060206101cc8582860161012e565b9150509250929050565b6000602082840312156101ec576101eb610108565b5b60006101fa8482850161012e565b91505092915050565b6000806000806080858703121561021d5761021c610108565b5b600061022b8782880161012e565b945050602061023c8782880161012e565b935050604061024d8782880161012e565b925050606061025e8782880161012e565b9150509295919450925056fea264697066735822122073a4b156f487e59970dc1ef449cc0d51467268f676033a17188edafcee861f9864736f6c63430008110033") 186 187 hash1 = common.BytesToHash([]byte("topic1")) 188 hash2 = common.BytesToHash([]byte("topic2")) 189 hash3 = common.BytesToHash([]byte("topic3")) 190 hash4 = common.BytesToHash([]byte("topic4")) 191 hash5 = common.BytesToHash([]byte("topic5")) 192 193 gspec = &core.Genesis{ 194 Config: params.TestChainConfig, 195 Alloc: types.GenesisAlloc{ 196 addr: {Balance: big.NewInt(0).Mul(big.NewInt(100), big.NewInt(params.Ether))}, 197 contract: {Balance: big.NewInt(0), Code: bytecode}, 198 contract2: {Balance: big.NewInt(0), Code: bytecode}, 199 }, 200 BaseFee: big.NewInt(params.InitialBaseFee), 201 } 202 ) 203 204 contractABI, err := abi.JSON(strings.NewReader(abiStr)) 205 if err != nil { 206 t.Fatal(err) 207 } 208 209 // Hack: GenerateChainWithGenesis creates a new db. 210 // Commit the genesis manually and use GenerateChain. 211 _, err = gspec.Commit(db, triedb.NewDatabase(db, nil)) 212 if err != nil { 213 t.Fatal(err) 214 } 215 chain, _ := core.GenerateChain(gspec.Config, gspec.ToBlock(), ethash.NewFaker(), db, 1000, func(i int, gen *core.BlockGen) { 216 switch i { 217 case 1: 218 data, err := contractABI.Pack("log1", hash1.Big()) 219 if err != nil { 220 t.Fatal(err) 221 } 222 tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{ 223 Nonce: 0, 224 GasPrice: gen.BaseFee(), 225 Gas: 30000, 226 To: &contract, 227 Data: data, 228 }), signer, key1) 229 gen.AddTx(tx) 230 tx2, _ := types.SignTx(types.NewTx(&types.LegacyTx{ 231 Nonce: 1, 232 GasPrice: gen.BaseFee(), 233 Gas: 30000, 234 To: &contract2, 235 Data: data, 236 }), signer, key1) 237 gen.AddTx(tx2) 238 case 2: 239 data, err := contractABI.Pack("log2", hash2.Big(), hash1.Big()) 240 if err != nil { 241 t.Fatal(err) 242 } 243 tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{ 244 Nonce: 2, 245 GasPrice: gen.BaseFee(), 246 Gas: 30000, 247 To: &contract, 248 Data: data, 249 }), signer, key1) 250 gen.AddTx(tx) 251 case 998: 252 data, err := contractABI.Pack("log1", hash3.Big()) 253 if err != nil { 254 t.Fatal(err) 255 } 256 tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{ 257 Nonce: 3, 258 GasPrice: gen.BaseFee(), 259 Gas: 30000, 260 To: &contract2, 261 Data: data, 262 }), signer, key1) 263 gen.AddTx(tx) 264 case 999: 265 data, err := contractABI.Pack("log1", hash4.Big()) 266 if err != nil { 267 t.Fatal(err) 268 } 269 tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{ 270 Nonce: 4, 271 GasPrice: gen.BaseFee(), 272 Gas: 30000, 273 To: &contract, 274 Data: data, 275 }), signer, key1) 276 gen.AddTx(tx) 277 } 278 }) 279 options := core.DefaultConfig().WithStateScheme(rawdb.HashScheme) 280 options.TxLookupLimit = 0 // index all txs 281 bc, err := core.NewBlockChain(db, gspec, ethash.NewFaker(), options) 282 if err != nil { 283 t.Fatal(err) 284 } 285 _, err = bc.InsertChain(chain) 286 if err != nil { 287 t.Fatal(err) 288 } 289 290 // Set block 998 as Finalized (-3) 291 bc.SetFinalized(chain[998].Header()) 292 293 // Generate pending block 294 pchain, preceipts := core.GenerateChain(gspec.Config, chain[len(chain)-1], ethash.NewFaker(), db, 1, func(i int, gen *core.BlockGen) { 295 data, err := contractABI.Pack("log1", hash5.Big()) 296 if err != nil { 297 t.Fatal(err) 298 } 299 tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{ 300 Nonce: 5, 301 GasPrice: gen.BaseFee(), 302 Gas: 30000, 303 To: &contract, 304 Data: data, 305 }), signer, key1) 306 gen.AddTx(tx) 307 }) 308 backend.setPending(pchain[0], preceipts[0]) 309 310 backend.startFilterMaps(history, noHistory, filtermaps.DefaultParams) 311 defer backend.stopFilterMaps() 312 313 for i, tc := range []struct { 314 f *Filter 315 want string 316 err string 317 }{ 318 { 319 f: sys.NewBlockFilter(chain[2].Hash(), []common.Address{contract}, nil), 320 want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696332","0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x3","transactionHash":"0xdefe471992a07a02acdfbe33edaae22fbb86d7d3cec3f1b8e4e77702fb3acc1d","transactionIndex":"0x0","blockHash":"0x7a7556792ca7d37882882e2b001fe14833eaf81c2c7f865c9c771ec37a024f6b","blockTimestamp":"0x1e","logIndex":"0x0","removed":false}]`, 321 }, 322 { 323 f: sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), []common.Address{contract}, [][]common.Hash{{hash1, hash2, hash3, hash4}}), 324 want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x2","transactionHash":"0xa8028c655b6423204c8edfbc339f57b042d6bec2b6a61145d76b7c08b4cccd42","transactionIndex":"0x0","blockHash":"0x24417bb49ce44cfad65da68f33b510bf2a129c0d89ccf06acb6958b8585ccf34","blockTimestamp":"0x14","logIndex":"0x0","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696332","0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x3","transactionHash":"0xdefe471992a07a02acdfbe33edaae22fbb86d7d3cec3f1b8e4e77702fb3acc1d","transactionIndex":"0x0","blockHash":"0x7a7556792ca7d37882882e2b001fe14833eaf81c2c7f865c9c771ec37a024f6b","blockTimestamp":"0x1e","logIndex":"0x0","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696334"],"data":"0x","blockNumber":"0x3e8","transactionHash":"0x9a87842100a638dfa5da8842b4beda691d2fd77b0c84b57f24ecfa9fb208f747","transactionIndex":"0x0","blockHash":"0xb360bad5265261c075ece02d3bf0e39498a6a76310482cdfd90588748e6c5ee0","blockTimestamp":"0x2710","logIndex":"0x0","removed":false}]`, 325 }, 326 { 327 f: sys.NewRangeFilter(900, 999, []common.Address{contract}, [][]common.Hash{{hash3}}), 328 }, 329 { 330 f: sys.NewRangeFilter(990, int64(rpc.LatestBlockNumber), []common.Address{contract2}, [][]common.Hash{{hash3}}), 331 want: `[{"address":"0xff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696333"],"data":"0x","blockNumber":"0x3e7","transactionHash":"0x53e3675800c6908424b61b35a44e51ca4c73ca603e58a65b32c67968b4f42200","transactionIndex":"0x0","blockHash":"0x2e4620a2b426b0612ec6cad9603f466723edaed87f98c9137405dd4f7a2409ff","blockTimestamp":"0x2706","logIndex":"0x0","removed":false}]`, 332 }, 333 { 334 f: sys.NewRangeFilter(1, 10, []common.Address{contract}, [][]common.Hash{{hash2}, {hash1}}), 335 want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696332","0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x3","transactionHash":"0xdefe471992a07a02acdfbe33edaae22fbb86d7d3cec3f1b8e4e77702fb3acc1d","transactionIndex":"0x0","blockHash":"0x7a7556792ca7d37882882e2b001fe14833eaf81c2c7f865c9c771ec37a024f6b","blockTimestamp":"0x1e","logIndex":"0x0","removed":false}]`, 336 }, 337 { 338 f: sys.NewRangeFilter(1, 10, nil, [][]common.Hash{{hash1, hash2}}), 339 want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x2","transactionHash":"0xa8028c655b6423204c8edfbc339f57b042d6bec2b6a61145d76b7c08b4cccd42","transactionIndex":"0x0","blockHash":"0x24417bb49ce44cfad65da68f33b510bf2a129c0d89ccf06acb6958b8585ccf34","blockTimestamp":"0x14","logIndex":"0x0","removed":false},{"address":"0xff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x2","transactionHash":"0xdba3e2ea9a7d690b722d70ee605fd67ba4c00d1d3aecd5cf187a7b92ad8eb3df","transactionIndex":"0x1","blockHash":"0x24417bb49ce44cfad65da68f33b510bf2a129c0d89ccf06acb6958b8585ccf34","blockTimestamp":"0x14","logIndex":"0x1","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696332","0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x3","transactionHash":"0xdefe471992a07a02acdfbe33edaae22fbb86d7d3cec3f1b8e4e77702fb3acc1d","transactionIndex":"0x0","blockHash":"0x7a7556792ca7d37882882e2b001fe14833eaf81c2c7f865c9c771ec37a024f6b","blockTimestamp":"0x1e","logIndex":"0x0","removed":false}]`, 340 }, 341 { 342 f: sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), nil, [][]common.Hash{{common.BytesToHash([]byte("fail"))}}), 343 }, 344 { 345 f: sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), []common.Address{common.BytesToAddress([]byte("failmenow"))}, nil), 346 }, 347 { 348 f: sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), nil, [][]common.Hash{{common.BytesToHash([]byte("fail"))}, {hash1}}), 349 }, 350 { 351 f: sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.LatestBlockNumber), nil, nil), 352 want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696334"],"data":"0x","blockNumber":"0x3e8","transactionHash":"0x9a87842100a638dfa5da8842b4beda691d2fd77b0c84b57f24ecfa9fb208f747","transactionIndex":"0x0","blockHash":"0xb360bad5265261c075ece02d3bf0e39498a6a76310482cdfd90588748e6c5ee0","blockTimestamp":"0x2710","logIndex":"0x0","removed":false}]`, 353 }, 354 { 355 f: sys.NewRangeFilter(int64(rpc.FinalizedBlockNumber), int64(rpc.LatestBlockNumber), nil, nil), 356 want: `[{"address":"0xff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696333"],"data":"0x","blockNumber":"0x3e7","transactionHash":"0x53e3675800c6908424b61b35a44e51ca4c73ca603e58a65b32c67968b4f42200","transactionIndex":"0x0","blockHash":"0x2e4620a2b426b0612ec6cad9603f466723edaed87f98c9137405dd4f7a2409ff","blockTimestamp":"0x2706","logIndex":"0x0","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696334"],"data":"0x","blockNumber":"0x3e8","transactionHash":"0x9a87842100a638dfa5da8842b4beda691d2fd77b0c84b57f24ecfa9fb208f747","transactionIndex":"0x0","blockHash":"0xb360bad5265261c075ece02d3bf0e39498a6a76310482cdfd90588748e6c5ee0","blockTimestamp":"0x2710","logIndex":"0x0","removed":false}]`, 357 }, 358 { 359 f: sys.NewRangeFilter(int64(rpc.FinalizedBlockNumber), int64(rpc.FinalizedBlockNumber), nil, nil), 360 want: `[{"address":"0xff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696333"],"data":"0x","blockNumber":"0x3e7","transactionHash":"0x53e3675800c6908424b61b35a44e51ca4c73ca603e58a65b32c67968b4f42200","transactionIndex":"0x0","blockHash":"0x2e4620a2b426b0612ec6cad9603f466723edaed87f98c9137405dd4f7a2409ff","blockTimestamp":"0x2706","logIndex":"0x0","removed":false}]`, 361 }, 362 { 363 f: sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.FinalizedBlockNumber), nil, nil), 364 }, 365 { 366 f: sys.NewRangeFilter(int64(rpc.SafeBlockNumber), int64(rpc.LatestBlockNumber), nil, nil), 367 err: "safe header not found", 368 }, 369 { 370 f: sys.NewRangeFilter(int64(rpc.SafeBlockNumber), int64(rpc.SafeBlockNumber), nil, nil), 371 err: "safe header not found", 372 }, 373 { 374 f: sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.SafeBlockNumber), nil, nil), 375 err: "safe header not found", 376 }, 377 { 378 f: sys.NewRangeFilter(int64(rpc.PendingBlockNumber), int64(rpc.PendingBlockNumber), nil, nil), 379 err: errPendingLogsUnsupported.Error(), 380 }, 381 { 382 f: sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.PendingBlockNumber), nil, nil), 383 err: errPendingLogsUnsupported.Error(), 384 }, 385 { 386 f: sys.NewRangeFilter(int64(rpc.PendingBlockNumber), int64(rpc.LatestBlockNumber), nil, nil), 387 err: errPendingLogsUnsupported.Error(), 388 }, 389 } { 390 logs, err := tc.f.Logs(context.Background()) 391 if err == nil && tc.err != "" { 392 t.Fatalf("test %d, expected error %q, got nil", i, tc.err) 393 } else if err != nil && err.Error() != tc.err { 394 t.Fatalf("test %d, expected error %q, got %q", i, tc.err, err.Error()) 395 } 396 if tc.want == "" && len(logs) == 0 { 397 continue 398 } 399 have, err := json.Marshal(logs) 400 if err != nil { 401 t.Fatal(err) 402 } 403 if string(have) != tc.want { 404 t.Fatalf("test %d, have:\n%s\nwant:\n%s", i, have, tc.want) 405 } 406 } 407 408 t.Run("timeout", func(t *testing.T) { 409 f := sys.NewRangeFilter(0, rpc.LatestBlockNumber.Int64(), nil, nil) 410 ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(-time.Hour)) 411 defer cancel() 412 _, err := f.Logs(ctx) 413 if err == nil { 414 t.Fatal("expected error") 415 } 416 if err != context.DeadlineExceeded { 417 t.Fatalf("expected context.DeadlineExceeded, got %v", err) 418 } 419 }) 420 } 421 422 func TestRangeLogs(t *testing.T) { 423 var ( 424 db = rawdb.NewMemoryDatabase() 425 backend, sys = newTestFilterSystem(db, Config{}) 426 gspec = &core.Genesis{ 427 Config: params.TestChainConfig, 428 Alloc: types.GenesisAlloc{}, 429 BaseFee: big.NewInt(params.InitialBaseFee), 430 } 431 ) 432 _, err := gspec.Commit(db, triedb.NewDatabase(db, nil)) 433 if err != nil { 434 t.Fatal(err) 435 } 436 chain, _ := core.GenerateChain(gspec.Config, gspec.ToBlock(), ethash.NewFaker(), db, 1000, func(i int, gen *core.BlockGen) {}) 437 438 options := core.DefaultConfig().WithStateScheme(rawdb.HashScheme) 439 options.TxLookupLimit = 0 // index all txs 440 bc, err := core.NewBlockChain(db, gspec, ethash.NewFaker(), options) 441 if err != nil { 442 t.Fatal(err) 443 } 444 _, err = bc.InsertChain(chain[:600]) 445 if err != nil { 446 t.Fatal(err) 447 } 448 449 backend.startFilterMaps(200, false, filtermaps.RangeTestParams) 450 defer backend.stopFilterMaps() 451 452 var ( 453 testCase, event int 454 filter *Filter 455 addresses = []common.Address{{}} 456 ) 457 458 expEvent := func(expEvent int, expFirst, expAfterLast uint64) { 459 exp := rangeLogsTestEvent{expEvent, common.NewRange[uint64](expFirst, expAfterLast-expFirst)} 460 event++ 461 ev := <-filter.rangeLogsTestHook 462 if ev != exp { 463 t.Fatalf("Test case #%d: wrong test event #%d received (got %v, expected %v)", testCase, event, ev, exp) 464 } 465 } 466 467 newFilter := func(begin, end int64) { 468 testCase++ 469 event = 0 470 filter = sys.NewRangeFilter(begin, end, addresses, nil) 471 filter.rangeLogsTestHook = make(chan rangeLogsTestEvent) 472 go func(filter *Filter) { 473 filter.Logs(context.Background()) 474 // ensure that filter will not be blocked if we exit early 475 for range filter.rangeLogsTestHook { 476 } 477 }(filter) 478 } 479 480 updateHead := func() { 481 head := bc.CurrentBlock() 482 backend.fm.SetTarget(filtermaps.NewChainView(backend, head.Number.Uint64(), head.Hash()), 0, 0) 483 backend.fm.WaitIdle() 484 } 485 486 // test case #1 487 newFilter(300, 500) 488 expEvent(rangeLogsTestIndexed, 401, 501) 489 expEvent(rangeLogsTestSync, 0, 0) 490 expEvent(rangeLogsTestSynced, 401, 601) 491 expEvent(rangeLogsTestResults, 401, 501) 492 expEvent(rangeLogsTestUnindexed, 300, 401) 493 if _, err := bc.InsertChain(chain[600:700]); err != nil { 494 t.Fatal(err) 495 } 496 updateHead() 497 expEvent(rangeLogsTestResults, 300, 501) 498 expEvent(rangeLogsTestDone, 0, 0) 499 500 // test case #2 501 newFilter(400, int64(rpc.LatestBlockNumber)) 502 expEvent(rangeLogsTestIndexed, 501, 701) 503 if _, err := bc.InsertChain(chain[700:800]); err != nil { 504 t.Fatal(err) 505 } 506 updateHead() 507 expEvent(rangeLogsTestSync, 0, 0) 508 expEvent(rangeLogsTestSynced, 601, 699) 509 expEvent(rangeLogsTestResults, 601, 699) 510 expEvent(rangeLogsTestUnindexed, 400, 601) 511 expEvent(rangeLogsTestResults, 400, 699) 512 expEvent(rangeLogsTestIndexed, 699, 801) 513 if _, err := bc.SetCanonical(chain[749]); err != nil { // set head to block 750 514 t.Fatal(err) 515 } 516 updateHead() 517 expEvent(rangeLogsTestSync, 0, 0) 518 expEvent(rangeLogsTestSynced, 601, 749) 519 expEvent(rangeLogsTestResults, 400, 749) 520 expEvent(rangeLogsTestIndexed, 749, 751) 521 expEvent(rangeLogsTestSync, 0, 0) 522 expEvent(rangeLogsTestSynced, 551, 751) 523 expEvent(rangeLogsTestResults, 400, 751) 524 expEvent(rangeLogsTestDone, 0, 0) 525 526 // test case #3 527 newFilter(int64(rpc.LatestBlockNumber), int64(rpc.LatestBlockNumber)) 528 expEvent(rangeLogsTestIndexed, 750, 751) 529 if _, err := bc.SetCanonical(chain[739]); err != nil { 530 t.Fatal(err) 531 } 532 updateHead() 533 expEvent(rangeLogsTestSync, 0, 0) 534 expEvent(rangeLogsTestSynced, 551, 739) 535 expEvent(rangeLogsTestResults, 0, 0) 536 expEvent(rangeLogsTestIndexed, 740, 741) 537 if _, err := bc.InsertChain(chain[740:750]); err != nil { 538 t.Fatal(err) 539 } 540 updateHead() 541 expEvent(rangeLogsTestSync, 0, 0) 542 expEvent(rangeLogsTestSynced, 551, 739) 543 expEvent(rangeLogsTestResults, 0, 0) 544 expEvent(rangeLogsTestIndexed, 750, 751) 545 expEvent(rangeLogsTestSync, 0, 0) 546 expEvent(rangeLogsTestSynced, 551, 751) 547 expEvent(rangeLogsTestResults, 750, 751) 548 expEvent(rangeLogsTestDone, 0, 0) 549 550 // test case #4 551 if _, err := bc.SetCanonical(chain[499]); err != nil { 552 t.Fatal(err) 553 } 554 updateHead() 555 newFilter(400, int64(rpc.LatestBlockNumber)) 556 expEvent(rangeLogsTestIndexed, 400, 501) 557 if _, err := bc.InsertChain(chain[500:650]); err != nil { 558 t.Fatal(err) 559 } 560 updateHead() 561 expEvent(rangeLogsTestSync, 0, 0) 562 expEvent(rangeLogsTestSynced, 451, 499) 563 expEvent(rangeLogsTestResults, 451, 499) 564 expEvent(rangeLogsTestUnindexed, 400, 451) 565 expEvent(rangeLogsTestResults, 400, 499) 566 // indexed head extension seems possible 567 expEvent(rangeLogsTestIndexed, 499, 651) 568 // further head extension causes tail unindexing in searched range 569 if _, err := bc.InsertChain(chain[650:750]); err != nil { 570 t.Fatal(err) 571 } 572 updateHead() 573 expEvent(rangeLogsTestSync, 0, 0) 574 expEvent(rangeLogsTestSynced, 551, 649) 575 // tail trimmed to 551; cannot merge with existing results 576 expEvent(rangeLogsTestResults, 551, 649) 577 expEvent(rangeLogsTestUnindexed, 400, 551) 578 expEvent(rangeLogsTestResults, 400, 649) 579 expEvent(rangeLogsTestIndexed, 649, 751) 580 expEvent(rangeLogsTestSync, 0, 0) 581 expEvent(rangeLogsTestSynced, 551, 751) 582 expEvent(rangeLogsTestResults, 400, 751) 583 expEvent(rangeLogsTestDone, 0, 0) 584 585 // test case #5 586 newFilter(400, int64(rpc.LatestBlockNumber)) 587 expEvent(rangeLogsTestIndexed, 551, 751) 588 expEvent(rangeLogsTestSync, 0, 0) 589 expEvent(rangeLogsTestSynced, 551, 751) 590 expEvent(rangeLogsTestResults, 551, 751) 591 expEvent(rangeLogsTestUnindexed, 400, 551) 592 if _, err := bc.InsertChain(chain[750:1000]); err != nil { 593 t.Fatal(err) 594 } 595 updateHead() 596 expEvent(rangeLogsTestResults, 400, 751) 597 // indexed tail already beyond results head; revert to unindexed head search 598 expEvent(rangeLogsTestUnindexed, 751, 1001) 599 if _, err := bc.SetCanonical(chain[899]); err != nil { 600 t.Fatal(err) 601 } 602 updateHead() 603 expEvent(rangeLogsTestResults, 400, 1001) 604 expEvent(rangeLogsTestReorg, 400, 901) 605 expEvent(rangeLogsTestDone, 0, 0) 606 }