github.com/bloxroute-labs/bor@v0.1.4/les/handler.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 "encoding/binary" 21 "encoding/json" 22 "errors" 23 "fmt" 24 "math/big" 25 "sync" 26 "sync/atomic" 27 "time" 28 29 "github.com/maticnetwork/bor/common" 30 "github.com/maticnetwork/bor/core" 31 "github.com/maticnetwork/bor/core/rawdb" 32 "github.com/maticnetwork/bor/core/state" 33 "github.com/maticnetwork/bor/core/types" 34 "github.com/maticnetwork/bor/eth/downloader" 35 "github.com/maticnetwork/bor/ethdb" 36 "github.com/maticnetwork/bor/event" 37 "github.com/maticnetwork/bor/light" 38 "github.com/maticnetwork/bor/log" 39 "github.com/maticnetwork/bor/p2p" 40 "github.com/maticnetwork/bor/p2p/discv5" 41 "github.com/maticnetwork/bor/params" 42 "github.com/maticnetwork/bor/rlp" 43 "github.com/maticnetwork/bor/trie" 44 ) 45 46 var errTooManyInvalidRequest = errors.New("too many invalid requests made") 47 48 const ( 49 softResponseLimit = 2 * 1024 * 1024 // Target maximum size of returned blocks, headers or node data. 50 estHeaderRlpSize = 500 // Approximate size of an RLP encoded block header 51 52 ethVersion = 63 // equivalent eth version for the downloader 53 54 MaxHeaderFetch = 192 // Amount of block headers to be fetched per retrieval request 55 MaxBodyFetch = 32 // Amount of block bodies to be fetched per retrieval request 56 MaxReceiptFetch = 128 // Amount of transaction receipts to allow fetching per request 57 MaxCodeFetch = 64 // Amount of contract codes to allow fetching per request 58 MaxProofsFetch = 64 // Amount of merkle proofs to be fetched per retrieval request 59 MaxHelperTrieProofsFetch = 64 // Amount of merkle proofs to be fetched per retrieval request 60 MaxTxSend = 64 // Amount of transactions to be send per request 61 MaxTxStatus = 256 // Amount of transactions to queried per request 62 63 disableClientRemovePeer = false 64 ) 65 66 func errResp(code errCode, format string, v ...interface{}) error { 67 return fmt.Errorf("%v - %v", code, fmt.Sprintf(format, v...)) 68 } 69 70 type BlockChain interface { 71 Config() *params.ChainConfig 72 HasHeader(hash common.Hash, number uint64) bool 73 GetHeader(hash common.Hash, number uint64) *types.Header 74 GetHeaderByHash(hash common.Hash) *types.Header 75 CurrentHeader() *types.Header 76 GetTd(hash common.Hash, number uint64) *big.Int 77 StateCache() state.Database 78 InsertHeaderChain(chain []*types.Header, checkFreq int) (int, error) 79 Rollback(chain []common.Hash) 80 GetHeaderByNumber(number uint64) *types.Header 81 GetAncestor(hash common.Hash, number, ancestor uint64, maxNonCanonical *uint64) (common.Hash, uint64) 82 Genesis() *types.Block 83 SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription 84 } 85 86 type txPool interface { 87 AddRemotes(txs []*types.Transaction) []error 88 Status(hashes []common.Hash) []core.TxStatus 89 } 90 91 type ProtocolManager struct { 92 // Configs 93 chainConfig *params.ChainConfig 94 iConfig *light.IndexerConfig 95 96 client bool // The indicator whether the node is light client 97 maxPeers int // The maximum number peers allowed to connect. 98 networkId uint64 // The identity of network. 99 100 txpool txPool 101 txrelay *lesTxRelay 102 blockchain BlockChain 103 chainDb ethdb.Database 104 odr *LesOdr 105 server *LesServer 106 serverPool *serverPool 107 lesTopic discv5.Topic 108 reqDist *requestDistributor 109 retriever *retrieveManager 110 servingQueue *servingQueue 111 downloader *downloader.Downloader 112 fetcher *lightFetcher 113 ulc *ulc 114 peers *peerSet 115 checkpoint *params.TrustedCheckpoint 116 reg *checkpointOracle // If reg == nil, it means the checkpoint registrar is not activated 117 118 // channels for fetcher, syncer, txsyncLoop 119 newPeerCh chan *peer 120 quitSync chan struct{} 121 noMorePeers chan struct{} 122 123 wg *sync.WaitGroup 124 eventMux *event.TypeMux 125 126 // Callbacks 127 synced func() bool 128 } 129 130 // NewProtocolManager returns a new ethereum sub protocol manager. The Ethereum sub protocol manages peers capable 131 // with the ethereum network. 132 func NewProtocolManager(chainConfig *params.ChainConfig, checkpoint *params.TrustedCheckpoint, indexerConfig *light.IndexerConfig, ulcServers []string, ulcFraction int, client bool, networkId uint64, mux *event.TypeMux, peers *peerSet, blockchain BlockChain, txpool txPool, chainDb ethdb.Database, odr *LesOdr, serverPool *serverPool, registrar *checkpointOracle, quitSync chan struct{}, wg *sync.WaitGroup, synced func() bool) (*ProtocolManager, error) { 133 // Create the protocol manager with the base fields 134 manager := &ProtocolManager{ 135 client: client, 136 eventMux: mux, 137 blockchain: blockchain, 138 chainConfig: chainConfig, 139 iConfig: indexerConfig, 140 chainDb: chainDb, 141 odr: odr, 142 networkId: networkId, 143 txpool: txpool, 144 serverPool: serverPool, 145 reg: registrar, 146 peers: peers, 147 newPeerCh: make(chan *peer), 148 quitSync: quitSync, 149 wg: wg, 150 noMorePeers: make(chan struct{}), 151 checkpoint: checkpoint, 152 synced: synced, 153 } 154 if odr != nil { 155 manager.retriever = odr.retriever 156 manager.reqDist = odr.retriever.dist 157 } 158 159 if ulcServers != nil { 160 ulc, err := newULC(ulcServers, ulcFraction) 161 if err != nil { 162 log.Warn("Failed to initialize ultra light client", "err", err) 163 } else { 164 manager.ulc = ulc 165 } 166 } 167 removePeer := manager.removePeer 168 if disableClientRemovePeer { 169 removePeer = func(id string) {} 170 } 171 if client { 172 var checkpointNumber uint64 173 if checkpoint != nil { 174 checkpointNumber = (checkpoint.SectionIndex+1)*params.CHTFrequency - 1 175 } 176 manager.downloader = downloader.New(checkpointNumber, chainDb, nil, manager.eventMux, nil, blockchain, removePeer) 177 manager.peers.notify((*downloaderPeerNotify)(manager)) 178 manager.fetcher = newLightFetcher(manager) 179 } 180 return manager, nil 181 } 182 183 // removePeer initiates disconnection from a peer by removing it from the peer set 184 func (pm *ProtocolManager) removePeer(id string) { 185 pm.peers.Unregister(id) 186 } 187 188 func (pm *ProtocolManager) Start(maxPeers int) { 189 pm.maxPeers = maxPeers 190 if pm.client { 191 go pm.syncer() 192 } else { 193 go func() { 194 for range pm.newPeerCh { 195 } 196 }() 197 } 198 } 199 200 func (pm *ProtocolManager) Stop() { 201 // Showing a log message. During download / process this could actually 202 // take between 5 to 10 seconds and therefor feedback is required. 203 log.Info("Stopping light Ethereum protocol") 204 205 // Quit the sync loop. 206 // After this send has completed, no new peers will be accepted. 207 pm.noMorePeers <- struct{}{} 208 209 close(pm.quitSync) // quits syncer, fetcher 210 211 if pm.servingQueue != nil { 212 pm.servingQueue.stop() 213 } 214 215 // Disconnect existing sessions. 216 // This also closes the gate for any new registrations on the peer set. 217 // sessions which are already established but not added to pm.peers yet 218 // will exit when they try to register. 219 pm.peers.Close() 220 221 // Wait for any process action 222 pm.wg.Wait() 223 224 log.Info("Light Ethereum protocol stopped") 225 } 226 227 // runPeer is the p2p protocol run function for the given version. 228 func (pm *ProtocolManager) runPeer(version uint, p *p2p.Peer, rw p2p.MsgReadWriter) error { 229 var entry *poolEntry 230 peer := pm.newPeer(int(version), pm.networkId, p, rw) 231 if pm.serverPool != nil { 232 entry = pm.serverPool.connect(peer, peer.Node()) 233 } 234 peer.poolEntry = entry 235 select { 236 case pm.newPeerCh <- peer: 237 pm.wg.Add(1) 238 defer pm.wg.Done() 239 err := pm.handle(peer) 240 if entry != nil { 241 pm.serverPool.disconnect(entry) 242 } 243 return err 244 case <-pm.quitSync: 245 if entry != nil { 246 pm.serverPool.disconnect(entry) 247 } 248 return p2p.DiscQuitting 249 } 250 } 251 252 func (pm *ProtocolManager) newPeer(pv int, nv uint64, p *p2p.Peer, rw p2p.MsgReadWriter) *peer { 253 var trusted bool 254 if pm.ulc != nil { 255 trusted = pm.ulc.trusted(p.ID()) 256 } 257 return newPeer(pv, nv, trusted, p, newMeteredMsgWriter(rw)) 258 } 259 260 // handle is the callback invoked to manage the life cycle of a les peer. When 261 // this function terminates, the peer is disconnected. 262 func (pm *ProtocolManager) handle(p *peer) error { 263 // Ignore maxPeers if this is a trusted peer 264 // In server mode we try to check into the client pool after handshake 265 if pm.client && pm.peers.Len() >= pm.maxPeers && !p.Peer.Info().Network.Trusted { 266 clientRejectedMeter.Mark(1) 267 return p2p.DiscTooManyPeers 268 } 269 // Reject light clients if server is not synced. 270 if !pm.client && !pm.synced() { 271 clientRejectedMeter.Mark(1) 272 return p2p.DiscRequested 273 } 274 p.Log().Debug("Light Ethereum peer connected", "name", p.Name()) 275 276 // Execute the LES handshake 277 var ( 278 genesis = pm.blockchain.Genesis() 279 head = pm.blockchain.CurrentHeader() 280 hash = head.Hash() 281 number = head.Number.Uint64() 282 td = pm.blockchain.GetTd(hash, number) 283 ) 284 if err := p.Handshake(td, hash, number, genesis.Hash(), pm.server); err != nil { 285 p.Log().Debug("Light Ethereum handshake failed", "err", err) 286 clientErrorMeter.Mark(1) 287 return err 288 } 289 if p.fcClient != nil { 290 defer p.fcClient.Disconnect() 291 } 292 293 if rw, ok := p.rw.(*meteredMsgReadWriter); ok { 294 rw.Init(p.version) 295 } 296 297 // Register the peer locally 298 if err := pm.peers.Register(p); err != nil { 299 clientErrorMeter.Mark(1) 300 p.Log().Error("Light Ethereum peer registration failed", "err", err) 301 return err 302 } 303 connectedAt := time.Now() 304 defer func() { 305 pm.removePeer(p.id) 306 connectionTimer.UpdateSince(connectedAt) 307 }() 308 309 // Register the peer in the downloader. If the downloader considers it banned, we disconnect 310 if pm.client { 311 p.lock.Lock() 312 head := p.headInfo 313 p.lock.Unlock() 314 if pm.fetcher != nil { 315 pm.fetcher.announce(p, head) 316 } 317 318 if p.poolEntry != nil { 319 pm.serverPool.registered(p.poolEntry) 320 } 321 } 322 // main loop. handle incoming messages. 323 for { 324 if err := pm.handleMsg(p); err != nil { 325 p.Log().Debug("Light Ethereum message handling failed", "err", err) 326 if p.fcServer != nil { 327 p.fcServer.DumpLogs() 328 } 329 return err 330 } 331 } 332 } 333 334 // handleMsg is invoked whenever an inbound message is received from a remote 335 // peer. The remote connection is torn down upon returning any error. 336 func (pm *ProtocolManager) handleMsg(p *peer) error { 337 select { 338 case err := <-p.errCh: 339 return err 340 default: 341 } 342 // Read the next message from the remote peer, and ensure it's fully consumed 343 msg, err := p.rw.ReadMsg() 344 if err != nil { 345 return err 346 } 347 p.Log().Trace("Light Ethereum message arrived", "code", msg.Code, "bytes", msg.Size) 348 349 p.responseCount++ 350 responseCount := p.responseCount 351 var ( 352 maxCost uint64 353 task *servingTask 354 ) 355 356 accept := func(reqID, reqCnt, maxCnt uint64) bool { 357 inSizeCost := func() uint64 { 358 if pm.server.costTracker != nil { 359 return pm.server.costTracker.realCost(0, msg.Size, 0) 360 } 361 return 0 362 } 363 if p.isFrozen() || reqCnt == 0 || p.fcClient == nil || reqCnt > maxCnt { 364 p.fcClient.OneTimeCost(inSizeCost()) 365 return false 366 } 367 maxCost = p.fcCosts.getMaxCost(msg.Code, reqCnt) 368 gf := float64(1) 369 if pm.server.costTracker != nil { 370 gf = pm.server.costTracker.globalFactor() 371 if gf < 0.001 { 372 p.Log().Error("Invalid global cost factor", "globalFactor", gf) 373 gf = 1 374 } 375 } 376 maxTime := uint64(float64(maxCost) / gf) 377 378 if accepted, bufShort, servingPriority := p.fcClient.AcceptRequest(reqID, responseCount, maxCost); !accepted { 379 p.freezeClient() 380 p.Log().Warn("Request came too early", "remaining", common.PrettyDuration(time.Duration(bufShort*1000000/p.fcParams.MinRecharge))) 381 p.fcClient.OneTimeCost(inSizeCost()) 382 return false 383 } else { 384 task = pm.servingQueue.newTask(p, maxTime, servingPriority) 385 } 386 if task.start() { 387 return true 388 } 389 p.fcClient.RequestProcessed(reqID, responseCount, maxCost, inSizeCost()) 390 return false 391 } 392 393 if msg.Size > ProtocolMaxMsgSize { 394 return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, ProtocolMaxMsgSize) 395 } 396 defer msg.Discard() 397 398 var deliverMsg *Msg 399 400 sendResponse := func(reqID, amount uint64, reply *reply, servingTime uint64) { 401 p.responseLock.Lock() 402 defer p.responseLock.Unlock() 403 404 if p.isFrozen() { 405 amount = 0 406 reply = nil 407 } 408 var replySize uint32 409 if reply != nil { 410 replySize = reply.size() 411 } 412 var realCost uint64 413 if pm.server.costTracker != nil { 414 realCost = pm.server.costTracker.realCost(servingTime, msg.Size, replySize) 415 if amount != 0 { 416 pm.server.costTracker.updateStats(msg.Code, amount, servingTime, realCost) 417 } 418 } else { 419 realCost = maxCost 420 } 421 bv := p.fcClient.RequestProcessed(reqID, responseCount, maxCost, realCost) 422 if reply != nil { 423 p.queueSend(func() { 424 if err := reply.send(bv); err != nil { 425 select { 426 case p.errCh <- err: 427 default: 428 } 429 } 430 }) 431 } 432 } 433 434 // Handle the message depending on its contents 435 switch msg.Code { 436 case StatusMsg: 437 p.Log().Trace("Received status message") 438 // Status messages should never arrive after the handshake 439 return errResp(ErrExtraStatusMsg, "uncontrolled status message") 440 441 // Block header query, collect the requested headers and reply 442 case AnnounceMsg: 443 p.Log().Trace("Received announce message") 444 var req announceData 445 if err := msg.Decode(&req); err != nil { 446 return errResp(ErrDecode, "%v: %v", msg, err) 447 } 448 if err := req.sanityCheck(); err != nil { 449 return err 450 } 451 update, size := req.Update.decode() 452 if p.rejectUpdate(size) { 453 return errResp(ErrRequestRejected, "") 454 } 455 p.updateFlowControl(update) 456 457 if req.Hash != (common.Hash{}) { 458 if p.announceType == announceTypeNone { 459 return errResp(ErrUnexpectedResponse, "") 460 } 461 if p.announceType == announceTypeSigned { 462 if err := req.checkSignature(p.ID(), update); err != nil { 463 p.Log().Trace("Invalid announcement signature", "err", err) 464 return err 465 } 466 p.Log().Trace("Valid announcement signature") 467 } 468 469 p.Log().Trace("Announce message content", "number", req.Number, "hash", req.Hash, "td", req.Td, "reorg", req.ReorgDepth) 470 if pm.fetcher != nil { 471 pm.fetcher.announce(p, &req) 472 } 473 } 474 475 case GetBlockHeadersMsg: 476 p.Log().Trace("Received block header request") 477 // Decode the complex header query 478 var req struct { 479 ReqID uint64 480 Query getBlockHeadersData 481 } 482 if err := msg.Decode(&req); err != nil { 483 return errResp(ErrDecode, "%v: %v", msg, err) 484 } 485 486 query := req.Query 487 if accept(req.ReqID, query.Amount, MaxHeaderFetch) { 488 go func() { 489 hashMode := query.Origin.Hash != (common.Hash{}) 490 first := true 491 maxNonCanonical := uint64(100) 492 493 // Gather headers until the fetch or network limits is reached 494 var ( 495 bytes common.StorageSize 496 headers []*types.Header 497 unknown bool 498 ) 499 for !unknown && len(headers) < int(query.Amount) && bytes < softResponseLimit { 500 if !first && !task.waitOrStop() { 501 sendResponse(req.ReqID, 0, nil, task.servingTime) 502 return 503 } 504 // Retrieve the next header satisfying the query 505 var origin *types.Header 506 if hashMode { 507 if first { 508 origin = pm.blockchain.GetHeaderByHash(query.Origin.Hash) 509 if origin != nil { 510 query.Origin.Number = origin.Number.Uint64() 511 } 512 } else { 513 origin = pm.blockchain.GetHeader(query.Origin.Hash, query.Origin.Number) 514 } 515 } else { 516 origin = pm.blockchain.GetHeaderByNumber(query.Origin.Number) 517 } 518 if origin == nil { 519 atomic.AddUint32(&p.invalidCount, 1) 520 break 521 } 522 headers = append(headers, origin) 523 bytes += estHeaderRlpSize 524 525 // Advance to the next header of the query 526 switch { 527 case hashMode && query.Reverse: 528 // Hash based traversal towards the genesis block 529 ancestor := query.Skip + 1 530 if ancestor == 0 { 531 unknown = true 532 } else { 533 query.Origin.Hash, query.Origin.Number = pm.blockchain.GetAncestor(query.Origin.Hash, query.Origin.Number, ancestor, &maxNonCanonical) 534 unknown = (query.Origin.Hash == common.Hash{}) 535 } 536 case hashMode && !query.Reverse: 537 // Hash based traversal towards the leaf block 538 var ( 539 current = origin.Number.Uint64() 540 next = current + query.Skip + 1 541 ) 542 if next <= current { 543 infos, _ := json.MarshalIndent(p.Peer.Info(), "", " ") 544 p.Log().Warn("GetBlockHeaders skip overflow attack", "current", current, "skip", query.Skip, "next", next, "attacker", infos) 545 unknown = true 546 } else { 547 if header := pm.blockchain.GetHeaderByNumber(next); header != nil { 548 nextHash := header.Hash() 549 expOldHash, _ := pm.blockchain.GetAncestor(nextHash, next, query.Skip+1, &maxNonCanonical) 550 if expOldHash == query.Origin.Hash { 551 query.Origin.Hash, query.Origin.Number = nextHash, next 552 } else { 553 unknown = true 554 } 555 } else { 556 unknown = true 557 } 558 } 559 case query.Reverse: 560 // Number based traversal towards the genesis block 561 if query.Origin.Number >= query.Skip+1 { 562 query.Origin.Number -= query.Skip + 1 563 } else { 564 unknown = true 565 } 566 case !query.Reverse: 567 // Number based traversal towards the leaf block 568 query.Origin.Number += query.Skip + 1 569 } 570 first = false 571 } 572 sendResponse(req.ReqID, query.Amount, p.ReplyBlockHeaders(req.ReqID, headers), task.done()) 573 }() 574 } 575 576 case BlockHeadersMsg: 577 if pm.downloader == nil { 578 return errResp(ErrUnexpectedResponse, "") 579 } 580 581 p.Log().Trace("Received block header response message") 582 // A batch of headers arrived to one of our previous requests 583 var resp struct { 584 ReqID, BV uint64 585 Headers []*types.Header 586 } 587 if err := msg.Decode(&resp); err != nil { 588 return errResp(ErrDecode, "msg %v: %v", msg, err) 589 } 590 p.fcServer.ReceivedReply(resp.ReqID, resp.BV) 591 if pm.fetcher != nil && pm.fetcher.requestedID(resp.ReqID) { 592 pm.fetcher.deliverHeaders(p, resp.ReqID, resp.Headers) 593 } else { 594 err := pm.downloader.DeliverHeaders(p.id, resp.Headers) 595 if err != nil { 596 log.Debug(fmt.Sprint(err)) 597 } 598 } 599 600 case GetBlockBodiesMsg: 601 p.Log().Trace("Received block bodies request") 602 // Decode the retrieval message 603 var req struct { 604 ReqID uint64 605 Hashes []common.Hash 606 } 607 if err := msg.Decode(&req); err != nil { 608 return errResp(ErrDecode, "msg %v: %v", msg, err) 609 } 610 // Gather blocks until the fetch or network limits is reached 611 var ( 612 bytes int 613 bodies []rlp.RawValue 614 ) 615 reqCnt := len(req.Hashes) 616 if accept(req.ReqID, uint64(reqCnt), MaxBodyFetch) { 617 go func() { 618 for i, hash := range req.Hashes { 619 if i != 0 && !task.waitOrStop() { 620 sendResponse(req.ReqID, 0, nil, task.servingTime) 621 return 622 } 623 // Retrieve the requested block body, stopping if enough was found 624 if bytes >= softResponseLimit { 625 break 626 } 627 number := rawdb.ReadHeaderNumber(pm.chainDb, hash) 628 if number == nil { 629 atomic.AddUint32(&p.invalidCount, 1) 630 continue 631 } 632 if data := rawdb.ReadBodyRLP(pm.chainDb, hash, *number); len(data) != 0 { 633 bodies = append(bodies, data) 634 bytes += len(data) 635 } 636 } 637 sendResponse(req.ReqID, uint64(reqCnt), p.ReplyBlockBodiesRLP(req.ReqID, bodies), task.done()) 638 }() 639 } 640 641 case BlockBodiesMsg: 642 if pm.odr == nil { 643 return errResp(ErrUnexpectedResponse, "") 644 } 645 646 p.Log().Trace("Received block bodies response") 647 // A batch of block bodies arrived to one of our previous requests 648 var resp struct { 649 ReqID, BV uint64 650 Data []*types.Body 651 } 652 if err := msg.Decode(&resp); err != nil { 653 return errResp(ErrDecode, "msg %v: %v", msg, err) 654 } 655 p.fcServer.ReceivedReply(resp.ReqID, resp.BV) 656 deliverMsg = &Msg{ 657 MsgType: MsgBlockBodies, 658 ReqID: resp.ReqID, 659 Obj: resp.Data, 660 } 661 662 case GetCodeMsg: 663 p.Log().Trace("Received code request") 664 // Decode the retrieval message 665 var req struct { 666 ReqID uint64 667 Reqs []CodeReq 668 } 669 if err := msg.Decode(&req); err != nil { 670 return errResp(ErrDecode, "msg %v: %v", msg, err) 671 } 672 // Gather state data until the fetch or network limits is reached 673 var ( 674 bytes int 675 data [][]byte 676 ) 677 reqCnt := len(req.Reqs) 678 if accept(req.ReqID, uint64(reqCnt), MaxCodeFetch) { 679 go func() { 680 for i, request := range req.Reqs { 681 if i != 0 && !task.waitOrStop() { 682 sendResponse(req.ReqID, 0, nil, task.servingTime) 683 return 684 } 685 // Look up the root hash belonging to the request 686 number := rawdb.ReadHeaderNumber(pm.chainDb, request.BHash) 687 if number == nil { 688 p.Log().Warn("Failed to retrieve block num for code", "hash", request.BHash) 689 atomic.AddUint32(&p.invalidCount, 1) 690 continue 691 } 692 header := rawdb.ReadHeader(pm.chainDb, request.BHash, *number) 693 if header == nil { 694 p.Log().Warn("Failed to retrieve header for code", "block", *number, "hash", request.BHash) 695 continue 696 } 697 // Refuse to search stale state data in the database since looking for 698 // a non-exist key is kind of expensive. 699 local := pm.blockchain.CurrentHeader().Number.Uint64() 700 if !pm.server.archiveMode && header.Number.Uint64()+core.TriesInMemory <= local { 701 p.Log().Debug("Reject stale code request", "number", header.Number.Uint64(), "head", local) 702 atomic.AddUint32(&p.invalidCount, 1) 703 continue 704 } 705 triedb := pm.blockchain.StateCache().TrieDB() 706 707 account, err := pm.getAccount(triedb, header.Root, common.BytesToHash(request.AccKey)) 708 if err != nil { 709 p.Log().Warn("Failed to retrieve account for code", "block", header.Number, "hash", header.Hash(), "account", common.BytesToHash(request.AccKey), "err", err) 710 atomic.AddUint32(&p.invalidCount, 1) 711 continue 712 } 713 code, err := triedb.Node(common.BytesToHash(account.CodeHash)) 714 if err != nil { 715 p.Log().Warn("Failed to retrieve account code", "block", header.Number, "hash", header.Hash(), "account", common.BytesToHash(request.AccKey), "codehash", common.BytesToHash(account.CodeHash), "err", err) 716 continue 717 } 718 // Accumulate the code and abort if enough data was retrieved 719 data = append(data, code) 720 if bytes += len(code); bytes >= softResponseLimit { 721 break 722 } 723 } 724 sendResponse(req.ReqID, uint64(reqCnt), p.ReplyCode(req.ReqID, data), task.done()) 725 }() 726 } 727 728 case CodeMsg: 729 if pm.odr == nil { 730 return errResp(ErrUnexpectedResponse, "") 731 } 732 733 p.Log().Trace("Received code response") 734 // A batch of node state data arrived to one of our previous requests 735 var resp struct { 736 ReqID, BV uint64 737 Data [][]byte 738 } 739 if err := msg.Decode(&resp); err != nil { 740 return errResp(ErrDecode, "msg %v: %v", msg, err) 741 } 742 p.fcServer.ReceivedReply(resp.ReqID, resp.BV) 743 deliverMsg = &Msg{ 744 MsgType: MsgCode, 745 ReqID: resp.ReqID, 746 Obj: resp.Data, 747 } 748 749 case GetReceiptsMsg: 750 p.Log().Trace("Received receipts request") 751 // Decode the retrieval message 752 var req struct { 753 ReqID uint64 754 Hashes []common.Hash 755 } 756 if err := msg.Decode(&req); err != nil { 757 return errResp(ErrDecode, "msg %v: %v", msg, err) 758 } 759 // Gather state data until the fetch or network limits is reached 760 var ( 761 bytes int 762 receipts []rlp.RawValue 763 ) 764 reqCnt := len(req.Hashes) 765 if accept(req.ReqID, uint64(reqCnt), MaxReceiptFetch) { 766 go func() { 767 for i, hash := range req.Hashes { 768 if i != 0 && !task.waitOrStop() { 769 sendResponse(req.ReqID, 0, nil, task.servingTime) 770 return 771 } 772 if bytes >= softResponseLimit { 773 break 774 } 775 // Retrieve the requested block's receipts, skipping if unknown to us 776 var results types.Receipts 777 number := rawdb.ReadHeaderNumber(pm.chainDb, hash) 778 if number == nil { 779 atomic.AddUint32(&p.invalidCount, 1) 780 continue 781 } 782 results = rawdb.ReadRawReceipts(pm.chainDb, hash, *number) 783 if results == nil { 784 if header := pm.blockchain.GetHeaderByHash(hash); header == nil || header.ReceiptHash != types.EmptyRootHash { 785 continue 786 } 787 } 788 // If known, encode and queue for response packet 789 if encoded, err := rlp.EncodeToBytes(results); err != nil { 790 log.Error("Failed to encode receipt", "err", err) 791 } else { 792 receipts = append(receipts, encoded) 793 bytes += len(encoded) 794 } 795 } 796 sendResponse(req.ReqID, uint64(reqCnt), p.ReplyReceiptsRLP(req.ReqID, receipts), task.done()) 797 }() 798 } 799 800 case ReceiptsMsg: 801 if pm.odr == nil { 802 return errResp(ErrUnexpectedResponse, "") 803 } 804 805 p.Log().Trace("Received receipts response") 806 // A batch of receipts arrived to one of our previous requests 807 var resp struct { 808 ReqID, BV uint64 809 Receipts []types.Receipts 810 } 811 if err := msg.Decode(&resp); err != nil { 812 return errResp(ErrDecode, "msg %v: %v", msg, err) 813 } 814 p.fcServer.ReceivedReply(resp.ReqID, resp.BV) 815 deliverMsg = &Msg{ 816 MsgType: MsgReceipts, 817 ReqID: resp.ReqID, 818 Obj: resp.Receipts, 819 } 820 821 case GetProofsV2Msg: 822 p.Log().Trace("Received les/2 proofs request") 823 // Decode the retrieval message 824 var req struct { 825 ReqID uint64 826 Reqs []ProofReq 827 } 828 if err := msg.Decode(&req); err != nil { 829 return errResp(ErrDecode, "msg %v: %v", msg, err) 830 } 831 // Gather state data until the fetch or network limits is reached 832 var ( 833 lastBHash common.Hash 834 root common.Hash 835 ) 836 reqCnt := len(req.Reqs) 837 if accept(req.ReqID, uint64(reqCnt), MaxProofsFetch) { 838 go func() { 839 nodes := light.NewNodeSet() 840 841 for i, request := range req.Reqs { 842 if i != 0 && !task.waitOrStop() { 843 sendResponse(req.ReqID, 0, nil, task.servingTime) 844 return 845 } 846 // Look up the root hash belonging to the request 847 var ( 848 number *uint64 849 header *types.Header 850 trie state.Trie 851 ) 852 if request.BHash != lastBHash { 853 root, lastBHash = common.Hash{}, request.BHash 854 855 if number = rawdb.ReadHeaderNumber(pm.chainDb, request.BHash); number == nil { 856 p.Log().Warn("Failed to retrieve block num for proof", "hash", request.BHash) 857 atomic.AddUint32(&p.invalidCount, 1) 858 continue 859 } 860 if header = rawdb.ReadHeader(pm.chainDb, request.BHash, *number); header == nil { 861 p.Log().Warn("Failed to retrieve header for proof", "block", *number, "hash", request.BHash) 862 continue 863 } 864 // Refuse to search stale state data in the database since looking for 865 // a non-exist key is kind of expensive. 866 local := pm.blockchain.CurrentHeader().Number.Uint64() 867 if !pm.server.archiveMode && header.Number.Uint64()+core.TriesInMemory <= local { 868 p.Log().Debug("Reject stale trie request", "number", header.Number.Uint64(), "head", local) 869 atomic.AddUint32(&p.invalidCount, 1) 870 continue 871 } 872 root = header.Root 873 } 874 // If a header lookup failed (non existent), ignore subsequent requests for the same header 875 if root == (common.Hash{}) { 876 atomic.AddUint32(&p.invalidCount, 1) 877 continue 878 } 879 // Open the account or storage trie for the request 880 statedb := pm.blockchain.StateCache() 881 882 switch len(request.AccKey) { 883 case 0: 884 // No account key specified, open an account trie 885 trie, err = statedb.OpenTrie(root) 886 if trie == nil || err != nil { 887 p.Log().Warn("Failed to open storage trie for proof", "block", header.Number, "hash", header.Hash(), "root", root, "err", err) 888 continue 889 } 890 default: 891 // Account key specified, open a storage trie 892 account, err := pm.getAccount(statedb.TrieDB(), root, common.BytesToHash(request.AccKey)) 893 if err != nil { 894 p.Log().Warn("Failed to retrieve account for proof", "block", header.Number, "hash", header.Hash(), "account", common.BytesToHash(request.AccKey), "err", err) 895 atomic.AddUint32(&p.invalidCount, 1) 896 continue 897 } 898 trie, err = statedb.OpenStorageTrie(common.BytesToHash(request.AccKey), account.Root) 899 if trie == nil || err != nil { 900 p.Log().Warn("Failed to open storage trie for proof", "block", header.Number, "hash", header.Hash(), "account", common.BytesToHash(request.AccKey), "root", account.Root, "err", err) 901 continue 902 } 903 } 904 // Prove the user's request from the account or stroage trie 905 if err := trie.Prove(request.Key, request.FromLevel, nodes); err != nil { 906 p.Log().Warn("Failed to prove state request", "block", header.Number, "hash", header.Hash(), "err", err) 907 continue 908 } 909 if nodes.DataSize() >= softResponseLimit { 910 break 911 } 912 } 913 sendResponse(req.ReqID, uint64(reqCnt), p.ReplyProofsV2(req.ReqID, nodes.NodeList()), task.done()) 914 }() 915 } 916 917 case ProofsV2Msg: 918 if pm.odr == nil { 919 return errResp(ErrUnexpectedResponse, "") 920 } 921 922 p.Log().Trace("Received les/2 proofs response") 923 // A batch of merkle proofs arrived to one of our previous requests 924 var resp struct { 925 ReqID, BV uint64 926 Data light.NodeList 927 } 928 if err := msg.Decode(&resp); err != nil { 929 return errResp(ErrDecode, "msg %v: %v", msg, err) 930 } 931 p.fcServer.ReceivedReply(resp.ReqID, resp.BV) 932 deliverMsg = &Msg{ 933 MsgType: MsgProofsV2, 934 ReqID: resp.ReqID, 935 Obj: resp.Data, 936 } 937 938 case GetHelperTrieProofsMsg: 939 p.Log().Trace("Received helper trie proof request") 940 // Decode the retrieval message 941 var req struct { 942 ReqID uint64 943 Reqs []HelperTrieReq 944 } 945 if err := msg.Decode(&req); err != nil { 946 return errResp(ErrDecode, "msg %v: %v", msg, err) 947 } 948 // Gather state data until the fetch or network limits is reached 949 var ( 950 auxBytes int 951 auxData [][]byte 952 ) 953 reqCnt := len(req.Reqs) 954 if accept(req.ReqID, uint64(reqCnt), MaxHelperTrieProofsFetch) { 955 go func() { 956 957 var ( 958 lastIdx uint64 959 lastType uint 960 root common.Hash 961 auxTrie *trie.Trie 962 ) 963 nodes := light.NewNodeSet() 964 for i, request := range req.Reqs { 965 if i != 0 && !task.waitOrStop() { 966 sendResponse(req.ReqID, 0, nil, task.servingTime) 967 return 968 } 969 if auxTrie == nil || request.Type != lastType || request.TrieIdx != lastIdx { 970 auxTrie, lastType, lastIdx = nil, request.Type, request.TrieIdx 971 972 var prefix string 973 if root, prefix = pm.getHelperTrie(request.Type, request.TrieIdx); root != (common.Hash{}) { 974 auxTrie, _ = trie.New(root, trie.NewDatabase(rawdb.NewTable(pm.chainDb, prefix))) 975 } 976 } 977 if request.AuxReq == auxRoot { 978 var data []byte 979 if root != (common.Hash{}) { 980 data = root[:] 981 } 982 auxData = append(auxData, data) 983 auxBytes += len(data) 984 } else { 985 if auxTrie != nil { 986 auxTrie.Prove(request.Key, request.FromLevel, nodes) 987 } 988 if request.AuxReq != 0 { 989 data := pm.getHelperTrieAuxData(request) 990 auxData = append(auxData, data) 991 auxBytes += len(data) 992 } 993 } 994 if nodes.DataSize()+auxBytes >= softResponseLimit { 995 break 996 } 997 } 998 sendResponse(req.ReqID, uint64(reqCnt), p.ReplyHelperTrieProofs(req.ReqID, HelperTrieResps{Proofs: nodes.NodeList(), AuxData: auxData}), task.done()) 999 }() 1000 } 1001 1002 case HelperTrieProofsMsg: 1003 if pm.odr == nil { 1004 return errResp(ErrUnexpectedResponse, "") 1005 } 1006 1007 p.Log().Trace("Received helper trie proof response") 1008 var resp struct { 1009 ReqID, BV uint64 1010 Data HelperTrieResps 1011 } 1012 if err := msg.Decode(&resp); err != nil { 1013 return errResp(ErrDecode, "msg %v: %v", msg, err) 1014 } 1015 1016 p.fcServer.ReceivedReply(resp.ReqID, resp.BV) 1017 deliverMsg = &Msg{ 1018 MsgType: MsgHelperTrieProofs, 1019 ReqID: resp.ReqID, 1020 Obj: resp.Data, 1021 } 1022 1023 case SendTxV2Msg: 1024 if pm.txpool == nil { 1025 return errResp(ErrRequestRejected, "") 1026 } 1027 // Transactions arrived, parse all of them and deliver to the pool 1028 var req struct { 1029 ReqID uint64 1030 Txs []*types.Transaction 1031 } 1032 if err := msg.Decode(&req); err != nil { 1033 return errResp(ErrDecode, "msg %v: %v", msg, err) 1034 } 1035 reqCnt := len(req.Txs) 1036 if accept(req.ReqID, uint64(reqCnt), MaxTxSend) { 1037 go func() { 1038 stats := make([]light.TxStatus, len(req.Txs)) 1039 for i, tx := range req.Txs { 1040 if i != 0 && !task.waitOrStop() { 1041 sendResponse(req.ReqID, 0, nil, task.servingTime) 1042 return 1043 } 1044 hash := tx.Hash() 1045 stats[i] = pm.txStatus(hash) 1046 if stats[i].Status == core.TxStatusUnknown { 1047 if errs := pm.txpool.AddRemotes([]*types.Transaction{tx}); errs[0] != nil { 1048 stats[i].Error = errs[0].Error() 1049 continue 1050 } 1051 stats[i] = pm.txStatus(hash) 1052 } 1053 } 1054 sendResponse(req.ReqID, uint64(reqCnt), p.ReplyTxStatus(req.ReqID, stats), task.done()) 1055 }() 1056 } 1057 1058 case GetTxStatusMsg: 1059 if pm.txpool == nil { 1060 return errResp(ErrUnexpectedResponse, "") 1061 } 1062 // Transactions arrived, parse all of them and deliver to the pool 1063 var req struct { 1064 ReqID uint64 1065 Hashes []common.Hash 1066 } 1067 if err := msg.Decode(&req); err != nil { 1068 return errResp(ErrDecode, "msg %v: %v", msg, err) 1069 } 1070 reqCnt := len(req.Hashes) 1071 if accept(req.ReqID, uint64(reqCnt), MaxTxStatus) { 1072 go func() { 1073 stats := make([]light.TxStatus, len(req.Hashes)) 1074 for i, hash := range req.Hashes { 1075 if i != 0 && !task.waitOrStop() { 1076 sendResponse(req.ReqID, 0, nil, task.servingTime) 1077 return 1078 } 1079 stats[i] = pm.txStatus(hash) 1080 } 1081 sendResponse(req.ReqID, uint64(reqCnt), p.ReplyTxStatus(req.ReqID, stats), task.done()) 1082 }() 1083 } 1084 1085 case TxStatusMsg: 1086 if pm.odr == nil { 1087 return errResp(ErrUnexpectedResponse, "") 1088 } 1089 1090 p.Log().Trace("Received tx status response") 1091 var resp struct { 1092 ReqID, BV uint64 1093 Status []light.TxStatus 1094 } 1095 if err := msg.Decode(&resp); err != nil { 1096 return errResp(ErrDecode, "msg %v: %v", msg, err) 1097 } 1098 1099 p.fcServer.ReceivedReply(resp.ReqID, resp.BV) 1100 1101 p.Log().Trace("Received helper trie proof response") 1102 deliverMsg = &Msg{ 1103 MsgType: MsgTxStatus, 1104 ReqID: resp.ReqID, 1105 Obj: resp.Status, 1106 } 1107 1108 case StopMsg: 1109 if pm.odr == nil { 1110 return errResp(ErrUnexpectedResponse, "") 1111 } 1112 p.freezeServer(true) 1113 pm.retriever.frozen(p) 1114 p.Log().Warn("Service stopped") 1115 1116 case ResumeMsg: 1117 if pm.odr == nil { 1118 return errResp(ErrUnexpectedResponse, "") 1119 } 1120 var bv uint64 1121 if err := msg.Decode(&bv); err != nil { 1122 return errResp(ErrDecode, "msg %v: %v", msg, err) 1123 } 1124 p.fcServer.ResumeFreeze(bv) 1125 p.freezeServer(false) 1126 p.Log().Warn("Service resumed") 1127 1128 default: 1129 p.Log().Trace("Received unknown message", "code", msg.Code) 1130 return errResp(ErrInvalidMsgCode, "%v", msg.Code) 1131 } 1132 1133 if deliverMsg != nil { 1134 err := pm.retriever.deliver(p, deliverMsg) 1135 if err != nil { 1136 p.responseErrors++ 1137 if p.responseErrors > maxResponseErrors { 1138 return err 1139 } 1140 } 1141 } 1142 // If the client has made too much invalid request(e.g. request a non-exist data), 1143 // reject them to prevent SPAM attack. 1144 if atomic.LoadUint32(&p.invalidCount) > maxRequestErrors { 1145 return errTooManyInvalidRequest 1146 } 1147 return nil 1148 } 1149 1150 // getAccount retrieves an account from the state based at root. 1151 func (pm *ProtocolManager) getAccount(triedb *trie.Database, root, hash common.Hash) (state.Account, error) { 1152 trie, err := trie.New(root, triedb) 1153 if err != nil { 1154 return state.Account{}, err 1155 } 1156 blob, err := trie.TryGet(hash[:]) 1157 if err != nil { 1158 return state.Account{}, err 1159 } 1160 var account state.Account 1161 if err = rlp.DecodeBytes(blob, &account); err != nil { 1162 return state.Account{}, err 1163 } 1164 return account, nil 1165 } 1166 1167 // getHelperTrie returns the post-processed trie root for the given trie ID and section index 1168 func (pm *ProtocolManager) getHelperTrie(id uint, idx uint64) (common.Hash, string) { 1169 switch id { 1170 case htCanonical: 1171 sectionHead := rawdb.ReadCanonicalHash(pm.chainDb, (idx+1)*pm.iConfig.ChtSize-1) 1172 return light.GetChtRoot(pm.chainDb, idx, sectionHead), light.ChtTablePrefix 1173 case htBloomBits: 1174 sectionHead := rawdb.ReadCanonicalHash(pm.chainDb, (idx+1)*pm.iConfig.BloomTrieSize-1) 1175 return light.GetBloomTrieRoot(pm.chainDb, idx, sectionHead), light.BloomTrieTablePrefix 1176 } 1177 return common.Hash{}, "" 1178 } 1179 1180 // getHelperTrieAuxData returns requested auxiliary data for the given HelperTrie request 1181 func (pm *ProtocolManager) getHelperTrieAuxData(req HelperTrieReq) []byte { 1182 if req.Type == htCanonical && req.AuxReq == auxHeader && len(req.Key) == 8 { 1183 blockNum := binary.BigEndian.Uint64(req.Key) 1184 hash := rawdb.ReadCanonicalHash(pm.chainDb, blockNum) 1185 return rawdb.ReadHeaderRLP(pm.chainDb, hash, blockNum) 1186 } 1187 return nil 1188 } 1189 1190 func (pm *ProtocolManager) txStatus(hash common.Hash) light.TxStatus { 1191 var stat light.TxStatus 1192 stat.Status = pm.txpool.Status([]common.Hash{hash})[0] 1193 // If the transaction is unknown to the pool, try looking it up locally 1194 if stat.Status == core.TxStatusUnknown { 1195 if tx, blockHash, blockNumber, txIndex := rawdb.ReadTransaction(pm.chainDb, hash); tx != nil { 1196 stat.Status = core.TxStatusIncluded 1197 stat.Lookup = &rawdb.LegacyTxLookupEntry{BlockHash: blockHash, BlockIndex: blockNumber, Index: txIndex} 1198 } 1199 } 1200 return stat 1201 } 1202 1203 // downloaderPeerNotify implements peerSetNotify 1204 type downloaderPeerNotify ProtocolManager 1205 1206 type peerConnection struct { 1207 manager *ProtocolManager 1208 peer *peer 1209 } 1210 1211 func (pc *peerConnection) Head() (common.Hash, *big.Int) { 1212 return pc.peer.HeadAndTd() 1213 } 1214 1215 func (pc *peerConnection) RequestHeadersByHash(origin common.Hash, amount int, skip int, reverse bool) error { 1216 reqID := genReqID() 1217 rq := &distReq{ 1218 getCost: func(dp distPeer) uint64 { 1219 peer := dp.(*peer) 1220 return peer.GetRequestCost(GetBlockHeadersMsg, amount) 1221 }, 1222 canSend: func(dp distPeer) bool { 1223 return dp.(*peer) == pc.peer 1224 }, 1225 request: func(dp distPeer) func() { 1226 peer := dp.(*peer) 1227 cost := peer.GetRequestCost(GetBlockHeadersMsg, amount) 1228 peer.fcServer.QueuedRequest(reqID, cost) 1229 return func() { peer.RequestHeadersByHash(reqID, cost, origin, amount, skip, reverse) } 1230 }, 1231 } 1232 _, ok := <-pc.manager.reqDist.queue(rq) 1233 if !ok { 1234 return light.ErrNoPeers 1235 } 1236 return nil 1237 } 1238 1239 func (pc *peerConnection) RequestHeadersByNumber(origin uint64, amount int, skip int, reverse bool) error { 1240 reqID := genReqID() 1241 rq := &distReq{ 1242 getCost: func(dp distPeer) uint64 { 1243 peer := dp.(*peer) 1244 return peer.GetRequestCost(GetBlockHeadersMsg, amount) 1245 }, 1246 canSend: func(dp distPeer) bool { 1247 return dp.(*peer) == pc.peer 1248 }, 1249 request: func(dp distPeer) func() { 1250 peer := dp.(*peer) 1251 cost := peer.GetRequestCost(GetBlockHeadersMsg, amount) 1252 peer.fcServer.QueuedRequest(reqID, cost) 1253 return func() { peer.RequestHeadersByNumber(reqID, cost, origin, amount, skip, reverse) } 1254 }, 1255 } 1256 _, ok := <-pc.manager.reqDist.queue(rq) 1257 if !ok { 1258 return light.ErrNoPeers 1259 } 1260 return nil 1261 } 1262 1263 func (d *downloaderPeerNotify) registerPeer(p *peer) { 1264 pm := (*ProtocolManager)(d) 1265 pc := &peerConnection{ 1266 manager: pm, 1267 peer: p, 1268 } 1269 pm.downloader.RegisterLightPeer(p.id, ethVersion, pc) 1270 } 1271 1272 func (d *downloaderPeerNotify) unregisterPeer(p *peer) { 1273 pm := (*ProtocolManager)(d) 1274 pm.downloader.UnregisterPeer(p.id) 1275 }