github.com/neatio-net/neatio@v1.7.3-0.20231114194659-f4d7a2226baa/neatptc/downloader/downloader_test.go (about) 1 package downloader 2 3 import ( 4 "errors" 5 "fmt" 6 "math/big" 7 "sync" 8 "testing" 9 "time" 10 11 "github.com/neatio-net/neatio/chain/core" 12 "github.com/neatio-net/neatio/chain/core/rawdb" 13 "github.com/neatio-net/neatio/chain/core/types" 14 "github.com/neatio-net/neatio/chain/trie" 15 "github.com/neatio-net/neatio/neatdb" 16 "github.com/neatio-net/neatio/params" 17 "github.com/neatio-net/neatio/utilities/common" 18 "github.com/neatio-net/neatio/utilities/crypto" 19 "github.com/neatio-net/neatio/utilities/event" 20 ) 21 22 var ( 23 testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 24 testAddress = crypto.PubkeyToAddress(testKey.PublicKey) 25 ) 26 27 func init() { 28 MaxForkAncestry = uint64(10000) 29 blockCacheItems = 1024 30 fsHeaderContCheck = 500 * time.Millisecond 31 } 32 33 type downloadTester struct { 34 downloader *Downloader 35 36 genesis *types.Block 37 stateDb neatdb.Database 38 peerDb neatdb.Database 39 40 ownHashes []common.Hash 41 ownHeaders map[common.Hash]*types.Header 42 ownBlocks map[common.Hash]*types.Block 43 ownReceipts map[common.Hash]types.Receipts 44 ownChainTd map[common.Hash]*big.Int 45 46 peerHashes map[string][]common.Hash 47 peerHeaders map[string]map[common.Hash]*types.Header 48 peerBlocks map[string]map[common.Hash]*types.Block 49 peerReceipts map[string]map[common.Hash]types.Receipts 50 peerChainTds map[string]map[common.Hash]*big.Int 51 52 peerMissingStates map[string]map[common.Hash]bool 53 54 lock sync.RWMutex 55 } 56 57 func newTester() *downloadTester { 58 testdb := rawdb.NewMemoryDatabase() 59 genesis := core.GenesisBlockForTesting(testdb, testAddress, big.NewInt(1000000000)) 60 61 tester := &downloadTester{ 62 genesis: genesis, 63 peerDb: testdb, 64 ownHashes: []common.Hash{genesis.Hash()}, 65 ownHeaders: map[common.Hash]*types.Header{genesis.Hash(): genesis.Header()}, 66 ownBlocks: map[common.Hash]*types.Block{genesis.Hash(): genesis}, 67 ownReceipts: map[common.Hash]types.Receipts{genesis.Hash(): nil}, 68 ownChainTd: map[common.Hash]*big.Int{genesis.Hash(): genesis.Difficulty()}, 69 peerHashes: make(map[string][]common.Hash), 70 peerHeaders: make(map[string]map[common.Hash]*types.Header), 71 peerBlocks: make(map[string]map[common.Hash]*types.Block), 72 peerReceipts: make(map[string]map[common.Hash]types.Receipts), 73 peerChainTds: make(map[string]map[common.Hash]*big.Int), 74 peerMissingStates: make(map[string]map[common.Hash]bool), 75 } 76 tester.stateDb = rawdb.NewMemoryDatabase() 77 tester.stateDb.Put(genesis.Root().Bytes(), []byte{0x00}) 78 79 tester.downloader = New(FullSync, tester.stateDb, new(event.TypeMux), tester, nil, tester.dropPeer, nil) 80 81 return tester 82 } 83 84 func (dl *downloadTester) makeChain(n int, seed byte, parent *types.Block, parentReceipts types.Receipts, heavy bool) ([]common.Hash, map[common.Hash]*types.Header, map[common.Hash]*types.Block, map[common.Hash]types.Receipts) { 85 86 blocks, receipts := core.GenerateChain(params.TestChainConfig, parent, nil, dl.peerDb, n, func(i int, block *core.BlockGen) { 87 block.SetCoinbase(common.Address{seed}) 88 89 if heavy { 90 block.OffsetTime(-1) 91 } 92 93 if parent == dl.genesis && i%3 == 0 { 94 signer := types.MakeSigner(params.TestChainConfig, block.Number()) 95 tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), params.TxGas, nil, nil), signer, testKey) 96 if err != nil { 97 panic(err) 98 } 99 block.AddTx(tx) 100 } 101 102 if i > 0 && i%5 == 0 { 103 block.AddUncle(&types.Header{ 104 ParentHash: block.PrevBlock(i - 1).Hash(), 105 Number: big.NewInt(block.Number().Int64() - 1), 106 }) 107 } 108 }) 109 110 hashes := make([]common.Hash, n+1) 111 hashes[len(hashes)-1] = parent.Hash() 112 113 headerm := make(map[common.Hash]*types.Header, n+1) 114 headerm[parent.Hash()] = parent.Header() 115 116 blockm := make(map[common.Hash]*types.Block, n+1) 117 blockm[parent.Hash()] = parent 118 119 receiptm := make(map[common.Hash]types.Receipts, n+1) 120 receiptm[parent.Hash()] = parentReceipts 121 122 for i, b := range blocks { 123 hashes[len(hashes)-i-2] = b.Hash() 124 headerm[b.Hash()] = b.Header() 125 blockm[b.Hash()] = b 126 receiptm[b.Hash()] = receipts[i] 127 } 128 return hashes, headerm, blockm, receiptm 129 } 130 131 func (dl *downloadTester) makeChainFork(n, f int, parent *types.Block, parentReceipts types.Receipts, balanced bool) ([]common.Hash, []common.Hash, map[common.Hash]*types.Header, map[common.Hash]*types.Header, map[common.Hash]*types.Block, map[common.Hash]*types.Block, map[common.Hash]types.Receipts, map[common.Hash]types.Receipts) { 132 133 hashes, headers, blocks, receipts := dl.makeChain(n-f, 0, parent, parentReceipts, false) 134 135 hashes1, headers1, blocks1, receipts1 := dl.makeChain(f, 1, blocks[hashes[0]], receipts[hashes[0]], false) 136 hashes1 = append(hashes1, hashes[1:]...) 137 138 heavy := false 139 if !balanced { 140 heavy = true 141 } 142 hashes2, headers2, blocks2, receipts2 := dl.makeChain(f, 2, blocks[hashes[0]], receipts[hashes[0]], heavy) 143 hashes2 = append(hashes2, hashes[1:]...) 144 145 for hash, header := range headers { 146 headers1[hash] = header 147 headers2[hash] = header 148 } 149 for hash, block := range blocks { 150 blocks1[hash] = block 151 blocks2[hash] = block 152 } 153 for hash, receipt := range receipts { 154 receipts1[hash] = receipt 155 receipts2[hash] = receipt 156 } 157 return hashes1, hashes2, headers1, headers2, blocks1, blocks2, receipts1, receipts2 158 } 159 160 func (dl *downloadTester) terminate() { 161 dl.downloader.Terminate() 162 } 163 164 func (dl *downloadTester) sync(id string, td *big.Int, mode SyncMode) error { 165 dl.lock.RLock() 166 hash := dl.peerHashes[id][0] 167 168 if td == nil { 169 td = big.NewInt(1) 170 if diff, ok := dl.peerChainTds[id][hash]; ok { 171 td = diff 172 } 173 } 174 dl.lock.RUnlock() 175 176 err := dl.downloader.synchronise(id, hash, td, mode) 177 select { 178 case <-dl.downloader.cancelCh: 179 180 default: 181 182 panic("downloader active post sync cycle") 183 } 184 return err 185 } 186 187 func (dl *downloadTester) HasHeader(hash common.Hash, number uint64) bool { 188 return dl.GetHeaderByHash(hash) != nil 189 } 190 191 func (dl *downloadTester) HasBlock(hash common.Hash, number uint64) bool { 192 return dl.GetBlockByHash(hash) != nil 193 } 194 195 func (dl *downloadTester) GetHeaderByHash(hash common.Hash) *types.Header { 196 dl.lock.RLock() 197 defer dl.lock.RUnlock() 198 199 return dl.ownHeaders[hash] 200 } 201 202 func (dl *downloadTester) GetBlockByHash(hash common.Hash) *types.Block { 203 dl.lock.RLock() 204 defer dl.lock.RUnlock() 205 206 return dl.ownBlocks[hash] 207 } 208 209 func (dl *downloadTester) CurrentHeader() *types.Header { 210 dl.lock.RLock() 211 defer dl.lock.RUnlock() 212 213 for i := len(dl.ownHashes) - 1; i >= 0; i-- { 214 if header := dl.ownHeaders[dl.ownHashes[i]]; header != nil { 215 return header 216 } 217 } 218 return dl.genesis.Header() 219 } 220 221 func (dl *downloadTester) CurrentBlock() *types.Block { 222 dl.lock.RLock() 223 defer dl.lock.RUnlock() 224 225 for i := len(dl.ownHashes) - 1; i >= 0; i-- { 226 if block := dl.ownBlocks[dl.ownHashes[i]]; block != nil { 227 if _, err := dl.stateDb.Get(block.Root().Bytes()); err == nil { 228 return block 229 } 230 } 231 } 232 return dl.genesis 233 } 234 235 func (dl *downloadTester) CurrentFastBlock() *types.Block { 236 dl.lock.RLock() 237 defer dl.lock.RUnlock() 238 239 for i := len(dl.ownHashes) - 1; i >= 0; i-- { 240 if block := dl.ownBlocks[dl.ownHashes[i]]; block != nil { 241 return block 242 } 243 } 244 return dl.genesis 245 } 246 247 func (dl *downloadTester) FastSyncCommitHead(hash common.Hash) error { 248 249 if block := dl.GetBlockByHash(hash); block != nil { 250 _, err := trie.NewSecure(block.Root(), trie.NewDatabase(dl.stateDb)) 251 return err 252 } 253 return fmt.Errorf("non existent block: %x", hash[:4]) 254 } 255 256 func (dl *downloadTester) GetTd(hash common.Hash, number uint64) *big.Int { 257 dl.lock.RLock() 258 defer dl.lock.RUnlock() 259 260 return dl.ownChainTd[hash] 261 } 262 263 func (dl *downloadTester) InsertHeaderChain(headers []*types.Header, checkFreq int) (int, error) { 264 dl.lock.Lock() 265 defer dl.lock.Unlock() 266 267 if _, ok := dl.ownHeaders[headers[0].ParentHash]; !ok { 268 return 0, errors.New("unknown parent") 269 } 270 for i := 1; i < len(headers); i++ { 271 if headers[i].ParentHash != headers[i-1].Hash() { 272 return i, errors.New("unknown parent") 273 } 274 } 275 276 for i, header := range headers { 277 if _, ok := dl.ownHeaders[header.Hash()]; ok { 278 continue 279 } 280 if _, ok := dl.ownHeaders[header.ParentHash]; !ok { 281 return i, errors.New("unknown parent") 282 } 283 dl.ownHashes = append(dl.ownHashes, header.Hash()) 284 dl.ownHeaders[header.Hash()] = header 285 dl.ownChainTd[header.Hash()] = new(big.Int).Add(dl.ownChainTd[header.ParentHash], header.Difficulty) 286 } 287 return len(headers), nil 288 } 289 290 func (dl *downloadTester) InsertChain(blocks types.Blocks) (int, error) { 291 dl.lock.Lock() 292 defer dl.lock.Unlock() 293 294 for i, block := range blocks { 295 if parent, ok := dl.ownBlocks[block.ParentHash()]; !ok { 296 return i, errors.New("unknown parent") 297 } else if _, err := dl.stateDb.Get(parent.Root().Bytes()); err != nil { 298 return i, fmt.Errorf("unknown parent state %x: %v", parent.Root(), err) 299 } 300 if _, ok := dl.ownHeaders[block.Hash()]; !ok { 301 dl.ownHashes = append(dl.ownHashes, block.Hash()) 302 dl.ownHeaders[block.Hash()] = block.Header() 303 } 304 dl.ownBlocks[block.Hash()] = block 305 dl.stateDb.Put(block.Root().Bytes(), []byte{0x00}) 306 dl.ownChainTd[block.Hash()] = new(big.Int).Add(dl.ownChainTd[block.ParentHash()], block.Difficulty()) 307 } 308 return len(blocks), nil 309 } 310 311 func (dl *downloadTester) InsertReceiptChain(blocks types.Blocks, receipts []types.Receipts) (int, error) { 312 dl.lock.Lock() 313 defer dl.lock.Unlock() 314 315 for i := 0; i < len(blocks) && i < len(receipts); i++ { 316 if _, ok := dl.ownHeaders[blocks[i].Hash()]; !ok { 317 return i, errors.New("unknown owner") 318 } 319 if _, ok := dl.ownBlocks[blocks[i].ParentHash()]; !ok { 320 return i, errors.New("unknown parent") 321 } 322 dl.ownBlocks[blocks[i].Hash()] = blocks[i] 323 dl.ownReceipts[blocks[i].Hash()] = receipts[i] 324 } 325 return len(blocks), nil 326 } 327 328 func (dl *downloadTester) Rollback(hashes []common.Hash) { 329 dl.lock.Lock() 330 defer dl.lock.Unlock() 331 332 for i := len(hashes) - 1; i >= 0; i-- { 333 if dl.ownHashes[len(dl.ownHashes)-1] == hashes[i] { 334 dl.ownHashes = dl.ownHashes[:len(dl.ownHashes)-1] 335 } 336 delete(dl.ownChainTd, hashes[i]) 337 delete(dl.ownHeaders, hashes[i]) 338 delete(dl.ownReceipts, hashes[i]) 339 delete(dl.ownBlocks, hashes[i]) 340 } 341 } 342 343 func (dl *downloadTester) newPeer(id string, version int, hashes []common.Hash, headers map[common.Hash]*types.Header, blocks map[common.Hash]*types.Block, receipts map[common.Hash]types.Receipts) error { 344 return dl.newSlowPeer(id, version, hashes, headers, blocks, receipts, 0) 345 } 346 347 func (dl *downloadTester) newSlowPeer(id string, version int, hashes []common.Hash, headers map[common.Hash]*types.Header, blocks map[common.Hash]*types.Block, receipts map[common.Hash]types.Receipts, delay time.Duration) error { 348 dl.lock.Lock() 349 defer dl.lock.Unlock() 350 351 var err = dl.downloader.RegisterPeer(id, version, &downloadTesterPeer{dl: dl, id: id, delay: delay}) 352 if err == nil { 353 354 dl.peerHashes[id] = make([]common.Hash, len(hashes)) 355 copy(dl.peerHashes[id], hashes) 356 357 dl.peerHeaders[id] = make(map[common.Hash]*types.Header) 358 dl.peerBlocks[id] = make(map[common.Hash]*types.Block) 359 dl.peerReceipts[id] = make(map[common.Hash]types.Receipts) 360 dl.peerChainTds[id] = make(map[common.Hash]*big.Int) 361 dl.peerMissingStates[id] = make(map[common.Hash]bool) 362 363 genesis := hashes[len(hashes)-1] 364 if header := headers[genesis]; header != nil { 365 dl.peerHeaders[id][genesis] = header 366 dl.peerChainTds[id][genesis] = header.Difficulty 367 } 368 if block := blocks[genesis]; block != nil { 369 dl.peerBlocks[id][genesis] = block 370 dl.peerChainTds[id][genesis] = block.Difficulty() 371 } 372 373 for i := len(hashes) - 2; i >= 0; i-- { 374 hash := hashes[i] 375 376 if header, ok := headers[hash]; ok { 377 dl.peerHeaders[id][hash] = header 378 if _, ok := dl.peerHeaders[id][header.ParentHash]; ok { 379 dl.peerChainTds[id][hash] = new(big.Int).Add(header.Difficulty, dl.peerChainTds[id][header.ParentHash]) 380 } 381 } 382 if block, ok := blocks[hash]; ok { 383 dl.peerBlocks[id][hash] = block 384 if _, ok := dl.peerBlocks[id][block.ParentHash()]; ok { 385 dl.peerChainTds[id][hash] = new(big.Int).Add(block.Difficulty(), dl.peerChainTds[id][block.ParentHash()]) 386 } 387 } 388 if receipt, ok := receipts[hash]; ok { 389 dl.peerReceipts[id][hash] = receipt 390 } 391 } 392 } 393 return err 394 } 395 396 func (dl *downloadTester) dropPeer(id string) { 397 dl.lock.Lock() 398 defer dl.lock.Unlock() 399 400 delete(dl.peerHashes, id) 401 delete(dl.peerHeaders, id) 402 delete(dl.peerBlocks, id) 403 delete(dl.peerChainTds, id) 404 405 dl.downloader.UnregisterPeer(id) 406 } 407 408 type downloadTesterPeer struct { 409 dl *downloadTester 410 id string 411 delay time.Duration 412 lock sync.RWMutex 413 } 414 415 func (dlp *downloadTesterPeer) setDelay(delay time.Duration) { 416 dlp.lock.Lock() 417 defer dlp.lock.Unlock() 418 419 dlp.delay = delay 420 } 421 422 func (dlp *downloadTesterPeer) waitDelay() { 423 dlp.lock.RLock() 424 delay := dlp.delay 425 dlp.lock.RUnlock() 426 427 time.Sleep(delay) 428 } 429 430 func (dlp *downloadTesterPeer) Head() (common.Hash, *big.Int) { 431 dlp.dl.lock.RLock() 432 defer dlp.dl.lock.RUnlock() 433 434 return dlp.dl.peerHashes[dlp.id][0], nil 435 } 436 437 func (dlp *downloadTesterPeer) RequestHeadersByHash(origin common.Hash, amount int, skip int, reverse bool) error { 438 439 dlp.dl.lock.RLock() 440 number := uint64(0) 441 for num, hash := range dlp.dl.peerHashes[dlp.id] { 442 if hash == origin { 443 number = uint64(len(dlp.dl.peerHashes[dlp.id]) - num - 1) 444 break 445 } 446 } 447 dlp.dl.lock.RUnlock() 448 449 return dlp.RequestHeadersByNumber(number, amount, skip, reverse) 450 } 451 452 func (dlp *downloadTesterPeer) RequestHeadersByNumber(origin uint64, amount int, skip int, reverse bool) error { 453 dlp.waitDelay() 454 455 dlp.dl.lock.RLock() 456 defer dlp.dl.lock.RUnlock() 457 458 hashes := dlp.dl.peerHashes[dlp.id] 459 headers := dlp.dl.peerHeaders[dlp.id] 460 result := make([]*types.Header, 0, amount) 461 for i := 0; i < amount && len(hashes)-int(origin)-1-i*(skip+1) >= 0; i++ { 462 if header, ok := headers[hashes[len(hashes)-int(origin)-1-i*(skip+1)]]; ok { 463 result = append(result, header) 464 } 465 } 466 467 go func() { 468 time.Sleep(time.Millisecond) 469 dlp.dl.downloader.DeliverHeaders(dlp.id, result) 470 }() 471 return nil 472 } 473 474 func (dlp *downloadTesterPeer) RequestBodies(hashes []common.Hash) error { 475 dlp.waitDelay() 476 477 dlp.dl.lock.RLock() 478 defer dlp.dl.lock.RUnlock() 479 480 blocks := dlp.dl.peerBlocks[dlp.id] 481 482 transactions := make([][]*types.Transaction, 0, len(hashes)) 483 uncles := make([][]*types.Header, 0, len(hashes)) 484 485 for _, hash := range hashes { 486 if block, ok := blocks[hash]; ok { 487 transactions = append(transactions, block.Transactions()) 488 uncles = append(uncles, block.Uncles()) 489 } 490 } 491 go dlp.dl.downloader.DeliverBodies(dlp.id, transactions, uncles) 492 493 return nil 494 } 495 496 func (dlp *downloadTesterPeer) RequestReceipts(hashes []common.Hash) error { 497 dlp.waitDelay() 498 499 dlp.dl.lock.RLock() 500 defer dlp.dl.lock.RUnlock() 501 502 receipts := dlp.dl.peerReceipts[dlp.id] 503 504 results := make([][]*types.Receipt, 0, len(hashes)) 505 for _, hash := range hashes { 506 if receipt, ok := receipts[hash]; ok { 507 results = append(results, receipt) 508 } 509 } 510 go dlp.dl.downloader.DeliverReceipts(dlp.id, results) 511 512 return nil 513 } 514 515 func (dlp *downloadTesterPeer) RequestNodeData(hashes []common.Hash) error { 516 dlp.waitDelay() 517 518 dlp.dl.lock.RLock() 519 defer dlp.dl.lock.RUnlock() 520 521 results := make([][]byte, 0, len(hashes)) 522 for _, hash := range hashes { 523 if data, err := dlp.dl.peerDb.Get(hash.Bytes()); err == nil { 524 if !dlp.dl.peerMissingStates[dlp.id][hash] { 525 results = append(results, data) 526 } 527 } 528 } 529 go dlp.dl.downloader.DeliverNodeData(dlp.id, results) 530 531 return nil 532 } 533 534 func assertOwnChain(t *testing.T, tester *downloadTester, length int) { 535 assertOwnForkedChain(t, tester, 1, []int{length}) 536 } 537 538 func assertOwnForkedChain(t *testing.T, tester *downloadTester, common int, lengths []int) { 539 540 headers, blocks, receipts := lengths[0], lengths[0], lengths[0]-fsMinFullBlocks 541 542 if receipts < 0 { 543 receipts = 1 544 } 545 546 for _, length := range lengths[1:] { 547 headers += length - common 548 blocks += length - common 549 receipts += length - common - fsMinFullBlocks 550 } 551 switch tester.downloader.mode { 552 case FullSync: 553 receipts = 1 554 if hs := len(tester.ownHeaders); hs != headers { 555 t.Fatalf("synchronised headers mismatch: have %v, want %v", hs, headers) 556 } 557 if bs := len(tester.ownBlocks); bs != blocks { 558 t.Fatalf("synchronised blocks mismatch: have %v, want %v", bs, blocks) 559 } 560 if rs := len(tester.ownReceipts); rs != receipts { 561 t.Fatalf("synchronised receipts mismatch: have %v, want %v", rs, receipts) 562 } 563 564 } 565 }