github.com/nitinawathare/ethereumassignment3@v0.0.0-20211021213010-f07344c2b868/go-ethereum/les/fetcher.go (about) 1 // Copyright 2016 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 les 18 19 import ( 20 "math/big" 21 "sync" 22 "time" 23 24 "github.com/ethereum/go-ethereum/common" 25 "github.com/ethereum/go-ethereum/common/mclock" 26 "github.com/ethereum/go-ethereum/consensus" 27 "github.com/ethereum/go-ethereum/core/rawdb" 28 "github.com/ethereum/go-ethereum/core/types" 29 "github.com/ethereum/go-ethereum/light" 30 "github.com/ethereum/go-ethereum/log" 31 ) 32 33 const ( 34 blockDelayTimeout = time.Second * 10 // timeout for a peer to announce a head that has already been confirmed by others 35 maxNodeCount = 20 // maximum number of fetcherTreeNode entries remembered for each peer 36 serverStateAvailable = 100 // number of recent blocks where state availability is assumed 37 ) 38 39 // lightFetcher implements retrieval of newly announced headers. It also provides a peerHasBlock function for the 40 // ODR system to ensure that we only request data related to a certain block from peers who have already processed 41 // and announced that block. 42 type lightFetcher struct { 43 pm *ProtocolManager 44 odr *LesOdr 45 chain lightChain 46 47 lock sync.Mutex // lock protects access to the fetcher's internal state variables except sent requests 48 maxConfirmedTd *big.Int 49 peers map[*peer]*fetcherPeerInfo 50 lastUpdateStats *updateStatsEntry 51 syncing bool 52 syncDone chan *peer 53 54 reqMu sync.RWMutex // reqMu protects access to sent header fetch requests 55 requested map[uint64]fetchRequest 56 deliverChn chan fetchResponse 57 timeoutChn chan uint64 58 requestChn chan bool // true if initiated from outside 59 lastTrustedHeader *types.Header 60 } 61 62 // lightChain extends the BlockChain interface by locking. 63 type lightChain interface { 64 BlockChain 65 LockChain() 66 UnlockChain() 67 } 68 69 // fetcherPeerInfo holds fetcher-specific information about each active peer 70 type fetcherPeerInfo struct { 71 root, lastAnnounced *fetcherTreeNode 72 nodeCnt int 73 confirmedTd *big.Int 74 bestConfirmed *fetcherTreeNode 75 nodeByHash map[common.Hash]*fetcherTreeNode 76 firstUpdateStats *updateStatsEntry 77 } 78 79 // fetcherTreeNode is a node of a tree that holds information about blocks recently 80 // announced and confirmed by a certain peer. Each new announce message from a peer 81 // adds nodes to the tree, based on the previous announced head and the reorg depth. 82 // There are three possible states for a tree node: 83 // - announced: not downloaded (known) yet, but we know its head, number and td 84 // - intermediate: not known, hash and td are empty, they are filled out when it becomes known 85 // - known: both announced by this peer and downloaded (from any peer). 86 // This structure makes it possible to always know which peer has a certain block, 87 // which is necessary for selecting a suitable peer for ODR requests and also for 88 // canonizing new heads. It also helps to always download the minimum necessary 89 // amount of headers with a single request. 90 type fetcherTreeNode struct { 91 hash common.Hash 92 number uint64 93 td *big.Int 94 known, requested bool 95 parent *fetcherTreeNode 96 children []*fetcherTreeNode 97 } 98 99 // fetchRequest represents a header download request 100 type fetchRequest struct { 101 hash common.Hash 102 amount uint64 103 peer *peer 104 sent mclock.AbsTime 105 timeout bool 106 } 107 108 // fetchResponse represents a header download response 109 type fetchResponse struct { 110 reqID uint64 111 headers []*types.Header 112 peer *peer 113 } 114 115 // newLightFetcher creates a new light fetcher 116 func newLightFetcher(pm *ProtocolManager) *lightFetcher { 117 f := &lightFetcher{ 118 pm: pm, 119 chain: pm.blockchain.(*light.LightChain), 120 odr: pm.odr, 121 peers: make(map[*peer]*fetcherPeerInfo), 122 deliverChn: make(chan fetchResponse, 100), 123 requested: make(map[uint64]fetchRequest), 124 timeoutChn: make(chan uint64), 125 requestChn: make(chan bool, 100), 126 syncDone: make(chan *peer), 127 maxConfirmedTd: big.NewInt(0), 128 } 129 pm.peers.notify(f) 130 131 f.pm.wg.Add(1) 132 go f.syncLoop() 133 return f 134 } 135 136 // syncLoop is the main event loop of the light fetcher 137 func (f *lightFetcher) syncLoop() { 138 requesting := false 139 defer f.pm.wg.Done() 140 for { 141 select { 142 case <-f.pm.quitSync: 143 return 144 // when a new announce is received, request loop keeps running until 145 // no further requests are necessary or possible 146 case newAnnounce := <-f.requestChn: 147 f.lock.Lock() 148 s := requesting 149 requesting = false 150 var ( 151 rq *distReq 152 reqID uint64 153 syncing bool 154 ) 155 156 if !f.syncing && !(newAnnounce && s) { 157 rq, reqID, syncing = f.nextRequest() 158 } 159 f.lock.Unlock() 160 161 if rq != nil { 162 requesting = true 163 if _, ok := <-f.pm.reqDist.queue(rq); ok { 164 if syncing { 165 f.lock.Lock() 166 f.syncing = true 167 f.lock.Unlock() 168 } else { 169 go func() { 170 time.Sleep(softRequestTimeout) 171 f.reqMu.Lock() 172 req, ok := f.requested[reqID] 173 if ok { 174 req.timeout = true 175 f.requested[reqID] = req 176 } 177 f.reqMu.Unlock() 178 // keep starting new requests while possible 179 f.requestChn <- false 180 }() 181 } 182 } else { 183 f.requestChn <- false 184 } 185 } 186 case reqID := <-f.timeoutChn: 187 f.reqMu.Lock() 188 req, ok := f.requested[reqID] 189 if ok { 190 delete(f.requested, reqID) 191 } 192 f.reqMu.Unlock() 193 if ok { 194 f.pm.serverPool.adjustResponseTime(req.peer.poolEntry, time.Duration(mclock.Now()-req.sent), true) 195 req.peer.Log().Debug("Fetching data timed out hard") 196 go f.pm.removePeer(req.peer.id) 197 } 198 case resp := <-f.deliverChn: 199 f.reqMu.Lock() 200 req, ok := f.requested[resp.reqID] 201 if ok && req.peer != resp.peer { 202 ok = false 203 } 204 if ok { 205 delete(f.requested, resp.reqID) 206 } 207 f.reqMu.Unlock() 208 if ok { 209 f.pm.serverPool.adjustResponseTime(req.peer.poolEntry, time.Duration(mclock.Now()-req.sent), req.timeout) 210 } 211 f.lock.Lock() 212 if !ok || !(f.syncing || f.processResponse(req, resp)) { 213 resp.peer.Log().Debug("Failed processing response") 214 go f.pm.removePeer(resp.peer.id) 215 } 216 f.lock.Unlock() 217 case p := <-f.syncDone: 218 f.lock.Lock() 219 p.Log().Debug("Done synchronising with peer") 220 f.checkSyncedHeaders(p) 221 f.syncing = false 222 f.lock.Unlock() 223 f.requestChn <- false 224 } 225 } 226 } 227 228 // registerPeer adds a new peer to the fetcher's peer set 229 func (f *lightFetcher) registerPeer(p *peer) { 230 p.lock.Lock() 231 p.hasBlock = func(hash common.Hash, number uint64, hasState bool) bool { 232 return f.peerHasBlock(p, hash, number, hasState) 233 } 234 p.lock.Unlock() 235 236 f.lock.Lock() 237 defer f.lock.Unlock() 238 f.peers[p] = &fetcherPeerInfo{nodeByHash: make(map[common.Hash]*fetcherTreeNode)} 239 } 240 241 // unregisterPeer removes a new peer from the fetcher's peer set 242 func (f *lightFetcher) unregisterPeer(p *peer) { 243 p.lock.Lock() 244 p.hasBlock = nil 245 p.lock.Unlock() 246 247 f.lock.Lock() 248 defer f.lock.Unlock() 249 250 // check for potential timed out block delay statistics 251 f.checkUpdateStats(p, nil) 252 delete(f.peers, p) 253 } 254 255 // announce processes a new announcement message received from a peer, adding new 256 // nodes to the peer's block tree and removing old nodes if necessary 257 func (f *lightFetcher) announce(p *peer, head *announceData) { 258 f.lock.Lock() 259 defer f.lock.Unlock() 260 p.Log().Debug("Received new announcement", "number", head.Number, "hash", head.Hash, "reorg", head.ReorgDepth) 261 262 fp := f.peers[p] 263 if fp == nil { 264 p.Log().Debug("Announcement from unknown peer") 265 return 266 } 267 268 if fp.lastAnnounced != nil && head.Td.Cmp(fp.lastAnnounced.td) <= 0 { 269 // announced tds should be strictly monotonic 270 p.Log().Debug("Received non-monotonic td", "current", head.Td, "previous", fp.lastAnnounced.td) 271 go f.pm.removePeer(p.id) 272 return 273 } 274 275 n := fp.lastAnnounced 276 for i := uint64(0); i < head.ReorgDepth; i++ { 277 if n == nil { 278 break 279 } 280 n = n.parent 281 } 282 // n is now the reorg common ancestor, add a new branch of nodes 283 if n != nil && (head.Number >= n.number+maxNodeCount || head.Number <= n.number) { 284 // if announced head block height is lower or same as n or too far from it to add 285 // intermediate nodes then discard previous announcement info and trigger a resync 286 n = nil 287 fp.nodeCnt = 0 288 fp.nodeByHash = make(map[common.Hash]*fetcherTreeNode) 289 } 290 // check if the node count is too high to add new nodes, discard oldest ones if necessary 291 if n != nil { 292 // n is now the reorg common ancestor, add a new branch of nodes 293 // check if the node count is too high to add new nodes 294 locked := false 295 for uint64(fp.nodeCnt)+head.Number-n.number > maxNodeCount && fp.root != nil { 296 if !locked { 297 f.chain.LockChain() 298 defer f.chain.UnlockChain() 299 locked = true 300 } 301 // if one of root's children is canonical, keep it, delete other branches and root itself 302 var newRoot *fetcherTreeNode 303 for i, nn := range fp.root.children { 304 if rawdb.ReadCanonicalHash(f.pm.chainDb, nn.number) == nn.hash { 305 fp.root.children = append(fp.root.children[:i], fp.root.children[i+1:]...) 306 nn.parent = nil 307 newRoot = nn 308 break 309 } 310 } 311 fp.deleteNode(fp.root) 312 if n == fp.root { 313 n = newRoot 314 } 315 fp.root = newRoot 316 if newRoot == nil || !f.checkKnownNode(p, newRoot) { 317 fp.bestConfirmed = nil 318 fp.confirmedTd = nil 319 } 320 321 if n == nil { 322 break 323 } 324 } 325 if n != nil { 326 for n.number < head.Number { 327 nn := &fetcherTreeNode{number: n.number + 1, parent: n} 328 n.children = append(n.children, nn) 329 n = nn 330 fp.nodeCnt++ 331 } 332 n.hash = head.Hash 333 n.td = head.Td 334 fp.nodeByHash[n.hash] = n 335 } 336 } 337 338 if n == nil { 339 // could not find reorg common ancestor or had to delete entire tree, a new root and a resync is needed 340 if fp.root != nil { 341 fp.deleteNode(fp.root) 342 } 343 n = &fetcherTreeNode{hash: head.Hash, number: head.Number, td: head.Td} 344 fp.root = n 345 fp.nodeCnt++ 346 fp.nodeByHash[n.hash] = n 347 fp.bestConfirmed = nil 348 fp.confirmedTd = nil 349 } 350 351 f.checkKnownNode(p, n) 352 p.lock.Lock() 353 p.headInfo = head 354 fp.lastAnnounced = n 355 p.lock.Unlock() 356 f.checkUpdateStats(p, nil) 357 f.requestChn <- true 358 } 359 360 // peerHasBlock returns true if we can assume the peer knows the given block 361 // based on its announcements 362 func (f *lightFetcher) peerHasBlock(p *peer, hash common.Hash, number uint64, hasState bool) bool { 363 f.lock.Lock() 364 defer f.lock.Unlock() 365 366 fp := f.peers[p] 367 if fp == nil || fp.root == nil { 368 return false 369 } 370 371 if hasState { 372 if fp.lastAnnounced == nil || fp.lastAnnounced.number > number+serverStateAvailable { 373 return false 374 } 375 } 376 377 if f.syncing { 378 // always return true when syncing 379 // false positives are acceptable, a more sophisticated condition can be implemented later 380 return true 381 } 382 383 if number >= fp.root.number { 384 // it is recent enough that if it is known, is should be in the peer's block tree 385 return fp.nodeByHash[hash] != nil 386 } 387 f.chain.LockChain() 388 defer f.chain.UnlockChain() 389 // if it's older than the peer's block tree root but it's in the same canonical chain 390 // as the root, we can still be sure the peer knows it 391 // 392 // when syncing, just check if it is part of the known chain, there is nothing better we 393 // can do since we do not know the most recent block hash yet 394 return rawdb.ReadCanonicalHash(f.pm.chainDb, fp.root.number) == fp.root.hash && rawdb.ReadCanonicalHash(f.pm.chainDb, number) == hash 395 } 396 397 // requestAmount calculates the amount of headers to be downloaded starting 398 // from a certain head backwards 399 func (f *lightFetcher) requestAmount(p *peer, n *fetcherTreeNode) uint64 { 400 amount := uint64(0) 401 nn := n 402 for nn != nil && !f.checkKnownNode(p, nn) { 403 nn = nn.parent 404 amount++ 405 } 406 if nn == nil { 407 amount = n.number 408 } 409 return amount 410 } 411 412 // requestedID tells if a certain reqID has been requested by the fetcher 413 func (f *lightFetcher) requestedID(reqID uint64) bool { 414 f.reqMu.RLock() 415 _, ok := f.requested[reqID] 416 f.reqMu.RUnlock() 417 return ok 418 } 419 420 // nextRequest selects the peer and announced head to be requested next, amount 421 // to be downloaded starting from the head backwards is also returned 422 func (f *lightFetcher) nextRequest() (*distReq, uint64, bool) { 423 var ( 424 bestHash common.Hash 425 bestAmount uint64 426 bestTd *big.Int 427 bestSyncing bool 428 ) 429 bestHash, bestAmount, bestTd, bestSyncing = f.findBestRequest() 430 431 if bestTd == f.maxConfirmedTd { 432 return nil, 0, false 433 } 434 435 var rq *distReq 436 reqID := genReqID() 437 if bestSyncing { 438 rq = f.newFetcherDistReqForSync(bestHash) 439 } else { 440 rq = f.newFetcherDistReq(bestHash, reqID, bestAmount) 441 } 442 return rq, reqID, bestSyncing 443 } 444 445 // findBestRequest finds the best head to request that has been announced by but not yet requested from a known peer. 446 // It also returns the announced Td (which should be verified after fetching the head), 447 // the necessary amount to request and whether a downloader sync is necessary instead of a normal header request. 448 func (f *lightFetcher) findBestRequest() (bestHash common.Hash, bestAmount uint64, bestTd *big.Int, bestSyncing bool) { 449 bestTd = f.maxConfirmedTd 450 bestSyncing = false 451 452 for p, fp := range f.peers { 453 for hash, n := range fp.nodeByHash { 454 if f.checkKnownNode(p, n) || n.requested { 455 continue 456 } 457 458 //if ulc mode is disabled, isTrustedHash returns true 459 amount := f.requestAmount(p, n) 460 if (bestTd == nil || n.td.Cmp(bestTd) > 0 || amount < bestAmount) && (f.isTrustedHash(hash) || f.maxConfirmedTd.Int64() == 0) { 461 bestHash = hash 462 bestTd = n.td 463 bestAmount = amount 464 bestSyncing = fp.bestConfirmed == nil || fp.root == nil || !f.checkKnownNode(p, fp.root) 465 } 466 } 467 } 468 return 469 } 470 471 // isTrustedHash checks if the block can be trusted by the minimum trusted fraction. 472 func (f *lightFetcher) isTrustedHash(hash common.Hash) bool { 473 if !f.pm.isULCEnabled() { 474 return true 475 } 476 477 var numAgreed int 478 for p, fp := range f.peers { 479 if !p.isTrusted { 480 continue 481 } 482 if _, ok := fp.nodeByHash[hash]; !ok { 483 continue 484 } 485 486 numAgreed++ 487 } 488 489 return 100*numAgreed/len(f.pm.ulc.trustedKeys) >= f.pm.ulc.minTrustedFraction 490 } 491 492 func (f *lightFetcher) newFetcherDistReqForSync(bestHash common.Hash) *distReq { 493 return &distReq{ 494 getCost: func(dp distPeer) uint64 { 495 return 0 496 }, 497 canSend: func(dp distPeer) bool { 498 p := dp.(*peer) 499 f.lock.Lock() 500 defer f.lock.Unlock() 501 502 if p.isOnlyAnnounce { 503 return false 504 } 505 506 fp := f.peers[p] 507 return fp != nil && fp.nodeByHash[bestHash] != nil 508 }, 509 request: func(dp distPeer) func() { 510 if f.pm.isULCEnabled() { 511 //keep last trusted header before sync 512 f.setLastTrustedHeader(f.chain.CurrentHeader()) 513 } 514 go func() { 515 p := dp.(*peer) 516 p.Log().Debug("Synchronisation started") 517 f.pm.synchronise(p) 518 f.syncDone <- p 519 }() 520 return nil 521 }, 522 } 523 } 524 525 // newFetcherDistReq creates a new request for the distributor. 526 func (f *lightFetcher) newFetcherDistReq(bestHash common.Hash, reqID uint64, bestAmount uint64) *distReq { 527 return &distReq{ 528 getCost: func(dp distPeer) uint64 { 529 p := dp.(*peer) 530 return p.GetRequestCost(GetBlockHeadersMsg, int(bestAmount)) 531 }, 532 canSend: func(dp distPeer) bool { 533 p := dp.(*peer) 534 f.lock.Lock() 535 defer f.lock.Unlock() 536 537 if p.isOnlyAnnounce { 538 return false 539 } 540 541 fp := f.peers[p] 542 if fp == nil { 543 return false 544 } 545 n := fp.nodeByHash[bestHash] 546 return n != nil && !n.requested 547 }, 548 request: func(dp distPeer) func() { 549 p := dp.(*peer) 550 f.lock.Lock() 551 fp := f.peers[p] 552 if fp != nil { 553 n := fp.nodeByHash[bestHash] 554 if n != nil { 555 n.requested = true 556 } 557 } 558 f.lock.Unlock() 559 560 cost := p.GetRequestCost(GetBlockHeadersMsg, int(bestAmount)) 561 p.fcServer.QueuedRequest(reqID, cost) 562 f.reqMu.Lock() 563 f.requested[reqID] = fetchRequest{hash: bestHash, amount: bestAmount, peer: p, sent: mclock.Now()} 564 f.reqMu.Unlock() 565 go func() { 566 time.Sleep(hardRequestTimeout) 567 f.timeoutChn <- reqID 568 }() 569 return func() { p.RequestHeadersByHash(reqID, cost, bestHash, int(bestAmount), 0, true) } 570 }, 571 } 572 } 573 574 // deliverHeaders delivers header download request responses for processing 575 func (f *lightFetcher) deliverHeaders(peer *peer, reqID uint64, headers []*types.Header) { 576 f.deliverChn <- fetchResponse{reqID: reqID, headers: headers, peer: peer} 577 } 578 579 // processResponse processes header download request responses, returns true if successful 580 func (f *lightFetcher) processResponse(req fetchRequest, resp fetchResponse) bool { 581 if uint64(len(resp.headers)) != req.amount || resp.headers[0].Hash() != req.hash { 582 req.peer.Log().Debug("Response content mismatch", "requested", len(resp.headers), "reqfrom", resp.headers[0], "delivered", req.amount, "delfrom", req.hash) 583 return false 584 } 585 headers := make([]*types.Header, req.amount) 586 for i, header := range resp.headers { 587 headers[int(req.amount)-1-i] = header 588 } 589 590 if _, err := f.chain.InsertHeaderChain(headers, 1); err != nil { 591 if err == consensus.ErrFutureBlock { 592 return true 593 } 594 log.Debug("Failed to insert header chain", "err", err) 595 return false 596 } 597 tds := make([]*big.Int, len(headers)) 598 for i, header := range headers { 599 td := f.chain.GetTd(header.Hash(), header.Number.Uint64()) 600 if td == nil { 601 log.Debug("Total difficulty not found for header", "index", i+1, "number", header.Number, "hash", header.Hash()) 602 return false 603 } 604 tds[i] = td 605 } 606 f.newHeaders(headers, tds) 607 return true 608 } 609 610 // newHeaders updates the block trees of all active peers according to a newly 611 // downloaded and validated batch or headers 612 func (f *lightFetcher) newHeaders(headers []*types.Header, tds []*big.Int) { 613 var maxTd *big.Int 614 615 for p, fp := range f.peers { 616 if !f.checkAnnouncedHeaders(fp, headers, tds) { 617 p.Log().Debug("Inconsistent announcement") 618 go f.pm.removePeer(p.id) 619 } 620 if fp.confirmedTd != nil && (maxTd == nil || maxTd.Cmp(fp.confirmedTd) > 0) { 621 maxTd = fp.confirmedTd 622 } 623 } 624 625 if maxTd != nil { 626 f.updateMaxConfirmedTd(maxTd) 627 } 628 } 629 630 // checkAnnouncedHeaders updates peer's block tree if necessary after validating 631 // a batch of headers. It searches for the latest header in the batch that has a 632 // matching tree node (if any), and if it has not been marked as known already, 633 // sets it and its parents to known (even those which are older than the currently 634 // validated ones). Return value shows if all hashes, numbers and Tds matched 635 // correctly to the announced values (otherwise the peer should be dropped). 636 func (f *lightFetcher) checkAnnouncedHeaders(fp *fetcherPeerInfo, headers []*types.Header, tds []*big.Int) bool { 637 var ( 638 n *fetcherTreeNode 639 header *types.Header 640 td *big.Int 641 ) 642 643 for i := len(headers) - 1; ; i-- { 644 if i < 0 { 645 if n == nil { 646 // no more headers and nothing to match 647 return true 648 } 649 // we ran out of recently delivered headers but have not reached a node known by this peer yet, continue matching 650 hash, number := header.ParentHash, header.Number.Uint64()-1 651 td = f.chain.GetTd(hash, number) 652 header = f.chain.GetHeader(hash, number) 653 if header == nil || td == nil { 654 log.Error("Missing parent of validated header", "hash", hash, "number", number) 655 return false 656 } 657 } else { 658 header = headers[i] 659 td = tds[i] 660 } 661 hash := header.Hash() 662 number := header.Number.Uint64() 663 if n == nil { 664 n = fp.nodeByHash[hash] 665 } 666 if n != nil { 667 if n.td == nil { 668 // node was unannounced 669 if nn := fp.nodeByHash[hash]; nn != nil { 670 // if there was already a node with the same hash, continue there and drop this one 671 nn.children = append(nn.children, n.children...) 672 n.children = nil 673 fp.deleteNode(n) 674 n = nn 675 } else { 676 n.hash = hash 677 n.td = td 678 fp.nodeByHash[hash] = n 679 } 680 } 681 // check if it matches the header 682 if n.hash != hash || n.number != number || n.td.Cmp(td) != 0 { 683 // peer has previously made an invalid announcement 684 return false 685 } 686 if n.known { 687 // we reached a known node that matched our expectations, return with success 688 return true 689 } 690 n.known = true 691 if fp.confirmedTd == nil || td.Cmp(fp.confirmedTd) > 0 { 692 fp.confirmedTd = td 693 fp.bestConfirmed = n 694 } 695 n = n.parent 696 if n == nil { 697 return true 698 } 699 } 700 } 701 } 702 703 // checkSyncedHeaders updates peer's block tree after synchronisation by marking 704 // downloaded headers as known. If none of the announced headers are found after 705 // syncing, the peer is dropped. 706 func (f *lightFetcher) checkSyncedHeaders(p *peer) { 707 fp := f.peers[p] 708 if fp == nil { 709 p.Log().Debug("Unknown peer to check sync headers") 710 return 711 } 712 713 n := fp.lastAnnounced 714 var td *big.Int 715 716 var h *types.Header 717 if f.pm.isULCEnabled() { 718 var unapprovedHashes []common.Hash 719 // Overwrite last announced for ULC mode 720 h, unapprovedHashes = f.lastTrustedTreeNode(p) 721 //rollback untrusted blocks 722 f.chain.Rollback(unapprovedHashes) 723 //overwrite to last trusted 724 n = fp.nodeByHash[h.Hash()] 725 } 726 727 //find last valid block 728 for n != nil { 729 if td = f.chain.GetTd(n.hash, n.number); td != nil { 730 break 731 } 732 n = n.parent 733 } 734 735 // Now n is the latest downloaded/approved header after syncing 736 if n == nil { 737 p.Log().Debug("Synchronisation failed") 738 go f.pm.removePeer(p.id) 739 return 740 } 741 header := f.chain.GetHeader(n.hash, n.number) 742 f.newHeaders([]*types.Header{header}, []*big.Int{td}) 743 } 744 745 // lastTrustedTreeNode return last approved treeNode and a list of unapproved hashes 746 func (f *lightFetcher) lastTrustedTreeNode(p *peer) (*types.Header, []common.Hash) { 747 unapprovedHashes := make([]common.Hash, 0) 748 current := f.chain.CurrentHeader() 749 750 if f.lastTrustedHeader == nil { 751 return current, unapprovedHashes 752 } 753 754 canonical := f.chain.CurrentHeader() 755 if canonical.Number.Uint64() > f.lastTrustedHeader.Number.Uint64() { 756 canonical = f.chain.GetHeaderByNumber(f.lastTrustedHeader.Number.Uint64()) 757 } 758 commonAncestor := rawdb.FindCommonAncestor(f.pm.chainDb, canonical, f.lastTrustedHeader) 759 if commonAncestor == nil { 760 log.Error("Common ancestor of last trusted header and canonical header is nil", "canonical hash", canonical.Hash(), "trusted hash", f.lastTrustedHeader.Hash()) 761 return current, unapprovedHashes 762 } 763 764 for current.Hash() == commonAncestor.Hash() { 765 if f.isTrustedHash(current.Hash()) { 766 break 767 } 768 unapprovedHashes = append(unapprovedHashes, current.Hash()) 769 current = f.chain.GetHeader(current.ParentHash, current.Number.Uint64()-1) 770 } 771 return current, unapprovedHashes 772 } 773 774 func (f *lightFetcher) setLastTrustedHeader(h *types.Header) { 775 f.lock.Lock() 776 defer f.lock.Unlock() 777 f.lastTrustedHeader = h 778 } 779 780 // checkKnownNode checks if a block tree node is known (downloaded and validated) 781 // If it was not known previously but found in the database, sets its known flag 782 func (f *lightFetcher) checkKnownNode(p *peer, n *fetcherTreeNode) bool { 783 if n.known { 784 return true 785 } 786 td := f.chain.GetTd(n.hash, n.number) 787 if td == nil { 788 return false 789 } 790 header := f.chain.GetHeader(n.hash, n.number) 791 // check the availability of both header and td because reads are not protected by chain db mutex 792 // Note: returning false is always safe here 793 if header == nil { 794 return false 795 } 796 797 fp := f.peers[p] 798 if fp == nil { 799 p.Log().Debug("Unknown peer to check known nodes") 800 return false 801 } 802 if !f.checkAnnouncedHeaders(fp, []*types.Header{header}, []*big.Int{td}) { 803 p.Log().Debug("Inconsistent announcement") 804 go f.pm.removePeer(p.id) 805 } 806 if fp.confirmedTd != nil { 807 f.updateMaxConfirmedTd(fp.confirmedTd) 808 } 809 return n.known 810 } 811 812 // deleteNode deletes a node and its child subtrees from a peer's block tree 813 func (fp *fetcherPeerInfo) deleteNode(n *fetcherTreeNode) { 814 if n.parent != nil { 815 for i, nn := range n.parent.children { 816 if nn == n { 817 n.parent.children = append(n.parent.children[:i], n.parent.children[i+1:]...) 818 break 819 } 820 } 821 } 822 for { 823 if n.td != nil { 824 delete(fp.nodeByHash, n.hash) 825 } 826 fp.nodeCnt-- 827 if len(n.children) == 0 { 828 return 829 } 830 for i, nn := range n.children { 831 if i == 0 { 832 n = nn 833 } else { 834 fp.deleteNode(nn) 835 } 836 } 837 } 838 } 839 840 // updateStatsEntry items form a linked list that is expanded with a new item every time a new head with a higher Td 841 // than the previous one has been downloaded and validated. The list contains a series of maximum confirmed Td values 842 // and the time these values have been confirmed, both increasing monotonically. A maximum confirmed Td is calculated 843 // both globally for all peers and also for each individual peer (meaning that the given peer has announced the head 844 // and it has also been downloaded from any peer, either before or after the given announcement). 845 // The linked list has a global tail where new confirmed Td entries are added and a separate head for each peer, 846 // pointing to the next Td entry that is higher than the peer's max confirmed Td (nil if it has already confirmed 847 // the current global head). 848 type updateStatsEntry struct { 849 time mclock.AbsTime 850 td *big.Int 851 next *updateStatsEntry 852 } 853 854 // updateMaxConfirmedTd updates the block delay statistics of active peers. Whenever a new highest Td is confirmed, 855 // adds it to the end of a linked list together with the time it has been confirmed. Then checks which peers have 856 // already confirmed a head with the same or higher Td (which counts as zero block delay) and updates their statistics. 857 // Those who have not confirmed such a head by now will be updated by a subsequent checkUpdateStats call with a 858 // positive block delay value. 859 func (f *lightFetcher) updateMaxConfirmedTd(td *big.Int) { 860 if f.maxConfirmedTd == nil || td.Cmp(f.maxConfirmedTd) > 0 { 861 f.maxConfirmedTd = td 862 newEntry := &updateStatsEntry{ 863 time: mclock.Now(), 864 td: td, 865 } 866 if f.lastUpdateStats != nil { 867 f.lastUpdateStats.next = newEntry 868 } 869 870 f.lastUpdateStats = newEntry 871 for p := range f.peers { 872 f.checkUpdateStats(p, newEntry) 873 } 874 } 875 } 876 877 // checkUpdateStats checks those peers who have not confirmed a certain highest Td (or a larger one) by the time it 878 // has been confirmed by another peer. If they have confirmed such a head by now, their stats are updated with the 879 // block delay which is (this peer's confirmation time)-(first confirmation time). After blockDelayTimeout has passed, 880 // the stats are updated with blockDelayTimeout value. In either case, the confirmed or timed out updateStatsEntry 881 // items are removed from the head of the linked list. 882 // If a new entry has been added to the global tail, it is passed as a parameter here even though this function 883 // assumes that it has already been added, so that if the peer's list is empty (all heads confirmed, head is nil), 884 // it can set the new head to newEntry. 885 func (f *lightFetcher) checkUpdateStats(p *peer, newEntry *updateStatsEntry) { 886 now := mclock.Now() 887 fp := f.peers[p] 888 if fp == nil { 889 p.Log().Debug("Unknown peer to check update stats") 890 return 891 } 892 893 if newEntry != nil && fp.firstUpdateStats == nil { 894 fp.firstUpdateStats = newEntry 895 } 896 for fp.firstUpdateStats != nil && fp.firstUpdateStats.time <= now-mclock.AbsTime(blockDelayTimeout) { 897 f.pm.serverPool.adjustBlockDelay(p.poolEntry, blockDelayTimeout) 898 fp.firstUpdateStats = fp.firstUpdateStats.next 899 } 900 if fp.confirmedTd != nil { 901 for fp.firstUpdateStats != nil && fp.firstUpdateStats.td.Cmp(fp.confirmedTd) <= 0 { 902 f.pm.serverPool.adjustBlockDelay(p.poolEntry, time.Duration(now-fp.firstUpdateStats.time)) 903 fp.firstUpdateStats = fp.firstUpdateStats.next 904 } 905 } 906 }