github.com/digdeepmining/go-atheios@v1.5.13-0.20180902133602-d5687a2e6f43/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 "errors" 23 "fmt" 24 "math/big" 25 "net" 26 "sync" 27 "time" 28 29 "github.com/atheioschain/go-atheios/common" 30 "github.com/atheioschain/go-atheios/core" 31 "github.com/atheioschain/go-atheios/core/state" 32 "github.com/atheioschain/go-atheios/core/types" 33 "github.com/atheioschain/go-atheios/eth" 34 "github.com/atheioschain/go-atheios/eth/downloader" 35 "github.com/atheioschain/go-atheios/ethdb" 36 "github.com/atheioschain/go-atheios/event" 37 "github.com/atheioschain/go-atheios/logger" 38 "github.com/atheioschain/go-atheios/logger/glog" 39 "github.com/atheioschain/go-atheios/p2p" 40 "github.com/atheioschain/go-atheios/p2p/discover" 41 "github.com/atheioschain/go-atheios/p2p/discv5" 42 "github.com/atheioschain/go-atheios/params" 43 "github.com/atheioschain/go-atheios/pow" 44 "github.com/atheioschain/go-atheios/rlp" 45 "github.com/atheioschain/go-atheios/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 MaxHeaderProofsFetch = 64 // Amount of merkle proofs to be fetched per retrieval request 60 MaxTxSend = 64 // Amount of transactions to be send per request 61 62 disableClientRemovePeer = false 63 ) 64 65 // errIncompatibleConfig is returned if the requested protocols and configs are 66 // not compatible (low protocol version restrictions and high requirements). 67 var errIncompatibleConfig = errors.New("incompatible configuration") 68 69 func errResp(code errCode, format string, v ...interface{}) error { 70 return fmt.Errorf("%v - %v", code, fmt.Sprintf(format, v...)) 71 } 72 73 type hashFetcherFn func(common.Hash) error 74 75 type BlockChain interface { 76 HasHeader(hash common.Hash) bool 77 GetHeader(hash common.Hash, number uint64) *types.Header 78 GetHeaderByHash(hash common.Hash) *types.Header 79 CurrentHeader() *types.Header 80 GetTdByHash(hash common.Hash) *big.Int 81 InsertHeaderChain(chain []*types.Header, checkFreq int) (int, error) 82 Rollback(chain []common.Hash) 83 Status() (td *big.Int, currentBlock common.Hash, genesisBlock common.Hash) 84 GetHeaderByNumber(number uint64) *types.Header 85 GetBlockHashesFromHash(hash common.Hash, max uint64) []common.Hash 86 LastBlockHash() common.Hash 87 Genesis() *types.Block 88 } 89 90 type txPool interface { 91 // AddTransactions should add the given transactions to the pool. 92 AddBatch([]*types.Transaction) error 93 } 94 95 type ProtocolManager struct { 96 lightSync bool 97 txpool txPool 98 txrelay *LesTxRelay 99 networkId int 100 chainConfig *params.ChainConfig 101 blockchain BlockChain 102 chainDb ethdb.Database 103 odr *LesOdr 104 server *LesServer 105 serverPool *serverPool 106 107 downloader *downloader.Downloader 108 fetcher *lightFetcher 109 peers *peerSet 110 111 SubProtocols []p2p.Protocol 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 syncMu sync.Mutex 121 syncing bool 122 syncDone chan struct{} 123 124 // wait group is used for graceful shutdowns during downloading 125 // and processing 126 wg sync.WaitGroup 127 } 128 129 // NewProtocolManager returns a new ethereum sub protocol manager. The Ethereum sub protocol manages peers capable 130 // with the ethereum network. 131 func NewProtocolManager(chainConfig *params.ChainConfig, lightSync bool, networkId int, mux *event.TypeMux, pow pow.PoW, blockchain BlockChain, txpool txPool, chainDb ethdb.Database, odr *LesOdr, txrelay *LesTxRelay) (*ProtocolManager, error) { 132 // Create the protocol manager with the base fields 133 manager := &ProtocolManager{ 134 lightSync: lightSync, 135 eventMux: mux, 136 blockchain: blockchain, 137 chainConfig: chainConfig, 138 chainDb: chainDb, 139 networkId: networkId, 140 txpool: txpool, 141 txrelay: txrelay, 142 odr: odr, 143 peers: newPeerSet(), 144 newPeerCh: make(chan *peer), 145 quitSync: make(chan struct{}), 146 noMorePeers: make(chan struct{}), 147 } 148 // Initiate a sub-protocol for every implemented version we can handle 149 manager.SubProtocols = make([]p2p.Protocol, 0, len(ProtocolVersions)) 150 for i, version := range ProtocolVersions { 151 // Compatible, initialize the sub-protocol 152 version := version // Closure for the run 153 manager.SubProtocols = append(manager.SubProtocols, p2p.Protocol{ 154 Name: "les", 155 Version: version, 156 Length: ProtocolLengths[i], 157 Run: func(p *p2p.Peer, rw p2p.MsgReadWriter) error { 158 var entry *poolEntry 159 peer := manager.newPeer(int(version), networkId, p, rw) 160 if manager.serverPool != nil { 161 addr := p.RemoteAddr().(*net.TCPAddr) 162 entry = manager.serverPool.connect(peer, addr.IP, uint16(addr.Port)) 163 } 164 peer.poolEntry = entry 165 select { 166 case manager.newPeerCh <- peer: 167 manager.wg.Add(1) 168 defer manager.wg.Done() 169 err := manager.handle(peer) 170 if entry != nil { 171 manager.serverPool.disconnect(entry) 172 } 173 return err 174 case <-manager.quitSync: 175 if entry != nil { 176 manager.serverPool.disconnect(entry) 177 } 178 return p2p.DiscQuitting 179 } 180 }, 181 NodeInfo: func() interface{} { 182 return manager.NodeInfo() 183 }, 184 PeerInfo: func(id discover.NodeID) interface{} { 185 if p := manager.peers.Peer(fmt.Sprintf("%x", id[:8])); p != nil { 186 return p.Info() 187 } 188 return nil 189 }, 190 }) 191 } 192 if len(manager.SubProtocols) == 0 { 193 return nil, errIncompatibleConfig 194 } 195 196 removePeer := manager.removePeer 197 if disableClientRemovePeer { 198 removePeer = func(id string) {} 199 } 200 201 if lightSync { 202 glog.V(logger.Debug).Infof("LES: create downloader") 203 manager.downloader = downloader.New(downloader.LightSync, chainDb, manager.eventMux, blockchain.HasHeader, nil, blockchain.GetHeaderByHash, 204 nil, blockchain.CurrentHeader, nil, nil, nil, blockchain.GetTdByHash, 205 blockchain.InsertHeaderChain, nil, nil, blockchain.Rollback, removePeer) 206 } 207 208 if odr != nil { 209 odr.removePeer = removePeer 210 } 211 212 /*validator := func(block *types.Block, parent *types.Block) error { 213 return core.ValidateHeader(pow, block.Header(), parent.Header(), true, false) 214 } 215 heighter := func() uint64 { 216 return chainman.LastBlockNumberU64() 217 } 218 manager.fetcher = fetcher.New(chainman.GetBlockNoOdr, validator, nil, heighter, chainman.InsertChain, manager.removePeer) 219 */ 220 return manager, nil 221 } 222 223 func (pm *ProtocolManager) removePeer(id string) { 224 // Short circuit if the peer was already removed 225 peer := pm.peers.Peer(id) 226 if peer == nil { 227 return 228 } 229 if err := pm.peers.Unregister(id); err != nil { 230 if err == errNotRegistered { 231 return 232 } 233 glog.V(logger.Error).Infoln("Removal failed:", err) 234 } 235 glog.V(logger.Debug).Infoln("Removing peer", id) 236 237 // Unregister the peer from the downloader and Ethereum peer set 238 glog.V(logger.Debug).Infof("LES: unregister peer %v", id) 239 if pm.lightSync { 240 pm.downloader.UnregisterPeer(id) 241 if pm.txrelay != nil { 242 pm.txrelay.removePeer(id) 243 } 244 if pm.fetcher != nil { 245 pm.fetcher.removePeer(peer) 246 } 247 } 248 // Hard disconnect at the networking layer 249 if peer != nil { 250 peer.Peer.Disconnect(p2p.DiscUselessPeer) 251 } 252 } 253 254 func (pm *ProtocolManager) Start(srvr *p2p.Server) { 255 var topicDisc *discv5.Network 256 if srvr != nil { 257 topicDisc = srvr.DiscV5 258 } 259 lesTopic := discv5.Topic("LES@" + common.Bytes2Hex(pm.blockchain.Genesis().Hash().Bytes()[0:8])) 260 if pm.lightSync { 261 // start sync handler 262 if srvr != nil { // srvr is nil during testing 263 pm.serverPool = newServerPool(pm.chainDb, []byte("serverPool/"), srvr, lesTopic, pm.quitSync, &pm.wg) 264 pm.odr.serverPool = pm.serverPool 265 pm.fetcher = newLightFetcher(pm) 266 } 267 go pm.syncer() 268 } else { 269 if topicDisc != nil { 270 go func() { 271 glog.V(logger.Info).Infoln("Starting registering topic", string(lesTopic)) 272 topicDisc.RegisterTopic(lesTopic, pm.quitSync) 273 glog.V(logger.Info).Infoln("Stopped registering topic", string(lesTopic)) 274 }() 275 } 276 go func() { 277 for range pm.newPeerCh { 278 } 279 }() 280 } 281 } 282 283 func (pm *ProtocolManager) Stop() { 284 // Showing a log message. During download / process this could actually 285 // take between 5 to 10 seconds and therefor feedback is required. 286 glog.V(logger.Info).Infoln("Stopping light atheios protocol handler...") 287 288 // Quit the sync loop. 289 // After this send has completed, no new peers will be accepted. 290 pm.noMorePeers <- struct{}{} 291 292 close(pm.quitSync) // quits syncer, fetcher 293 294 // Disconnect existing sessions. 295 // This also closes the gate for any new registrations on the peer set. 296 // sessions which are already established but not added to pm.peers yet 297 // will exit when they try to register. 298 pm.peers.Close() 299 300 // Wait for any process action 301 pm.wg.Wait() 302 303 glog.V(logger.Info).Infoln("Light atheios protocol handler stopped") 304 } 305 306 func (pm *ProtocolManager) newPeer(pv, nv int, p *p2p.Peer, rw p2p.MsgReadWriter) *peer { 307 return newPeer(pv, nv, p, newMeteredMsgWriter(rw)) 308 } 309 310 // handle is the callback invoked to manage the life cycle of a les peer. When 311 // this function terminates, the peer is disconnected. 312 func (pm *ProtocolManager) handle(p *peer) error { 313 glog.V(logger.Debug).Infof("%v: peer connected [%s]", p, p.Name()) 314 315 // Execute the LES handshake 316 td, head, genesis := pm.blockchain.Status() 317 headNum := core.GetBlockNumber(pm.chainDb, head) 318 if err := p.Handshake(td, head, headNum, genesis, pm.server); err != nil { 319 glog.V(logger.Debug).Infof("%v: handshake failed: %v", p, err) 320 return err 321 } 322 if rw, ok := p.rw.(*meteredMsgReadWriter); ok { 323 rw.Init(p.version) 324 } 325 // Register the peer locally 326 glog.V(logger.Detail).Infof("%v: adding peer", p) 327 if err := pm.peers.Register(p); err != nil { 328 glog.V(logger.Error).Infof("%v: addition failed: %v", p, err) 329 return err 330 } 331 defer func() { 332 if pm.server != nil && pm.server.fcManager != nil && p.fcClient != nil { 333 p.fcClient.Remove(pm.server.fcManager) 334 } 335 pm.removePeer(p.id) 336 }() 337 338 // Register the peer in the downloader. If the downloader considers it banned, we disconnect 339 glog.V(logger.Debug).Infof("LES: register peer %v", p.id) 340 if pm.lightSync { 341 requestHeadersByHash := func(origin common.Hash, amount int, skip int, reverse bool) error { 342 reqID := getNextReqID() 343 cost := p.GetRequestCost(GetBlockHeadersMsg, amount) 344 p.fcServer.MustAssignRequest(reqID) 345 p.fcServer.SendRequest(reqID, cost) 346 return p.RequestHeadersByHash(reqID, cost, origin, amount, skip, reverse) 347 } 348 requestHeadersByNumber := func(origin uint64, amount int, skip int, reverse bool) error { 349 reqID := getNextReqID() 350 cost := p.GetRequestCost(GetBlockHeadersMsg, amount) 351 p.fcServer.MustAssignRequest(reqID) 352 p.fcServer.SendRequest(reqID, cost) 353 return p.RequestHeadersByNumber(reqID, cost, origin, amount, skip, reverse) 354 } 355 if err := pm.downloader.RegisterPeer(p.id, ethVersion, p.HeadAndTd, 356 requestHeadersByHash, requestHeadersByNumber, nil, nil, nil); err != nil { 357 return err 358 } 359 if pm.txrelay != nil { 360 pm.txrelay.addPeer(p) 361 } 362 363 p.lock.Lock() 364 head := p.headInfo 365 p.lock.Unlock() 366 if pm.fetcher != nil { 367 pm.fetcher.addPeer(p) 368 pm.fetcher.announce(p, head) 369 } 370 371 if p.poolEntry != nil { 372 pm.serverPool.registered(p.poolEntry) 373 } 374 } 375 376 stop := make(chan struct{}) 377 defer close(stop) 378 go func() { 379 // new block announce loop 380 for { 381 select { 382 case announce := <-p.announceChn: 383 p.SendAnnounce(announce) 384 case <-stop: 385 return 386 } 387 } 388 }() 389 390 // main loop. handle incoming messages. 391 for { 392 if err := pm.handleMsg(p); err != nil { 393 glog.V(logger.Debug).Infof("%v: message handling failed: %v", p, err) 394 return err 395 } 396 } 397 } 398 399 var reqList = []uint64{GetBlockHeadersMsg, GetBlockBodiesMsg, GetCodeMsg, GetReceiptsMsg, GetProofsMsg, SendTxMsg, GetHeaderProofsMsg} 400 401 // handleMsg is invoked whenever an inbound message is received from a remote 402 // peer. The remote connection is torn down upon returning any error. 403 func (pm *ProtocolManager) handleMsg(p *peer) error { 404 // Read the next message from the remote peer, and ensure it's fully consumed 405 msg, err := p.rw.ReadMsg() 406 if err != nil { 407 return err 408 } 409 410 glog.V(logger.Debug).Infoln("msg:", msg.Code, msg.Size) 411 412 costs := p.fcCosts[msg.Code] 413 reject := func(reqCnt, maxCnt uint64) bool { 414 if p.fcClient == nil || reqCnt > maxCnt { 415 return true 416 } 417 bufValue, _ := p.fcClient.AcceptRequest() 418 cost := costs.baseCost + reqCnt*costs.reqCost 419 if cost > pm.server.defParams.BufLimit { 420 cost = pm.server.defParams.BufLimit 421 } 422 if cost > bufValue { 423 glog.V(logger.Error).Infof("Request from %v came %v too early", p.id, time.Duration((cost-bufValue)*1000000/pm.server.defParams.MinRecharge)) 424 return true 425 } 426 return false 427 } 428 429 if msg.Size > ProtocolMaxMsgSize { 430 return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, ProtocolMaxMsgSize) 431 } 432 defer msg.Discard() 433 434 var deliverMsg *Msg 435 436 // Handle the message depending on its contents 437 switch msg.Code { 438 case StatusMsg: 439 glog.V(logger.Debug).Infof("<=== StatusMsg from peer %v", p.id) 440 // Status messages should never arrive after the handshake 441 return errResp(ErrExtraStatusMsg, "uncontrolled status message") 442 443 // Block header query, collect the requested headers and reply 444 case AnnounceMsg: 445 glog.V(logger.Debug).Infoln("<=== AnnounceMsg from peer %v:", p.id) 446 447 var req announceData 448 if err := msg.Decode(&req); err != nil { 449 return errResp(ErrDecode, "%v: %v", msg, err) 450 } 451 glog.V(logger.Detail).Infoln("AnnounceMsg:", req.Number, req.Hash, req.Td, req.ReorgDepth) 452 if pm.fetcher != nil { 453 pm.fetcher.announce(p, &req) 454 } 455 456 case GetBlockHeadersMsg: 457 glog.V(logger.Debug).Infof("<=== GetBlockHeadersMsg from peer %v", p.id) 458 // Decode the complex header query 459 var req struct { 460 ReqID uint64 461 Query getBlockHeadersData 462 } 463 if err := msg.Decode(&req); err != nil { 464 return errResp(ErrDecode, "%v: %v", msg, err) 465 } 466 467 query := req.Query 468 if reject(query.Amount, MaxHeaderFetch) { 469 return errResp(ErrRequestRejected, "") 470 } 471 472 hashMode := query.Origin.Hash != (common.Hash{}) 473 474 // Gather headers until the fetch or network limits is reached 475 var ( 476 bytes common.StorageSize 477 headers []*types.Header 478 unknown bool 479 ) 480 for !unknown && len(headers) < int(query.Amount) && bytes < softResponseLimit { 481 // Retrieve the next header satisfying the query 482 var origin *types.Header 483 if hashMode { 484 origin = pm.blockchain.GetHeaderByHash(query.Origin.Hash) 485 } else { 486 origin = pm.blockchain.GetHeaderByNumber(query.Origin.Number) 487 } 488 if origin == nil { 489 break 490 } 491 number := origin.Number.Uint64() 492 headers = append(headers, origin) 493 bytes += estHeaderRlpSize 494 495 // Advance to the next header of the query 496 switch { 497 case query.Origin.Hash != (common.Hash{}) && query.Reverse: 498 // Hash based traversal towards the genesis block 499 for i := 0; i < int(query.Skip)+1; i++ { 500 if header := pm.blockchain.GetHeader(query.Origin.Hash, number); header != nil { 501 query.Origin.Hash = header.ParentHash 502 number-- 503 } else { 504 unknown = true 505 break 506 } 507 } 508 case query.Origin.Hash != (common.Hash{}) && !query.Reverse: 509 // Hash based traversal towards the leaf block 510 if header := pm.blockchain.GetHeaderByNumber(origin.Number.Uint64() + query.Skip + 1); header != nil { 511 if pm.blockchain.GetBlockHashesFromHash(header.Hash(), query.Skip+1)[query.Skip] == query.Origin.Hash { 512 query.Origin.Hash = header.Hash() 513 } else { 514 unknown = true 515 } 516 } else { 517 unknown = true 518 } 519 case query.Reverse: 520 // Number based traversal towards the genesis block 521 if query.Origin.Number >= query.Skip+1 { 522 query.Origin.Number -= (query.Skip + 1) 523 } else { 524 unknown = true 525 } 526 527 case !query.Reverse: 528 // Number based traversal towards the leaf block 529 query.Origin.Number += (query.Skip + 1) 530 } 531 } 532 533 bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + query.Amount*costs.reqCost) 534 pm.server.fcCostStats.update(msg.Code, query.Amount, rcost) 535 return p.SendBlockHeaders(req.ReqID, bv, headers) 536 537 case BlockHeadersMsg: 538 if pm.downloader == nil { 539 return errResp(ErrUnexpectedResponse, "") 540 } 541 542 glog.V(logger.Debug).Infof("<=== BlockHeadersMsg from peer %v", p.id) 543 // A batch of headers arrived to one of our previous requests 544 var resp struct { 545 ReqID, BV uint64 546 Headers []*types.Header 547 } 548 if err := msg.Decode(&resp); err != nil { 549 return errResp(ErrDecode, "msg %v: %v", msg, err) 550 } 551 p.fcServer.GotReply(resp.ReqID, resp.BV) 552 if pm.fetcher != nil && pm.fetcher.requestedID(resp.ReqID) { 553 pm.fetcher.deliverHeaders(p, resp.ReqID, resp.Headers) 554 } else { 555 err := pm.downloader.DeliverHeaders(p.id, resp.Headers) 556 if err != nil { 557 glog.V(logger.Debug).Infoln(err) 558 } 559 } 560 561 case GetBlockBodiesMsg: 562 glog.V(logger.Debug).Infof("<=== GetBlockBodiesMsg from peer %v", p.id) 563 // Decode the retrieval message 564 var req struct { 565 ReqID uint64 566 Hashes []common.Hash 567 } 568 if err := msg.Decode(&req); err != nil { 569 return errResp(ErrDecode, "msg %v: %v", msg, err) 570 } 571 // Gather blocks until the fetch or network limits is reached 572 var ( 573 bytes int 574 bodies []rlp.RawValue 575 ) 576 reqCnt := len(req.Hashes) 577 if reject(uint64(reqCnt), MaxBodyFetch) { 578 return errResp(ErrRequestRejected, "") 579 } 580 for _, hash := range req.Hashes { 581 if bytes >= softResponseLimit { 582 break 583 } 584 // Retrieve the requested block body, stopping if enough was found 585 if data := core.GetBodyRLP(pm.chainDb, hash, core.GetBlockNumber(pm.chainDb, hash)); len(data) != 0 { 586 bodies = append(bodies, data) 587 bytes += len(data) 588 } 589 } 590 bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost) 591 pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost) 592 return p.SendBlockBodiesRLP(req.ReqID, bv, bodies) 593 594 case BlockBodiesMsg: 595 if pm.odr == nil { 596 return errResp(ErrUnexpectedResponse, "") 597 } 598 599 glog.V(logger.Debug).Infof("<=== BlockBodiesMsg from peer %v", p.id) 600 // A batch of block bodies arrived to one of our previous requests 601 var resp struct { 602 ReqID, BV uint64 603 Data []*types.Body 604 } 605 if err := msg.Decode(&resp); err != nil { 606 return errResp(ErrDecode, "msg %v: %v", msg, err) 607 } 608 p.fcServer.GotReply(resp.ReqID, resp.BV) 609 deliverMsg = &Msg{ 610 MsgType: MsgBlockBodies, 611 ReqID: resp.ReqID, 612 Obj: resp.Data, 613 } 614 615 case GetCodeMsg: 616 glog.V(logger.Debug).Infof("<=== GetCodeMsg from peer %v", p.id) 617 // Decode the retrieval message 618 var req struct { 619 ReqID uint64 620 Reqs []CodeReq 621 } 622 if err := msg.Decode(&req); err != nil { 623 return errResp(ErrDecode, "msg %v: %v", msg, err) 624 } 625 // Gather state data until the fetch or network limits is reached 626 var ( 627 bytes int 628 data [][]byte 629 ) 630 reqCnt := len(req.Reqs) 631 if reject(uint64(reqCnt), MaxCodeFetch) { 632 return errResp(ErrRequestRejected, "") 633 } 634 for _, req := range req.Reqs { 635 // Retrieve the requested state entry, stopping if enough was found 636 if header := core.GetHeader(pm.chainDb, req.BHash, core.GetBlockNumber(pm.chainDb, req.BHash)); header != nil { 637 if trie, _ := trie.New(header.Root, pm.chainDb); trie != nil { 638 sdata := trie.Get(req.AccKey) 639 var acc state.Account 640 if err := rlp.DecodeBytes(sdata, &acc); err == nil { 641 entry, _ := pm.chainDb.Get(acc.CodeHash) 642 if bytes+len(entry) >= softResponseLimit { 643 break 644 } 645 data = append(data, entry) 646 bytes += len(entry) 647 } 648 } 649 } 650 } 651 bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost) 652 pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost) 653 return p.SendCode(req.ReqID, bv, data) 654 655 case CodeMsg: 656 if pm.odr == nil { 657 return errResp(ErrUnexpectedResponse, "") 658 } 659 660 glog.V(logger.Debug).Infof("<=== CodeMsg from peer %v", p.id) 661 // A batch of node state data arrived to one of our previous requests 662 var resp struct { 663 ReqID, BV uint64 664 Data [][]byte 665 } 666 if err := msg.Decode(&resp); err != nil { 667 return errResp(ErrDecode, "msg %v: %v", msg, err) 668 } 669 p.fcServer.GotReply(resp.ReqID, resp.BV) 670 deliverMsg = &Msg{ 671 MsgType: MsgCode, 672 ReqID: resp.ReqID, 673 Obj: resp.Data, 674 } 675 676 case GetReceiptsMsg: 677 glog.V(logger.Debug).Infof("<=== GetReceiptsMsg from peer %v", p.id) 678 // Decode the retrieval message 679 var req struct { 680 ReqID uint64 681 Hashes []common.Hash 682 } 683 if err := msg.Decode(&req); err != nil { 684 return errResp(ErrDecode, "msg %v: %v", msg, err) 685 } 686 // Gather state data until the fetch or network limits is reached 687 var ( 688 bytes int 689 receipts []rlp.RawValue 690 ) 691 reqCnt := len(req.Hashes) 692 if reject(uint64(reqCnt), MaxReceiptFetch) { 693 return errResp(ErrRequestRejected, "") 694 } 695 for _, hash := range req.Hashes { 696 if bytes >= softResponseLimit { 697 break 698 } 699 // Retrieve the requested block's receipts, skipping if unknown to us 700 results := core.GetBlockReceipts(pm.chainDb, hash, core.GetBlockNumber(pm.chainDb, hash)) 701 if results == nil { 702 if header := pm.blockchain.GetHeaderByHash(hash); header == nil || header.ReceiptHash != types.EmptyRootHash { 703 continue 704 } 705 } 706 // If known, encode and queue for response packet 707 if encoded, err := rlp.EncodeToBytes(results); err != nil { 708 glog.V(logger.Error).Infof("failed to encode receipt: %v", err) 709 } else { 710 receipts = append(receipts, encoded) 711 bytes += len(encoded) 712 } 713 } 714 bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost) 715 pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost) 716 return p.SendReceiptsRLP(req.ReqID, bv, receipts) 717 718 case ReceiptsMsg: 719 if pm.odr == nil { 720 return errResp(ErrUnexpectedResponse, "") 721 } 722 723 glog.V(logger.Debug).Infof("<=== ReceiptsMsg from peer %v", p.id) 724 // A batch of receipts arrived to one of our previous requests 725 var resp struct { 726 ReqID, BV uint64 727 Receipts []types.Receipts 728 } 729 if err := msg.Decode(&resp); err != nil { 730 return errResp(ErrDecode, "msg %v: %v", msg, err) 731 } 732 p.fcServer.GotReply(resp.ReqID, resp.BV) 733 deliverMsg = &Msg{ 734 MsgType: MsgReceipts, 735 ReqID: resp.ReqID, 736 Obj: resp.Receipts, 737 } 738 739 case GetProofsMsg: 740 glog.V(logger.Debug).Infof("<=== GetProofsMsg from peer %v", p.id) 741 // Decode the retrieval message 742 var req struct { 743 ReqID uint64 744 Reqs []ProofReq 745 } 746 if err := msg.Decode(&req); err != nil { 747 return errResp(ErrDecode, "msg %v: %v", msg, err) 748 } 749 // Gather state data until the fetch or network limits is reached 750 var ( 751 bytes int 752 proofs proofsData 753 ) 754 reqCnt := len(req.Reqs) 755 if reject(uint64(reqCnt), MaxProofsFetch) { 756 return errResp(ErrRequestRejected, "") 757 } 758 for _, req := range req.Reqs { 759 if bytes >= softResponseLimit { 760 break 761 } 762 // Retrieve the requested state entry, stopping if enough was found 763 if header := core.GetHeader(pm.chainDb, req.BHash, core.GetBlockNumber(pm.chainDb, req.BHash)); header != nil { 764 if tr, _ := trie.New(header.Root, pm.chainDb); tr != nil { 765 if len(req.AccKey) > 0 { 766 sdata := tr.Get(req.AccKey) 767 tr = nil 768 var acc state.Account 769 if err := rlp.DecodeBytes(sdata, &acc); err == nil { 770 tr, _ = trie.New(acc.Root, pm.chainDb) 771 } 772 } 773 if tr != nil { 774 proof := tr.Prove(req.Key) 775 proofs = append(proofs, proof) 776 bytes += len(proof) 777 } 778 } 779 } 780 } 781 bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost) 782 pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost) 783 return p.SendProofs(req.ReqID, bv, proofs) 784 785 case ProofsMsg: 786 if pm.odr == nil { 787 return errResp(ErrUnexpectedResponse, "") 788 } 789 790 glog.V(logger.Debug).Infof("<=== ProofsMsg from peer %v", p.id) 791 // A batch of merkle proofs arrived to one of our previous requests 792 var resp struct { 793 ReqID, BV uint64 794 Data [][]rlp.RawValue 795 } 796 if err := msg.Decode(&resp); err != nil { 797 return errResp(ErrDecode, "msg %v: %v", msg, err) 798 } 799 p.fcServer.GotReply(resp.ReqID, resp.BV) 800 deliverMsg = &Msg{ 801 MsgType: MsgProofs, 802 ReqID: resp.ReqID, 803 Obj: resp.Data, 804 } 805 806 case GetHeaderProofsMsg: 807 glog.V(logger.Debug).Infof("<=== GetHeaderProofsMsg from peer %v", p.id) 808 // Decode the retrieval message 809 var req struct { 810 ReqID uint64 811 Reqs []ChtReq 812 } 813 if err := msg.Decode(&req); err != nil { 814 return errResp(ErrDecode, "msg %v: %v", msg, err) 815 } 816 // Gather state data until the fetch or network limits is reached 817 var ( 818 bytes int 819 proofs []ChtResp 820 ) 821 reqCnt := len(req.Reqs) 822 if reject(uint64(reqCnt), MaxHeaderProofsFetch) { 823 return errResp(ErrRequestRejected, "") 824 } 825 for _, req := range req.Reqs { 826 if bytes >= softResponseLimit { 827 break 828 } 829 830 if header := pm.blockchain.GetHeaderByNumber(req.BlockNum); header != nil { 831 if root := getChtRoot(pm.chainDb, req.ChtNum); root != (common.Hash{}) { 832 if tr, _ := trie.New(root, pm.chainDb); tr != nil { 833 var encNumber [8]byte 834 binary.BigEndian.PutUint64(encNumber[:], req.BlockNum) 835 proof := tr.Prove(encNumber[:]) 836 proofs = append(proofs, ChtResp{Header: header, Proof: proof}) 837 bytes += len(proof) + estHeaderRlpSize 838 } 839 } 840 } 841 } 842 bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost) 843 pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost) 844 return p.SendHeaderProofs(req.ReqID, bv, proofs) 845 846 case HeaderProofsMsg: 847 if pm.odr == nil { 848 return errResp(ErrUnexpectedResponse, "") 849 } 850 851 glog.V(logger.Debug).Infof("<=== HeaderProofsMsg from peer %v", p.id) 852 var resp struct { 853 ReqID, BV uint64 854 Data []ChtResp 855 } 856 if err := msg.Decode(&resp); err != nil { 857 return errResp(ErrDecode, "msg %v: %v", msg, err) 858 } 859 p.fcServer.GotReply(resp.ReqID, resp.BV) 860 deliverMsg = &Msg{ 861 MsgType: MsgHeaderProofs, 862 ReqID: resp.ReqID, 863 Obj: resp.Data, 864 } 865 866 case SendTxMsg: 867 if pm.txpool == nil { 868 return errResp(ErrUnexpectedResponse, "") 869 } 870 // Transactions arrived, parse all of them and deliver to the pool 871 var txs []*types.Transaction 872 if err := msg.Decode(&txs); err != nil { 873 return errResp(ErrDecode, "msg %v: %v", msg, err) 874 } 875 reqCnt := len(txs) 876 if reject(uint64(reqCnt), MaxTxSend) { 877 return errResp(ErrRequestRejected, "") 878 } 879 880 if err := pm.txpool.AddBatch(txs); err != nil { 881 return errResp(ErrUnexpectedResponse, "msg: %v", err) 882 } 883 884 _, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost) 885 pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost) 886 887 default: 888 glog.V(logger.Debug).Infof("<=== unknown message with code %d from peer %v", msg.Code, p.id) 889 return errResp(ErrInvalidMsgCode, "%v", msg.Code) 890 } 891 892 if deliverMsg != nil { 893 return pm.odr.Deliver(p, deliverMsg) 894 } 895 896 return nil 897 } 898 899 // NodeInfo retrieves some protocol metadata about the running host node. 900 func (self *ProtocolManager) NodeInfo() *eth.EthNodeInfo { 901 return ð.EthNodeInfo{ 902 Network: self.networkId, 903 Difficulty: self.blockchain.GetTdByHash(self.blockchain.LastBlockHash()), 904 Genesis: self.blockchain.Genesis().Hash(), 905 Head: self.blockchain.LastBlockHash(), 906 } 907 }