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