github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/les/handler.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 19:16:38</date> 10 //</624450093986091008> 11 12 13 //包les实现轻以太坊子协议。 14 package les 15 16 import ( 17 "encoding/binary" 18 "encoding/json" 19 "fmt" 20 "math/big" 21 "net" 22 "sync" 23 "time" 24 25 "github.com/ethereum/go-ethereum/common" 26 "github.com/ethereum/go-ethereum/common/mclock" 27 "github.com/ethereum/go-ethereum/consensus" 28 "github.com/ethereum/go-ethereum/core" 29 "github.com/ethereum/go-ethereum/core/rawdb" 30 "github.com/ethereum/go-ethereum/core/state" 31 "github.com/ethereum/go-ethereum/core/types" 32 "github.com/ethereum/go-ethereum/eth/downloader" 33 "github.com/ethereum/go-ethereum/ethdb" 34 "github.com/ethereum/go-ethereum/event" 35 "github.com/ethereum/go-ethereum/light" 36 "github.com/ethereum/go-ethereum/log" 37 "github.com/ethereum/go-ethereum/p2p" 38 "github.com/ethereum/go-ethereum/p2p/discv5" 39 "github.com/ethereum/go-ethereum/params" 40 "github.com/ethereum/go-ethereum/rlp" 41 "github.com/ethereum/go-ethereum/trie" 42 ) 43 44 const ( 45 softResponseLimit = 2 * 1024 * 1024 //返回的块、头或节点数据的目标最大大小。 46 estHeaderRlpSize = 500 //RLP编码块头的近似大小 47 48 ethVersion = 63 //下载器的等效ETH版本 49 50 MaxHeaderFetch = 192 //每个检索请求要获取的块头的数量 51 MaxBodyFetch = 32 //每个检索请求要获取的块体数量 52 MaxReceiptFetch = 128 //允许每个请求提取的事务处理收据的数量 53 MaxCodeFetch = 64 //允许按请求提取的合同代码量 54 MaxProofsFetch = 64 //每个检索请求要获取的Merkle证明的数量 55 MaxHelperTrieProofsFetch = 64 //每个检索请求要获取的Merkle证明的数量 56 MaxTxSend = 64 //每个请求发送的事务量 57 MaxTxStatus = 256 //每个请求要查询的事务量 58 59 disableClientRemovePeer = false 60 ) 61 62 func errResp(code errCode, format string, v ...interface{}) error { 63 return fmt.Errorf("%v - %v", code, fmt.Sprintf(format, v...)) 64 } 65 66 type BlockChain interface { 67 Config() *params.ChainConfig 68 HasHeader(hash common.Hash, number uint64) bool 69 GetHeader(hash common.Hash, number uint64) *types.Header 70 GetHeaderByHash(hash common.Hash) *types.Header 71 CurrentHeader() *types.Header 72 GetTd(hash common.Hash, number uint64) *big.Int 73 State() (*state.StateDB, error) 74 InsertHeaderChain(chain []*types.Header, checkFreq int) (int, error) 75 Rollback(chain []common.Hash) 76 GetHeaderByNumber(number uint64) *types.Header 77 GetAncestor(hash common.Hash, number, ancestor uint64, maxNonCanonical *uint64) (common.Hash, uint64) 78 Genesis() *types.Block 79 SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription 80 } 81 82 type txPool interface { 83 AddRemotes(txs []*types.Transaction) []error 84 Status(hashes []common.Hash) []core.TxStatus 85 } 86 87 type ProtocolManager struct { 88 lightSync bool 89 txpool txPool 90 txrelay *LesTxRelay 91 networkId uint64 92 chainConfig *params.ChainConfig 93 iConfig *light.IndexerConfig 94 blockchain BlockChain 95 chainDb ethdb.Database 96 odr *LesOdr 97 server *LesServer 98 serverPool *serverPool 99 clientPool *freeClientPool 100 lesTopic discv5.Topic 101 reqDist *requestDistributor 102 retriever *retrieveManager 103 104 downloader *downloader.Downloader 105 fetcher *lightFetcher 106 peers *peerSet 107 maxPeers int 108 109 eventMux *event.TypeMux 110 111 //获取器、同步器、TxSyncLoop的通道 112 newPeerCh chan *peer 113 quitSync chan struct{} 114 noMorePeers chan struct{} 115 116 //等待组用于在下载过程中正常关闭 117 //加工 118 wg *sync.WaitGroup 119 } 120 121 //NewProtocolManager返回新的以太坊子协议管理器。以太坊子协议管理对等端 122 //使用以太坊网络。 123 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) { 124 //使用基本字段创建协议管理器 125 manager := &ProtocolManager{ 126 lightSync: lightSync, 127 eventMux: mux, 128 blockchain: blockchain, 129 chainConfig: chainConfig, 130 iConfig: indexerConfig, 131 chainDb: chainDb, 132 odr: odr, 133 networkId: networkId, 134 txpool: txpool, 135 txrelay: txrelay, 136 serverPool: serverPool, 137 peers: peers, 138 newPeerCh: make(chan *peer), 139 quitSync: quitSync, 140 wg: wg, 141 noMorePeers: make(chan struct{}), 142 } 143 if odr != nil { 144 manager.retriever = odr.retriever 145 manager.reqDist = odr.retriever.dist 146 } 147 148 removePeer := manager.removePeer 149 if disableClientRemovePeer { 150 removePeer = func(id string) {} 151 } 152 153 if lightSync { 154 manager.downloader = downloader.New(downloader.LightSync, chainDb, manager.eventMux, nil, blockchain, removePeer) 155 manager.peers.notify((*downloaderPeerNotify)(manager)) 156 manager.fetcher = newLightFetcher(manager) 157 } 158 159 return manager, nil 160 } 161 162 //removepeer通过从对等端集删除对等端来启动与对等端的断开连接。 163 func (pm *ProtocolManager) removePeer(id string) { 164 pm.peers.Unregister(id) 165 } 166 167 func (pm *ProtocolManager) Start(maxPeers int) { 168 pm.maxPeers = maxPeers 169 170 if pm.lightSync { 171 go pm.syncer() 172 } else { 173 pm.clientPool = newFreeClientPool(pm.chainDb, maxPeers, 10000, mclock.System{}) 174 go func() { 175 for range pm.newPeerCh { 176 } 177 }() 178 } 179 } 180 181 func (pm *ProtocolManager) Stop() { 182 //显示日志消息。在下载/处理过程中,实际上 183 //需要5到10秒,因此需要反馈。 184 log.Info("Stopping light Ethereum protocol") 185 186 //退出同步循环。 187 //完成此发送后,将不接受任何新对等方。 188 pm.noMorePeers <- struct{}{} 189 190 close(pm.quitSync) //退出同步器,获取器 191 if pm.clientPool != nil { 192 pm.clientPool.stop() 193 } 194 195 //断开现有会话。 196 //这也会关闭对等集上任何新注册的入口。 197 //已建立但尚未添加到pm.peers的会话 198 //当他们尝试注册时将退出。 199 pm.peers.Close() 200 201 //等待任何进程操作 202 pm.wg.Wait() 203 204 log.Info("Light Ethereum protocol stopped") 205 } 206 207 //runpeer是给定版本的p2p协议运行函数。 208 func (pm *ProtocolManager) runPeer(version uint, p *p2p.Peer, rw p2p.MsgReadWriter) error { 209 var entry *poolEntry 210 peer := pm.newPeer(int(version), pm.networkId, p, rw) 211 if pm.serverPool != nil { 212 entry = pm.serverPool.connect(peer, peer.Node()) 213 } 214 peer.poolEntry = entry 215 select { 216 case pm.newPeerCh <- peer: 217 pm.wg.Add(1) 218 defer pm.wg.Done() 219 err := pm.handle(peer) 220 if entry != nil { 221 pm.serverPool.disconnect(entry) 222 } 223 return err 224 case <-pm.quitSync: 225 if entry != nil { 226 pm.serverPool.disconnect(entry) 227 } 228 return p2p.DiscQuitting 229 } 230 } 231 232 func (pm *ProtocolManager) newPeer(pv int, nv uint64, p *p2p.Peer, rw p2p.MsgReadWriter) *peer { 233 return newPeer(pv, nv, p, newMeteredMsgWriter(rw)) 234 } 235 236 //handle是为管理LES对等机的生命周期而调用的回调。什么时候? 237 //此函数终止,对等端断开连接。 238 func (pm *ProtocolManager) handle(p *peer) error { 239 //如果这是受信任的对等,则忽略MaxPeers 240 //在服务器模式下,我们尝试在握手后签入客户端池 241 if pm.lightSync && pm.peers.Len() >= pm.maxPeers && !p.Peer.Info().Network.Trusted { 242 return p2p.DiscTooManyPeers 243 } 244 245 p.Log().Debug("Light Ethereum peer connected", "name", p.Name()) 246 247 //执行LES握手 248 var ( 249 genesis = pm.blockchain.Genesis() 250 head = pm.blockchain.CurrentHeader() 251 hash = head.Hash() 252 number = head.Number.Uint64() 253 td = pm.blockchain.GetTd(hash, number) 254 ) 255 if err := p.Handshake(td, hash, number, genesis.Hash(), pm.server); err != nil { 256 p.Log().Debug("Light Ethereum handshake failed", "err", err) 257 return err 258 } 259 260 if !pm.lightSync && !p.Peer.Info().Network.Trusted { 261 addr, ok := p.RemoteAddr().(*net.TCPAddr) 262 //测试对等地址不是TCP地址,如果无法进行类型转换,则不使用客户端池 263 if ok { 264 id := addr.IP.String() 265 if !pm.clientPool.connect(id, func() { go pm.removePeer(p.id) }) { 266 return p2p.DiscTooManyPeers 267 } 268 defer pm.clientPool.disconnect(id) 269 } 270 } 271 272 if rw, ok := p.rw.(*meteredMsgReadWriter); ok { 273 rw.Init(p.version) 274 } 275 //在本地注册对等机 276 if err := pm.peers.Register(p); err != nil { 277 p.Log().Error("Light Ethereum peer registration failed", "err", err) 278 return err 279 } 280 defer func() { 281 if pm.server != nil && pm.server.fcManager != nil && p.fcClient != nil { 282 p.fcClient.Remove(pm.server.fcManager) 283 } 284 pm.removePeer(p.id) 285 }() 286 //在下载程序中注册对等点。如果下载者认为它是被禁止的,我们会断开 287 if pm.lightSync { 288 p.lock.Lock() 289 head := p.headInfo 290 p.lock.Unlock() 291 if pm.fetcher != nil { 292 pm.fetcher.announce(p, head) 293 } 294 295 if p.poolEntry != nil { 296 pm.serverPool.registered(p.poolEntry) 297 } 298 } 299 300 stop := make(chan struct{}) 301 defer close(stop) 302 go func() { 303 //新块通知循环 304 for { 305 select { 306 case announce := <-p.announceChn: 307 p.SendAnnounce(announce) 308 case <-stop: 309 return 310 } 311 } 312 }() 313 314 //主回路。处理传入消息。 315 for { 316 if err := pm.handleMsg(p); err != nil { 317 p.Log().Debug("Light Ethereum message handling failed", "err", err) 318 return err 319 } 320 } 321 } 322 323 var reqList = []uint64{GetBlockHeadersMsg, GetBlockBodiesMsg, GetCodeMsg, GetReceiptsMsg, GetProofsV1Msg, SendTxMsg, SendTxV2Msg, GetTxStatusMsg, GetHeaderProofsMsg, GetProofsV2Msg, GetHelperTrieProofsMsg} 324 325 //每当从远程服务器接收到入站消息时,将调用handlemsg。 326 //同龄人。返回任何错误时,远程连接被断开。 327 func (pm *ProtocolManager) handleMsg(p *peer) error { 328 //从远程对等端读取下一条消息,并确保它被完全消耗掉。 329 msg, err := p.rw.ReadMsg() 330 if err != nil { 331 return err 332 } 333 p.Log().Trace("Light Ethereum message arrived", "code", msg.Code, "bytes", msg.Size) 334 335 costs := p.fcCosts[msg.Code] 336 reject := func(reqCnt, maxCnt uint64) bool { 337 if p.fcClient == nil || reqCnt > maxCnt { 338 return true 339 } 340 bufValue, _ := p.fcClient.AcceptRequest() 341 cost := costs.baseCost + reqCnt*costs.reqCost 342 if cost > pm.server.defParams.BufLimit { 343 cost = pm.server.defParams.BufLimit 344 } 345 if cost > bufValue { 346 recharge := time.Duration((cost - bufValue) * 1000000 / pm.server.defParams.MinRecharge) 347 p.Log().Error("Request came too early", "recharge", common.PrettyDuration(recharge)) 348 return true 349 } 350 return false 351 } 352 353 if msg.Size > ProtocolMaxMsgSize { 354 return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, ProtocolMaxMsgSize) 355 } 356 defer msg.Discard() 357 358 var deliverMsg *Msg 359 360 //根据消息的内容处理消息 361 switch msg.Code { 362 case StatusMsg: 363 p.Log().Trace("Received status message") 364 //状态消息不应在握手后到达 365 return errResp(ErrExtraStatusMsg, "uncontrolled status message") 366 367 //阻止头查询,收集请求的头并答复 368 case AnnounceMsg: 369 p.Log().Trace("Received announce message") 370 if p.requestAnnounceType == announceTypeNone { 371 return errResp(ErrUnexpectedResponse, "") 372 } 373 374 var req announceData 375 if err := msg.Decode(&req); err != nil { 376 return errResp(ErrDecode, "%v: %v", msg, err) 377 } 378 379 if p.requestAnnounceType == announceTypeSigned { 380 if err := req.checkSignature(p.ID()); err != nil { 381 p.Log().Trace("Invalid announcement signature", "err", err) 382 return err 383 } 384 p.Log().Trace("Valid announcement signature") 385 } 386 387 p.Log().Trace("Announce message content", "number", req.Number, "hash", req.Hash, "td", req.Td, "reorg", req.ReorgDepth) 388 if pm.fetcher != nil { 389 pm.fetcher.announce(p, &req) 390 } 391 392 case GetBlockHeadersMsg: 393 p.Log().Trace("Received block header request") 394 //解码复杂的头查询 395 var req struct { 396 ReqID uint64 397 Query getBlockHeadersData 398 } 399 if err := msg.Decode(&req); err != nil { 400 return errResp(ErrDecode, "%v: %v", msg, err) 401 } 402 403 query := req.Query 404 if reject(query.Amount, MaxHeaderFetch) { 405 return errResp(ErrRequestRejected, "") 406 } 407 408 hashMode := query.Origin.Hash != (common.Hash{}) 409 first := true 410 maxNonCanonical := uint64(100) 411 412 //收集邮件头,直到达到提取或网络限制 413 var ( 414 bytes common.StorageSize 415 headers []*types.Header 416 unknown bool 417 ) 418 for !unknown && len(headers) < int(query.Amount) && bytes < softResponseLimit { 419 //检索满足查询的下一个标题 420 var origin *types.Header 421 if hashMode { 422 if first { 423 first = false 424 origin = pm.blockchain.GetHeaderByHash(query.Origin.Hash) 425 if origin != nil { 426 query.Origin.Number = origin.Number.Uint64() 427 } 428 } else { 429 origin = pm.blockchain.GetHeader(query.Origin.Hash, query.Origin.Number) 430 } 431 } else { 432 origin = pm.blockchain.GetHeaderByNumber(query.Origin.Number) 433 } 434 if origin == nil { 435 break 436 } 437 headers = append(headers, origin) 438 bytes += estHeaderRlpSize 439 440 //前进到查询的下一个标题 441 switch { 442 case hashMode && query.Reverse: 443 //向Genesis块的基于哈希的遍历 444 ancestor := query.Skip + 1 445 if ancestor == 0 { 446 unknown = true 447 } else { 448 query.Origin.Hash, query.Origin.Number = pm.blockchain.GetAncestor(query.Origin.Hash, query.Origin.Number, ancestor, &maxNonCanonical) 449 unknown = (query.Origin.Hash == common.Hash{}) 450 } 451 case hashMode && !query.Reverse: 452 //基于哈希的叶块遍历 453 var ( 454 current = origin.Number.Uint64() 455 next = current + query.Skip + 1 456 ) 457 if next <= current { 458 infos, _ := json.MarshalIndent(p.Peer.Info(), "", " ") 459 p.Log().Warn("GetBlockHeaders skip overflow attack", "current", current, "skip", query.Skip, "next", next, "attacker", infos) 460 unknown = true 461 } else { 462 if header := pm.blockchain.GetHeaderByNumber(next); header != nil { 463 nextHash := header.Hash() 464 expOldHash, _ := pm.blockchain.GetAncestor(nextHash, next, query.Skip+1, &maxNonCanonical) 465 if expOldHash == query.Origin.Hash { 466 query.Origin.Hash, query.Origin.Number = nextHash, next 467 } else { 468 unknown = true 469 } 470 } else { 471 unknown = true 472 } 473 } 474 case query.Reverse: 475 //朝向Genesis区块的基于数字的遍历 476 if query.Origin.Number >= query.Skip+1 { 477 query.Origin.Number -= query.Skip + 1 478 } else { 479 unknown = true 480 } 481 482 case !query.Reverse: 483 //面向叶块的基于数字的遍历 484 query.Origin.Number += query.Skip + 1 485 } 486 } 487 488 bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + query.Amount*costs.reqCost) 489 pm.server.fcCostStats.update(msg.Code, query.Amount, rcost) 490 return p.SendBlockHeaders(req.ReqID, bv, headers) 491 492 case BlockHeadersMsg: 493 if pm.downloader == nil { 494 return errResp(ErrUnexpectedResponse, "") 495 } 496 497 p.Log().Trace("Received block header response message") 498 //我们以前的一个请求收到了一批头文件 499 var resp struct { 500 ReqID, BV uint64 501 Headers []*types.Header 502 } 503 if err := msg.Decode(&resp); err != nil { 504 return errResp(ErrDecode, "msg %v: %v", msg, err) 505 } 506 p.fcServer.GotReply(resp.ReqID, resp.BV) 507 if pm.fetcher != nil && pm.fetcher.requestedID(resp.ReqID) { 508 pm.fetcher.deliverHeaders(p, resp.ReqID, resp.Headers) 509 } else { 510 err := pm.downloader.DeliverHeaders(p.id, resp.Headers) 511 if err != nil { 512 log.Debug(fmt.Sprint(err)) 513 } 514 } 515 516 case GetBlockBodiesMsg: 517 p.Log().Trace("Received block bodies request") 518 //解码检索消息 519 var req struct { 520 ReqID uint64 521 Hashes []common.Hash 522 } 523 if err := msg.Decode(&req); err != nil { 524 return errResp(ErrDecode, "msg %v: %v", msg, err) 525 } 526 //收集块,直到达到获取或网络限制 527 var ( 528 bytes int 529 bodies []rlp.RawValue 530 ) 531 reqCnt := len(req.Hashes) 532 if reject(uint64(reqCnt), MaxBodyFetch) { 533 return errResp(ErrRequestRejected, "") 534 } 535 for _, hash := range req.Hashes { 536 if bytes >= softResponseLimit { 537 break 538 } 539 //检索请求的块体,如果找到足够的块体,则停止 540 if number := rawdb.ReadHeaderNumber(pm.chainDb, hash); number != nil { 541 if data := rawdb.ReadBodyRLP(pm.chainDb, hash, *number); len(data) != 0 { 542 bodies = append(bodies, data) 543 bytes += len(data) 544 } 545 } 546 } 547 bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost) 548 pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost) 549 return p.SendBlockBodiesRLP(req.ReqID, bv, bodies) 550 551 case BlockBodiesMsg: 552 if pm.odr == nil { 553 return errResp(ErrUnexpectedResponse, "") 554 } 555 556 p.Log().Trace("Received block bodies response") 557 //我们以前的一个要求得到了一批尸体。 558 var resp struct { 559 ReqID, BV uint64 560 Data []*types.Body 561 } 562 if err := msg.Decode(&resp); err != nil { 563 return errResp(ErrDecode, "msg %v: %v", msg, err) 564 } 565 p.fcServer.GotReply(resp.ReqID, resp.BV) 566 deliverMsg = &Msg{ 567 MsgType: MsgBlockBodies, 568 ReqID: resp.ReqID, 569 Obj: resp.Data, 570 } 571 572 case GetCodeMsg: 573 p.Log().Trace("Received code request") 574 //解码检索消息 575 var req struct { 576 ReqID uint64 577 Reqs []CodeReq 578 } 579 if err := msg.Decode(&req); err != nil { 580 return errResp(ErrDecode, "msg %v: %v", msg, err) 581 } 582 //收集状态数据,直到达到提取或网络限制 583 var ( 584 bytes int 585 data [][]byte 586 ) 587 reqCnt := len(req.Reqs) 588 if reject(uint64(reqCnt), MaxCodeFetch) { 589 return errResp(ErrRequestRejected, "") 590 } 591 for _, req := range req.Reqs { 592 //检索请求的状态项,如果找到足够的,则停止 593 if number := rawdb.ReadHeaderNumber(pm.chainDb, req.BHash); number != nil { 594 if header := rawdb.ReadHeader(pm.chainDb, req.BHash, *number); header != nil { 595 statedb, err := pm.blockchain.State() 596 if err != nil { 597 continue 598 } 599 account, err := pm.getAccount(statedb, header.Root, common.BytesToHash(req.AccKey)) 600 if err != nil { 601 continue 602 } 603 code, _ := statedb.Database().TrieDB().Node(common.BytesToHash(account.CodeHash)) 604 605 data = append(data, code) 606 if bytes += len(code); bytes >= softResponseLimit { 607 break 608 } 609 } 610 } 611 } 612 bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost) 613 pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost) 614 return p.SendCode(req.ReqID, bv, data) 615 616 case CodeMsg: 617 if pm.odr == nil { 618 return errResp(ErrUnexpectedResponse, "") 619 } 620 621 p.Log().Trace("Received code response") 622 //一批节点状态数据到达了我们以前的一个请求 623 var resp struct { 624 ReqID, BV uint64 625 Data [][]byte 626 } 627 if err := msg.Decode(&resp); err != nil { 628 return errResp(ErrDecode, "msg %v: %v", msg, err) 629 } 630 p.fcServer.GotReply(resp.ReqID, resp.BV) 631 deliverMsg = &Msg{ 632 MsgType: MsgCode, 633 ReqID: resp.ReqID, 634 Obj: resp.Data, 635 } 636 637 case GetReceiptsMsg: 638 p.Log().Trace("Received receipts request") 639 //解码检索消息 640 var req struct { 641 ReqID uint64 642 Hashes []common.Hash 643 } 644 if err := msg.Decode(&req); err != nil { 645 return errResp(ErrDecode, "msg %v: %v", msg, err) 646 } 647 //收集状态数据,直到达到提取或网络限制 648 var ( 649 bytes int 650 receipts []rlp.RawValue 651 ) 652 reqCnt := len(req.Hashes) 653 if reject(uint64(reqCnt), MaxReceiptFetch) { 654 return errResp(ErrRequestRejected, "") 655 } 656 for _, hash := range req.Hashes { 657 if bytes >= softResponseLimit { 658 break 659 } 660 //检索请求块的收据,如果我们不知道,则跳过 661 var results types.Receipts 662 if number := rawdb.ReadHeaderNumber(pm.chainDb, hash); number != nil { 663 results = rawdb.ReadReceipts(pm.chainDb, hash, *number) 664 } 665 if results == nil { 666 if header := pm.blockchain.GetHeaderByHash(hash); header == nil || header.ReceiptHash != types.EmptyRootHash { 667 continue 668 } 669 } 670 //如果已知,则对响应数据包进行编码和排队 671 if encoded, err := rlp.EncodeToBytes(results); err != nil { 672 log.Error("Failed to encode receipt", "err", err) 673 } else { 674 receipts = append(receipts, encoded) 675 bytes += len(encoded) 676 } 677 } 678 bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost) 679 pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost) 680 return p.SendReceiptsRLP(req.ReqID, bv, receipts) 681 682 case ReceiptsMsg: 683 if pm.odr == nil { 684 return errResp(ErrUnexpectedResponse, "") 685 } 686 687 p.Log().Trace("Received receipts response") 688 //我们以前的一个请求收到了一批收据 689 var resp struct { 690 ReqID, BV uint64 691 Receipts []types.Receipts 692 } 693 if err := msg.Decode(&resp); err != nil { 694 return errResp(ErrDecode, "msg %v: %v", msg, err) 695 } 696 p.fcServer.GotReply(resp.ReqID, resp.BV) 697 deliverMsg = &Msg{ 698 MsgType: MsgReceipts, 699 ReqID: resp.ReqID, 700 Obj: resp.Receipts, 701 } 702 703 case GetProofsV1Msg: 704 p.Log().Trace("Received proofs request") 705 //解码检索消息 706 var req struct { 707 ReqID uint64 708 Reqs []ProofReq 709 } 710 if err := msg.Decode(&req); err != nil { 711 return errResp(ErrDecode, "msg %v: %v", msg, err) 712 } 713 //收集状态数据,直到达到提取或网络限制 714 var ( 715 bytes int 716 proofs proofsData 717 ) 718 reqCnt := len(req.Reqs) 719 if reject(uint64(reqCnt), MaxProofsFetch) { 720 return errResp(ErrRequestRejected, "") 721 } 722 for _, req := range req.Reqs { 723 //检索请求的状态项,如果找到足够的,则停止 724 if number := rawdb.ReadHeaderNumber(pm.chainDb, req.BHash); number != nil { 725 if header := rawdb.ReadHeader(pm.chainDb, req.BHash, *number); header != nil { 726 statedb, err := pm.blockchain.State() 727 if err != nil { 728 continue 729 } 730 var trie state.Trie 731 if len(req.AccKey) > 0 { 732 account, err := pm.getAccount(statedb, header.Root, common.BytesToHash(req.AccKey)) 733 if err != nil { 734 continue 735 } 736 trie, _ = statedb.Database().OpenStorageTrie(common.BytesToHash(req.AccKey), account.Root) 737 } else { 738 trie, _ = statedb.Database().OpenTrie(header.Root) 739 } 740 if trie != nil { 741 var proof light.NodeList 742 trie.Prove(req.Key, 0, &proof) 743 744 proofs = append(proofs, proof) 745 if bytes += proof.DataSize(); bytes >= softResponseLimit { 746 break 747 } 748 } 749 } 750 } 751 } 752 bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost) 753 pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost) 754 return p.SendProofs(req.ReqID, bv, proofs) 755 756 case GetProofsV2Msg: 757 p.Log().Trace("Received les/2 proofs request") 758 //解码检索消息 759 var req struct { 760 ReqID uint64 761 Reqs []ProofReq 762 } 763 if err := msg.Decode(&req); err != nil { 764 return errResp(ErrDecode, "msg %v: %v", msg, err) 765 } 766 //收集状态数据,直到达到提取或网络限制 767 var ( 768 lastBHash common.Hash 769 statedb *state.StateDB 770 root common.Hash 771 ) 772 reqCnt := len(req.Reqs) 773 if reject(uint64(reqCnt), MaxProofsFetch) { 774 return errResp(ErrRequestRejected, "") 775 } 776 777 nodes := light.NewNodeSet() 778 779 for _, req := range req.Reqs { 780 //查找属于请求的状态 781 if statedb == nil || req.BHash != lastBHash { 782 statedb, root, lastBHash = nil, common.Hash{}, req.BHash 783 784 if number := rawdb.ReadHeaderNumber(pm.chainDb, req.BHash); number != nil { 785 if header := rawdb.ReadHeader(pm.chainDb, req.BHash, *number); header != nil { 786 statedb, _ = pm.blockchain.State() 787 root = header.Root 788 } 789 } 790 } 791 if statedb == nil { 792 continue 793 } 794 //提取请求的帐户或存储检索 795 var trie state.Trie 796 if len(req.AccKey) > 0 { 797 account, err := pm.getAccount(statedb, root, common.BytesToHash(req.AccKey)) 798 if err != nil { 799 continue 800 } 801 trie, _ = statedb.Database().OpenStorageTrie(common.BytesToHash(req.AccKey), account.Root) 802 } else { 803 trie, _ = statedb.Database().OpenTrie(root) 804 } 805 if trie == nil { 806 continue 807 } 808 //从帐户或stroage trie证明用户的请求 809 trie.Prove(req.Key, req.FromLevel, nodes) 810 if nodes.DataSize() >= softResponseLimit { 811 break 812 } 813 } 814 bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost) 815 pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost) 816 return p.SendProofsV2(req.ReqID, bv, nodes.NodeList()) 817 818 case ProofsV1Msg: 819 if pm.odr == nil { 820 return errResp(ErrUnexpectedResponse, "") 821 } 822 823 p.Log().Trace("Received proofs response") 824 //我们以前的一个要求得到了一批Merkle证明 825 var resp struct { 826 ReqID, BV uint64 827 Data []light.NodeList 828 } 829 if err := msg.Decode(&resp); err != nil { 830 return errResp(ErrDecode, "msg %v: %v", msg, err) 831 } 832 p.fcServer.GotReply(resp.ReqID, resp.BV) 833 deliverMsg = &Msg{ 834 MsgType: MsgProofsV1, 835 ReqID: resp.ReqID, 836 Obj: resp.Data, 837 } 838 839 case ProofsV2Msg: 840 if pm.odr == nil { 841 return errResp(ErrUnexpectedResponse, "") 842 } 843 844 p.Log().Trace("Received les/2 proofs response") 845 //我们以前的一个要求得到了一批Merkle证明 846 var resp struct { 847 ReqID, BV uint64 848 Data light.NodeList 849 } 850 if err := msg.Decode(&resp); err != nil { 851 return errResp(ErrDecode, "msg %v: %v", msg, err) 852 } 853 p.fcServer.GotReply(resp.ReqID, resp.BV) 854 deliverMsg = &Msg{ 855 MsgType: MsgProofsV2, 856 ReqID: resp.ReqID, 857 Obj: resp.Data, 858 } 859 860 case GetHeaderProofsMsg: 861 p.Log().Trace("Received headers proof request") 862 //解码检索消息 863 var req struct { 864 ReqID uint64 865 Reqs []ChtReq 866 } 867 if err := msg.Decode(&req); err != nil { 868 return errResp(ErrDecode, "msg %v: %v", msg, err) 869 } 870 //收集状态数据,直到达到提取或网络限制 871 var ( 872 bytes int 873 proofs []ChtResp 874 ) 875 reqCnt := len(req.Reqs) 876 if reject(uint64(reqCnt), MaxHelperTrieProofsFetch) { 877 return errResp(ErrRequestRejected, "") 878 } 879 trieDb := trie.NewDatabase(ethdb.NewTable(pm.chainDb, light.ChtTablePrefix)) 880 for _, req := range req.Reqs { 881 if header := pm.blockchain.GetHeaderByNumber(req.BlockNum); header != nil { 882 sectionHead := rawdb.ReadCanonicalHash(pm.chainDb, req.ChtNum*pm.iConfig.ChtSize-1) 883 if root := light.GetChtRoot(pm.chainDb, req.ChtNum-1, sectionHead); root != (common.Hash{}) { 884 trie, err := trie.New(root, trieDb) 885 if err != nil { 886 continue 887 } 888 var encNumber [8]byte 889 binary.BigEndian.PutUint64(encNumber[:], req.BlockNum) 890 891 var proof light.NodeList 892 trie.Prove(encNumber[:], 0, &proof) 893 894 proofs = append(proofs, ChtResp{Header: header, Proof: proof}) 895 if bytes += proof.DataSize() + estHeaderRlpSize; bytes >= softResponseLimit { 896 break 897 } 898 } 899 } 900 } 901 bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost) 902 pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost) 903 return p.SendHeaderProofs(req.ReqID, bv, proofs) 904 905 case GetHelperTrieProofsMsg: 906 p.Log().Trace("Received helper trie proof request") 907 //解码检索消息 908 var req struct { 909 ReqID uint64 910 Reqs []HelperTrieReq 911 } 912 if err := msg.Decode(&req); err != nil { 913 return errResp(ErrDecode, "msg %v: %v", msg, err) 914 } 915 //收集状态数据,直到达到提取或网络限制 916 var ( 917 auxBytes int 918 auxData [][]byte 919 ) 920 reqCnt := len(req.Reqs) 921 if reject(uint64(reqCnt), MaxHelperTrieProofsFetch) { 922 return errResp(ErrRequestRejected, "") 923 } 924 925 var ( 926 lastIdx uint64 927 lastType uint 928 root common.Hash 929 auxTrie *trie.Trie 930 ) 931 nodes := light.NewNodeSet() 932 for _, req := range req.Reqs { 933 if auxTrie == nil || req.Type != lastType || req.TrieIdx != lastIdx { 934 auxTrie, lastType, lastIdx = nil, req.Type, req.TrieIdx 935 936 var prefix string 937 if root, prefix = pm.getHelperTrie(req.Type, req.TrieIdx); root != (common.Hash{}) { 938 auxTrie, _ = trie.New(root, trie.NewDatabase(ethdb.NewTable(pm.chainDb, prefix))) 939 } 940 } 941 if req.AuxReq == auxRoot { 942 var data []byte 943 if root != (common.Hash{}) { 944 data = root[:] 945 } 946 auxData = append(auxData, data) 947 auxBytes += len(data) 948 } else { 949 if auxTrie != nil { 950 auxTrie.Prove(req.Key, req.FromLevel, nodes) 951 } 952 if req.AuxReq != 0 { 953 data := pm.getHelperTrieAuxData(req) 954 auxData = append(auxData, data) 955 auxBytes += len(data) 956 } 957 } 958 if nodes.DataSize()+auxBytes >= softResponseLimit { 959 break 960 } 961 } 962 bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost) 963 pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost) 964 return p.SendHelperTrieProofs(req.ReqID, bv, HelperTrieResps{Proofs: nodes.NodeList(), AuxData: auxData}) 965 966 case HeaderProofsMsg: 967 if pm.odr == nil { 968 return errResp(ErrUnexpectedResponse, "") 969 } 970 971 p.Log().Trace("Received headers proof response") 972 var resp struct { 973 ReqID, BV uint64 974 Data []ChtResp 975 } 976 if err := msg.Decode(&resp); err != nil { 977 return errResp(ErrDecode, "msg %v: %v", msg, err) 978 } 979 p.fcServer.GotReply(resp.ReqID, resp.BV) 980 deliverMsg = &Msg{ 981 MsgType: MsgHeaderProofs, 982 ReqID: resp.ReqID, 983 Obj: resp.Data, 984 } 985 986 case HelperTrieProofsMsg: 987 if pm.odr == nil { 988 return errResp(ErrUnexpectedResponse, "") 989 } 990 991 p.Log().Trace("Received helper trie proof response") 992 var resp struct { 993 ReqID, BV uint64 994 Data HelperTrieResps 995 } 996 if err := msg.Decode(&resp); err != nil { 997 return errResp(ErrDecode, "msg %v: %v", msg, err) 998 } 999 1000 p.fcServer.GotReply(resp.ReqID, resp.BV) 1001 deliverMsg = &Msg{ 1002 MsgType: MsgHelperTrieProofs, 1003 ReqID: resp.ReqID, 1004 Obj: resp.Data, 1005 } 1006 1007 case SendTxMsg: 1008 if pm.txpool == nil { 1009 return errResp(ErrRequestRejected, "") 1010 } 1011 //事务到达,分析所有事务并传递到池 1012 var txs []*types.Transaction 1013 if err := msg.Decode(&txs); err != nil { 1014 return errResp(ErrDecode, "msg %v: %v", msg, err) 1015 } 1016 reqCnt := len(txs) 1017 if reject(uint64(reqCnt), MaxTxSend) { 1018 return errResp(ErrRequestRejected, "") 1019 } 1020 pm.txpool.AddRemotes(txs) 1021 1022 _, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost) 1023 pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost) 1024 1025 case SendTxV2Msg: 1026 if pm.txpool == nil { 1027 return errResp(ErrRequestRejected, "") 1028 } 1029 //事务到达,分析所有事务并传递到池 1030 var req struct { 1031 ReqID uint64 1032 Txs []*types.Transaction 1033 } 1034 if err := msg.Decode(&req); err != nil { 1035 return errResp(ErrDecode, "msg %v: %v", msg, err) 1036 } 1037 reqCnt := len(req.Txs) 1038 if reject(uint64(reqCnt), MaxTxSend) { 1039 return errResp(ErrRequestRejected, "") 1040 } 1041 1042 hashes := make([]common.Hash, len(req.Txs)) 1043 for i, tx := range req.Txs { 1044 hashes[i] = tx.Hash() 1045 } 1046 stats := pm.txStatus(hashes) 1047 for i, stat := range stats { 1048 if stat.Status == core.TxStatusUnknown { 1049 if errs := pm.txpool.AddRemotes([]*types.Transaction{req.Txs[i]}); errs[0] != nil { 1050 stats[i].Error = errs[0].Error() 1051 continue 1052 } 1053 stats[i] = pm.txStatus([]common.Hash{hashes[i]})[0] 1054 } 1055 } 1056 1057 bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost) 1058 pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost) 1059 1060 return p.SendTxStatus(req.ReqID, bv, stats) 1061 1062 case GetTxStatusMsg: 1063 if pm.txpool == nil { 1064 return errResp(ErrUnexpectedResponse, "") 1065 } 1066 //事务到达,分析所有事务并传递到池 1067 var req struct { 1068 ReqID uint64 1069 Hashes []common.Hash 1070 } 1071 if err := msg.Decode(&req); err != nil { 1072 return errResp(ErrDecode, "msg %v: %v", msg, err) 1073 } 1074 reqCnt := len(req.Hashes) 1075 if reject(uint64(reqCnt), MaxTxStatus) { 1076 return errResp(ErrRequestRejected, "") 1077 } 1078 bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost) 1079 pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost) 1080 1081 return p.SendTxStatus(req.ReqID, bv, pm.txStatus(req.Hashes)) 1082 1083 case TxStatusMsg: 1084 if pm.odr == nil { 1085 return errResp(ErrUnexpectedResponse, "") 1086 } 1087 1088 p.Log().Trace("Received tx status response") 1089 var resp struct { 1090 ReqID, BV uint64 1091 Status []txStatus 1092 } 1093 if err := msg.Decode(&resp); err != nil { 1094 return errResp(ErrDecode, "msg %v: %v", msg, err) 1095 } 1096 1097 p.fcServer.GotReply(resp.ReqID, resp.BV) 1098 1099 default: 1100 p.Log().Trace("Received unknown message", "code", msg.Code) 1101 return errResp(ErrInvalidMsgCode, "%v", msg.Code) 1102 } 1103 1104 if deliverMsg != nil { 1105 err := pm.retriever.deliver(p, deliverMsg) 1106 if err != nil { 1107 p.responseErrors++ 1108 if p.responseErrors > maxResponseErrors { 1109 return err 1110 } 1111 } 1112 } 1113 return nil 1114 } 1115 1116 //GetAccount从根目录下的状态检索帐户。 1117 func (pm *ProtocolManager) getAccount(statedb *state.StateDB, root, hash common.Hash) (state.Account, error) { 1118 trie, err := trie.New(root, statedb.Database().TrieDB()) 1119 if err != nil { 1120 return state.Account{}, err 1121 } 1122 blob, err := trie.TryGet(hash[:]) 1123 if err != nil { 1124 return state.Account{}, err 1125 } 1126 var account state.Account 1127 if err = rlp.DecodeBytes(blob, &account); err != nil { 1128 return state.Account{}, err 1129 } 1130 return account, nil 1131 } 1132 1133 //gethelpertrie返回给定trie id和节索引的后处理trie根。 1134 func (pm *ProtocolManager) getHelperTrie(id uint, idx uint64) (common.Hash, string) { 1135 switch id { 1136 case htCanonical: 1137 idxV1 := (idx+1)*(pm.iConfig.PairChtSize/pm.iConfig.ChtSize) - 1 1138 sectionHead := rawdb.ReadCanonicalHash(pm.chainDb, (idxV1+1)*pm.iConfig.ChtSize-1) 1139 return light.GetChtRoot(pm.chainDb, idxV1, sectionHead), light.ChtTablePrefix 1140 case htBloomBits: 1141 sectionHead := rawdb.ReadCanonicalHash(pm.chainDb, (idx+1)*pm.iConfig.BloomTrieSize-1) 1142 return light.GetBloomTrieRoot(pm.chainDb, idx, sectionHead), light.BloomTrieTablePrefix 1143 } 1144 return common.Hash{}, "" 1145 } 1146 1147 //gethelpertrieauxdata返回给定helpertrie请求的请求辅助数据 1148 func (pm *ProtocolManager) getHelperTrieAuxData(req HelperTrieReq) []byte { 1149 if req.Type == htCanonical && req.AuxReq == auxHeader && len(req.Key) == 8 { 1150 blockNum := binary.BigEndian.Uint64(req.Key) 1151 hash := rawdb.ReadCanonicalHash(pm.chainDb, blockNum) 1152 return rawdb.ReadHeaderRLP(pm.chainDb, hash, blockNum) 1153 } 1154 return nil 1155 } 1156 1157 func (pm *ProtocolManager) txStatus(hashes []common.Hash) []txStatus { 1158 stats := make([]txStatus, len(hashes)) 1159 for i, stat := range pm.txpool.Status(hashes) { 1160 //保存事务池中的状态 1161 stats[i].Status = stat 1162 1163 //如果池未知事务,请尝试在本地查找它 1164 if stat == core.TxStatusUnknown { 1165 if block, number, index := rawdb.ReadTxLookupEntry(pm.chainDb, hashes[i]); block != (common.Hash{}) { 1166 stats[i].Status = core.TxStatusIncluded 1167 stats[i].Lookup = &rawdb.TxLookupEntry{BlockHash: block, BlockIndex: number, Index: index} 1168 } 1169 } 1170 } 1171 return stats 1172 } 1173 1174 //DownloaderPeerNotify实现PeerSetNotify 1175 type downloaderPeerNotify ProtocolManager 1176 1177 type peerConnection struct { 1178 manager *ProtocolManager 1179 peer *peer 1180 } 1181 1182 func (pc *peerConnection) Head() (common.Hash, *big.Int) { 1183 return pc.peer.HeadAndTd() 1184 } 1185 1186 func (pc *peerConnection) RequestHeadersByHash(origin common.Hash, amount int, skip int, reverse bool) error { 1187 reqID := genReqID() 1188 rq := &distReq{ 1189 getCost: func(dp distPeer) uint64 { 1190 peer := dp.(*peer) 1191 return peer.GetRequestCost(GetBlockHeadersMsg, amount) 1192 }, 1193 canSend: func(dp distPeer) bool { 1194 return dp.(*peer) == pc.peer 1195 }, 1196 request: func(dp distPeer) func() { 1197 peer := dp.(*peer) 1198 cost := peer.GetRequestCost(GetBlockHeadersMsg, amount) 1199 peer.fcServer.QueueRequest(reqID, cost) 1200 return func() { peer.RequestHeadersByHash(reqID, cost, origin, amount, skip, reverse) } 1201 }, 1202 } 1203 _, ok := <-pc.manager.reqDist.queue(rq) 1204 if !ok { 1205 return light.ErrNoPeers 1206 } 1207 return nil 1208 } 1209 1210 func (pc *peerConnection) RequestHeadersByNumber(origin uint64, amount int, skip int, reverse bool) error { 1211 reqID := genReqID() 1212 rq := &distReq{ 1213 getCost: func(dp distPeer) uint64 { 1214 peer := dp.(*peer) 1215 return peer.GetRequestCost(GetBlockHeadersMsg, amount) 1216 }, 1217 canSend: func(dp distPeer) bool { 1218 return dp.(*peer) == pc.peer 1219 }, 1220 request: func(dp distPeer) func() { 1221 peer := dp.(*peer) 1222 cost := peer.GetRequestCost(GetBlockHeadersMsg, amount) 1223 peer.fcServer.QueueRequest(reqID, cost) 1224 return func() { peer.RequestHeadersByNumber(reqID, cost, origin, amount, skip, reverse) } 1225 }, 1226 } 1227 _, ok := <-pc.manager.reqDist.queue(rq) 1228 if !ok { 1229 return light.ErrNoPeers 1230 } 1231 return nil 1232 } 1233 1234 func (d *downloaderPeerNotify) registerPeer(p *peer) { 1235 pm := (*ProtocolManager)(d) 1236 pc := &peerConnection{ 1237 manager: pm, 1238 peer: p, 1239 } 1240 pm.downloader.RegisterLightPeer(p.id, ethVersion, pc) 1241 } 1242 1243 func (d *downloaderPeerNotify) unregisterPeer(p *peer) { 1244 pm := (*ProtocolManager)(d) 1245 pm.downloader.UnregisterPeer(p.id) 1246 } 1247