github.com/neatlab/neatio@v1.7.3-0.20220425043230-d903e92fcc75/neatptc/handler.go (about) 1 package neatptc 2 3 import ( 4 "encoding/json" 5 "errors" 6 "fmt" 7 "math" 8 "math/big" 9 "sync" 10 "sync/atomic" 11 "time" 12 13 "github.com/neatlab/neatio/chain/core/rawdb" 14 15 "github.com/neatlab/neatio/chain/consensus" 16 "github.com/neatlab/neatio/chain/core" 17 "github.com/neatlab/neatio/chain/core/types" 18 "github.com/neatlab/neatio/chain/log" 19 "github.com/neatlab/neatio/neatdb" 20 "github.com/neatlab/neatio/neatptc/downloader" 21 "github.com/neatlab/neatio/neatptc/fetcher" 22 "github.com/neatlab/neatio/network/p2p" 23 "github.com/neatlab/neatio/network/p2p/discover" 24 "github.com/neatlab/neatio/params" 25 "github.com/neatlab/neatio/utilities/common" 26 "github.com/neatlab/neatio/utilities/crypto" 27 "github.com/neatlab/neatio/utilities/event" 28 "github.com/neatlab/neatio/utilities/rlp" 29 ) 30 31 const ( 32 softResponseLimit = 2 * 1024 * 1024 33 estHeaderRlpSize = 500 34 35 txChanSize = 4096 36 37 tx3PrfDtChainSize = 4096 38 ) 39 40 var ( 41 daoChallengeTimeout = 15 * time.Second 42 ) 43 44 var errIncompatibleConfig = errors.New("incompatible configuration") 45 46 func errResp(code errCode, format string, v ...interface{}) error { 47 return fmt.Errorf("%v - %v", code, fmt.Sprintf(format, v...)) 48 } 49 50 type ProtocolManager struct { 51 networkId uint64 52 53 fastSync uint32 54 acceptTxs uint32 55 56 txpool txPool 57 blockchain *core.BlockChain 58 chainconfig *params.ChainConfig 59 maxPeers int 60 61 downloader *downloader.Downloader 62 fetcher *fetcher.Fetcher 63 peers *peerSet 64 65 SubProtocols []p2p.Protocol 66 67 eventMux *event.TypeMux 68 txCh chan core.TxPreEvent 69 txSub event.Subscription 70 71 tx3PrfDtCh chan core.Tx3ProofDataEvent 72 tx3PrfDtFeed event.Feed 73 tx3PrfDtScope event.SubscriptionScope 74 tx3PrfDtSub event.Subscription 75 76 minedBlockSub *event.TypeMuxSubscription 77 78 newPeerCh chan *peer 79 txsyncCh chan *txsync 80 quitSync chan struct{} 81 noMorePeers chan struct{} 82 83 wg sync.WaitGroup 84 85 engine consensus.Engine 86 87 cch core.CrossChainHelper 88 89 logger log.Logger 90 preimageLogger log.Logger 91 } 92 93 func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, networkId uint64, mux *event.TypeMux, txpool txPool, engine consensus.Engine, blockchain *core.BlockChain, chaindb neatdb.Database, cch core.CrossChainHelper) (*ProtocolManager, error) { 94 95 manager := &ProtocolManager{ 96 networkId: networkId, 97 eventMux: mux, 98 txpool: txpool, 99 blockchain: blockchain, 100 chainconfig: config, 101 peers: newPeerSet(), 102 newPeerCh: make(chan *peer), 103 noMorePeers: make(chan struct{}), 104 txsyncCh: make(chan *txsync), 105 quitSync: make(chan struct{}), 106 engine: engine, 107 cch: cch, 108 logger: config.ChainLogger, 109 preimageLogger: config.ChainLogger.New("module", "preimages"), 110 } 111 112 if handler, ok := manager.engine.(consensus.Handler); ok { 113 handler.SetBroadcaster(manager) 114 } 115 116 if mode == downloader.FastSync && blockchain.CurrentBlock().NumberU64() > 0 { 117 manager.logger.Warn("Blockchain not empty, fast sync disabled") 118 mode = downloader.FullSync 119 } 120 if mode == downloader.FastSync { 121 manager.fastSync = uint32(1) 122 } 123 protocol := engine.Protocol() 124 125 manager.SubProtocols = make([]p2p.Protocol, 0, len(protocol.Versions)) 126 for i, version := range protocol.Versions { 127 128 if mode == downloader.FastSync && version < consensus.Eth63 { 129 continue 130 } 131 132 version := version 133 manager.SubProtocols = append(manager.SubProtocols, p2p.Protocol{ 134 Name: protocol.Name, 135 Version: version, 136 Length: protocol.Lengths[i], 137 Run: func(p *p2p.Peer, rw p2p.MsgReadWriter) error { 138 peer := manager.newPeer(int(version), p, rw) 139 select { 140 case manager.newPeerCh <- peer: 141 manager.wg.Add(1) 142 defer manager.wg.Done() 143 return manager.handle(peer) 144 case <-manager.quitSync: 145 return p2p.DiscQuitting 146 } 147 }, 148 NodeInfo: func() interface{} { 149 return manager.NodeInfo() 150 }, 151 PeerInfo: func(id discover.NodeID) interface{} { 152 if p := manager.peers.Peer(fmt.Sprintf("%x", id[:8])); p != nil { 153 return p.Info() 154 } 155 return nil 156 }, 157 }) 158 } 159 if len(manager.SubProtocols) == 0 { 160 return nil, errIncompatibleConfig 161 } 162 163 manager.downloader = downloader.New(mode, chaindb, manager.eventMux, blockchain, nil, manager.removePeer, manager.logger) 164 165 validator := func(header *types.Header) error { 166 return engine.VerifyHeader(blockchain, header, true) 167 } 168 heighter := func() uint64 { 169 return blockchain.CurrentBlock().NumberU64() 170 } 171 inserter := func(blocks types.Blocks) (int, error) { 172 173 if atomic.LoadUint32(&manager.fastSync) == 1 { 174 manager.logger.Warn("Discarded bad propagated block", "number", blocks[0].Number(), "hash", blocks[0].Hash()) 175 return 0, nil 176 } 177 atomic.StoreUint32(&manager.acceptTxs, 1) 178 return manager.blockchain.InsertChain(blocks) 179 } 180 manager.fetcher = fetcher.New(blockchain.GetBlockByHash, validator, manager.BroadcastBlock, heighter, inserter, manager.removePeer) 181 182 return manager, nil 183 } 184 185 func (pm *ProtocolManager) removePeer(id string) { 186 187 peer := pm.peers.Peer(id) 188 if peer == nil { 189 return 190 } 191 pm.logger.Debug("Removing NEAT Blockchain peer", "peer", id) 192 193 pm.downloader.UnregisterPeer(id) 194 if err := pm.peers.Unregister(id); err != nil { 195 pm.logger.Error("Peer removal failed", "peer", id, "err", err) 196 } 197 198 if peer != nil { 199 peer.Peer.Disconnect(p2p.DiscUselessPeer) 200 } 201 } 202 203 func (pm *ProtocolManager) Start(maxPeers int) { 204 pm.maxPeers = maxPeers 205 206 pm.txCh = make(chan core.TxPreEvent, txChanSize) 207 pm.txSub = pm.txpool.SubscribeTxPreEvent(pm.txCh) 208 go pm.txBroadcastLoop() 209 210 pm.tx3PrfDtCh = make(chan core.Tx3ProofDataEvent, tx3PrfDtChainSize) 211 pm.tx3PrfDtSub = pm.tx3PrfDtScope.Track(pm.tx3PrfDtFeed.Subscribe(pm.tx3PrfDtCh)) 212 go pm.tx3PrfDtBroadcastLoop() 213 214 pm.minedBlockSub = pm.eventMux.Subscribe(core.NewMinedBlockEvent{}) 215 go pm.minedBroadcastLoop() 216 217 go pm.syncer() 218 go pm.txsyncLoop() 219 } 220 221 func (pm *ProtocolManager) Stop() { 222 pm.logger.Info("Stopping Neatio protocol") 223 224 pm.txSub.Unsubscribe() 225 pm.tx3PrfDtSub.Unsubscribe() 226 pm.minedBlockSub.Unsubscribe() 227 228 pm.noMorePeers <- struct{}{} 229 230 close(pm.quitSync) 231 232 pm.peers.Close() 233 234 pm.wg.Wait() 235 236 pm.logger.Info("Neatio protocol stopped") 237 } 238 239 func (pm *ProtocolManager) newPeer(pv int, p *p2p.Peer, rw p2p.MsgReadWriter) *peer { 240 return newPeer(pv, p, newMeteredMsgWriter(rw)) 241 } 242 243 func (pm *ProtocolManager) handle(p *peer) error { 244 245 if pm.peers.Len() >= pm.maxPeers && !p.Peer.Info().Network.Trusted { 246 return p2p.DiscTooManyPeers 247 } 248 p.Log().Debug("NEAT Blockchain peer connected", "name", p.Name()) 249 250 var ( 251 genesis = pm.blockchain.Genesis() 252 head = pm.blockchain.CurrentHeader() 253 hash = head.Hash() 254 number = head.Number.Uint64() 255 td = pm.blockchain.GetTd(hash, number) 256 ) 257 if err := p.Handshake(pm.networkId, td, hash, genesis.Hash()); err != nil { 258 p.Log().Debug("NEAT Blockchain handshake failed", "err", err) 259 return err 260 } 261 if rw, ok := p.rw.(*meteredMsgReadWriter); ok { 262 rw.Init(p.version) 263 } 264 265 if err := pm.peers.Register(p); err != nil { 266 p.Log().Error("NEAT Blockchain peer registration failed", "err", err) 267 return err 268 } 269 270 defer func() { 271 pm.removePeer(p.id) 272 if handler, ok := pm.engine.(consensus.Handler); ok { 273 handler.RemovePeer(p) 274 } 275 }() 276 277 if err := pm.downloader.RegisterPeer(p.id, p.version, p); err != nil { 278 return err 279 } 280 281 pm.syncTransactions(p) 282 283 if handler, ok := pm.engine.(consensus.Handler); ok { 284 handler.AddPeer(p) 285 } else { 286 p.Log().Info("AddPeer not executed") 287 } 288 289 for { 290 if err := pm.handleMsg(p); err != nil { 291 p.Log().Debug("NEAT Blockchain message handling failed", "err", err) 292 return err 293 } 294 } 295 } 296 297 func (pm *ProtocolManager) handleMsg(p *peer) error { 298 299 msg, err := p.rw.ReadMsg() 300 if err != nil { 301 return err 302 } 303 if msg.Size > ProtocolMaxMsgSize { 304 return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, ProtocolMaxMsgSize) 305 } 306 defer msg.Discard() 307 308 switch { 309 310 case msg.Code >= 0x20 && msg.Code <= 0x23: 311 if handler, ok := pm.engine.(consensus.Handler); ok { 312 var msgBytes []byte 313 if err := msg.Decode(&msgBytes); err != nil { 314 return errResp(ErrDecode, "msg %v: %v", msg, err) 315 } 316 handler.HandleMsg(msg.Code, p, msgBytes) 317 } 318 case msg.Code == StatusMsg: 319 320 return errResp(ErrExtraStatusMsg, "uncontrolled status message") 321 322 case msg.Code == GetBlockHeadersMsg: 323 324 var query getBlockHeadersData 325 if err := msg.Decode(&query); err != nil { 326 return errResp(ErrDecode, "%v: %v", msg, err) 327 } 328 hashMode := query.Origin.Hash != (common.Hash{}) 329 330 var ( 331 bytes common.StorageSize 332 headers []*types.Header 333 unknown bool 334 ) 335 for !unknown && len(headers) < int(query.Amount) && bytes < softResponseLimit && len(headers) < downloader.MaxHeaderFetch { 336 337 var origin *types.Header 338 if hashMode { 339 origin = pm.blockchain.GetHeaderByHash(query.Origin.Hash) 340 } else { 341 origin = pm.blockchain.GetHeaderByNumber(query.Origin.Number) 342 } 343 if origin == nil { 344 break 345 } 346 number := origin.Number.Uint64() 347 headers = append(headers, origin) 348 bytes += estHeaderRlpSize 349 350 switch { 351 case query.Origin.Hash != (common.Hash{}) && query.Reverse: 352 353 for i := 0; i < int(query.Skip)+1; i++ { 354 if header := pm.blockchain.GetHeader(query.Origin.Hash, number); header != nil { 355 query.Origin.Hash = header.ParentHash 356 number-- 357 } else { 358 unknown = true 359 break 360 } 361 } 362 case query.Origin.Hash != (common.Hash{}) && !query.Reverse: 363 364 var ( 365 current = origin.Number.Uint64() 366 next = current + query.Skip + 1 367 ) 368 if next <= current { 369 infos, _ := json.MarshalIndent(p.Peer.Info(), "", " ") 370 p.Log().Warn("GetBlockHeaders skip overflow attack", "current", current, "skip", query.Skip, "next", next, "attacker", infos) 371 unknown = true 372 } else { 373 if header := pm.blockchain.GetHeaderByNumber(next); header != nil { 374 if pm.blockchain.GetBlockHashesFromHash(header.Hash(), query.Skip+1)[query.Skip] == query.Origin.Hash { 375 query.Origin.Hash = header.Hash() 376 } else { 377 unknown = true 378 } 379 } else { 380 unknown = true 381 } 382 } 383 case query.Reverse: 384 385 if query.Origin.Number >= query.Skip+1 { 386 query.Origin.Number -= query.Skip + 1 387 } else { 388 unknown = true 389 } 390 391 case !query.Reverse: 392 393 query.Origin.Number += query.Skip + 1 394 } 395 } 396 return p.SendBlockHeaders(headers) 397 398 case msg.Code == BlockHeadersMsg: 399 400 var headers []*types.Header 401 if err := msg.Decode(&headers); err != nil { 402 return errResp(ErrDecode, "msg %v: %v", msg, err) 403 } 404 405 filter := len(headers) == 1 406 if filter { 407 408 headers = pm.fetcher.FilterHeaders(p.id, headers, time.Now()) 409 } 410 if len(headers) > 0 || !filter { 411 err := pm.downloader.DeliverHeaders(p.id, headers) 412 if err != nil { 413 pm.logger.Debug("Failed to deliver headers", "err", err) 414 } 415 } 416 417 case msg.Code == GetBlockBodiesMsg: 418 419 msgStream := rlp.NewStream(msg.Payload, uint64(msg.Size)) 420 if _, err := msgStream.List(); err != nil { 421 return err 422 } 423 424 var ( 425 hash common.Hash 426 bytes int 427 bodies []rlp.RawValue 428 ) 429 for bytes < softResponseLimit && len(bodies) < downloader.MaxBlockFetch { 430 431 if err := msgStream.Decode(&hash); err == rlp.EOL { 432 break 433 } else if err != nil { 434 return errResp(ErrDecode, "msg %v: %v", msg, err) 435 } 436 437 if data := pm.blockchain.GetBodyRLP(hash); len(data) != 0 { 438 bodies = append(bodies, data) 439 bytes += len(data) 440 } 441 } 442 return p.SendBlockBodiesRLP(bodies) 443 444 case msg.Code == BlockBodiesMsg: 445 446 var request blockBodiesData 447 if err := msg.Decode(&request); err != nil { 448 return errResp(ErrDecode, "msg %v: %v", msg, err) 449 } 450 451 trasactions := make([][]*types.Transaction, len(request)) 452 uncles := make([][]*types.Header, len(request)) 453 454 for i, body := range request { 455 trasactions[i] = body.Transactions 456 uncles[i] = body.Uncles 457 } 458 459 filter := len(trasactions) > 0 || len(uncles) > 0 460 if filter { 461 trasactions, uncles = pm.fetcher.FilterBodies(p.id, trasactions, uncles, time.Now()) 462 } 463 if len(trasactions) > 0 || len(uncles) > 0 || !filter { 464 err := pm.downloader.DeliverBodies(p.id, trasactions, uncles) 465 if err != nil { 466 pm.logger.Debug("Failed to deliver bodies", "err", err) 467 } 468 } 469 470 case p.version >= consensus.Eth63 && msg.Code == GetNodeDataMsg: 471 472 msgStream := rlp.NewStream(msg.Payload, uint64(msg.Size)) 473 if _, err := msgStream.List(); err != nil { 474 return err 475 } 476 477 var ( 478 hash common.Hash 479 bytes int 480 data [][]byte 481 ) 482 for bytes < softResponseLimit && len(data) < downloader.MaxStateFetch { 483 484 if err := msgStream.Decode(&hash); err == rlp.EOL { 485 break 486 } else if err != nil { 487 return errResp(ErrDecode, "msg %v: %v", msg, err) 488 } 489 490 if entry, err := pm.blockchain.TrieNode(hash); err == nil { 491 data = append(data, entry) 492 bytes += len(entry) 493 } 494 } 495 return p.SendNodeData(data) 496 497 case p.version >= consensus.Eth63 && msg.Code == NodeDataMsg: 498 499 var data [][]byte 500 if err := msg.Decode(&data); err != nil { 501 return errResp(ErrDecode, "msg %v: %v", msg, err) 502 } 503 504 if err := pm.downloader.DeliverNodeData(p.id, data); err != nil { 505 pm.logger.Debug("Failed to deliver node state data", "err", err) 506 } 507 508 case p.version >= consensus.Eth63 && msg.Code == GetReceiptsMsg: 509 510 msgStream := rlp.NewStream(msg.Payload, uint64(msg.Size)) 511 if _, err := msgStream.List(); err != nil { 512 return err 513 } 514 515 var ( 516 hash common.Hash 517 bytes int 518 receipts []rlp.RawValue 519 ) 520 for bytes < softResponseLimit && len(receipts) < downloader.MaxReceiptFetch { 521 522 if err := msgStream.Decode(&hash); err == rlp.EOL { 523 break 524 } else if err != nil { 525 return errResp(ErrDecode, "msg %v: %v", msg, err) 526 } 527 528 results := pm.blockchain.GetReceiptsByHash(hash) 529 if results == nil { 530 if header := pm.blockchain.GetHeaderByHash(hash); header == nil || header.ReceiptHash != types.EmptyRootHash { 531 continue 532 } 533 } 534 535 if encoded, err := rlp.EncodeToBytes(results); err != nil { 536 pm.logger.Error("Failed to encode receipt", "err", err) 537 } else { 538 receipts = append(receipts, encoded) 539 bytes += len(encoded) 540 } 541 } 542 return p.SendReceiptsRLP(receipts) 543 544 case p.version >= consensus.Eth63 && msg.Code == ReceiptsMsg: 545 546 var receipts [][]*types.Receipt 547 if err := msg.Decode(&receipts); err != nil { 548 return errResp(ErrDecode, "msg %v: %v", msg, err) 549 } 550 551 if err := pm.downloader.DeliverReceipts(p.id, receipts); err != nil { 552 pm.logger.Debug("Failed to deliver receipts", "err", err) 553 } 554 555 case msg.Code == NewBlockHashesMsg: 556 var announces newBlockHashesData 557 if err := msg.Decode(&announces); err != nil { 558 return errResp(ErrDecode, "%v: %v", msg, err) 559 } 560 561 for _, block := range announces { 562 p.MarkBlock(block.Hash) 563 } 564 565 unknown := make(newBlockHashesData, 0, len(announces)) 566 for _, block := range announces { 567 if !pm.blockchain.HasBlock(block.Hash, block.Number) { 568 unknown = append(unknown, block) 569 } 570 } 571 for _, block := range unknown { 572 pm.fetcher.Notify(p.id, block.Hash, block.Number, time.Now(), p.RequestOneHeader, p.RequestBodies) 573 } 574 575 case msg.Code == NewBlockMsg: 576 577 var request newBlockData 578 if err := msg.Decode(&request); err != nil { 579 return errResp(ErrDecode, "%v: %v", msg, err) 580 } 581 request.Block.ReceivedAt = msg.ReceivedAt 582 request.Block.ReceivedFrom = p 583 584 p.MarkBlock(request.Block.Hash()) 585 pm.fetcher.Enqueue(p.id, request.Block) 586 587 var ( 588 trueHead = request.Block.ParentHash() 589 trueTD = new(big.Int).Sub(request.TD, request.Block.Difficulty()) 590 ) 591 592 if _, td := p.Head(); trueTD.Cmp(td) > 0 { 593 p.SetHead(trueHead, trueTD) 594 595 currentBlock := pm.blockchain.CurrentBlock() 596 if trueTD.Cmp(pm.blockchain.GetTd(currentBlock.Hash(), currentBlock.NumberU64())) > 0 { 597 go pm.synchronise(p) 598 } 599 } 600 601 case msg.Code == TxMsg: 602 603 if atomic.LoadUint32(&pm.acceptTxs) == 0 { 604 break 605 } 606 607 var txs []*types.Transaction 608 if err := msg.Decode(&txs); err != nil { 609 return errResp(ErrDecode, "msg %v: %v", msg, err) 610 } 611 for i, tx := range txs { 612 613 if tx == nil { 614 return errResp(ErrDecode, "transaction %d is nil", i) 615 } 616 p.MarkTransaction(tx.Hash()) 617 } 618 pm.txpool.AddRemotes(txs) 619 620 case msg.Code == TX3ProofDataMsg: 621 pm.logger.Debug("TX3ProofDataMsg received") 622 var proofDatas []*types.TX3ProofData 623 if err := msg.Decode(&proofDatas); err != nil { 624 pm.logger.Error("TX3ProofDataMsg decode error", "msg", msg, "error", err) 625 return errResp(ErrDecode, "msg %v: %v", msg, err) 626 } 627 for _, proofData := range proofDatas { 628 629 if err := pm.cch.ValidateTX3ProofData(proofData); err != nil { 630 pm.logger.Error("TX3ProofDataMsg validate error", "msg", msg, "error", err) 631 return errResp(ErrTX3ValidateFail, "msg %v: %v", msg, err) 632 } 633 p.MarkTX3ProofData(proofData.Header.Hash()) 634 635 if err := pm.cch.WriteTX3ProofData(proofData); err != nil { 636 pm.logger.Error("TX3ProofDataMsg write error", "msg", msg, "error", err) 637 } 638 639 go pm.tx3PrfDtFeed.Send(core.Tx3ProofDataEvent{proofData}) 640 } 641 642 case msg.Code == GetPreImagesMsg: 643 pm.preimageLogger.Debug("GetPreImagesMsg received") 644 645 msgStream := rlp.NewStream(msg.Payload, uint64(msg.Size)) 646 if _, err := msgStream.List(); err != nil { 647 return err 648 } 649 650 var ( 651 hash common.Hash 652 bytes int 653 preimages [][]byte 654 ) 655 656 for bytes < softResponseLimit && len(preimages) < downloader.MaxReceiptFetch { 657 658 if err := msgStream.Decode(&hash); err == rlp.EOL { 659 break 660 } else if err != nil { 661 662 return errResp(ErrDecode, "msg %v: %v", msg, err) 663 } 664 665 preimage := rawdb.ReadPreimage(pm.blockchain.StateCache().TrieDB().DiskDB(), hash) 666 667 if hash != crypto.Keccak256Hash(preimage) { 668 pm.preimageLogger.Errorf("Failed to pass the preimage double check. Request hash %x, Local Preimage %x", hash, preimage) 669 continue 670 } 671 672 preimages = append(preimages, preimage) 673 bytes += len(preimage) 674 } 675 return p.SendPreimagesRLP(preimages) 676 677 case msg.Code == PreImagesMsg: 678 pm.preimageLogger.Debug("PreImagesMsg received") 679 var preimages [][]byte 680 if err := msg.Decode(&preimages); err != nil { 681 return errResp(ErrDecode, "msg %v: %v", msg, err) 682 } 683 684 preimagesMap := make(map[common.Hash][]byte) 685 for _, preimage := range preimages { 686 pm.preimageLogger.Debugf("PreImagesMsg received: %x", preimage) 687 preimagesMap[crypto.Keccak256Hash(preimage)] = common.CopyBytes(preimage) 688 } 689 if len(preimagesMap) > 0 { 690 db, _ := pm.blockchain.StateCache().TrieDB().DiskDB().(neatdb.Database) 691 rawdb.WritePreimages(db, preimagesMap) 692 pm.preimageLogger.Info("PreImages wrote into database") 693 } 694 case msg.Code == TrieNodeDataMsg: 695 pm.logger.Debug("TrieNodeDataMsg received") 696 var trienodes [][]byte 697 if err := msg.Decode(&trienodes); err != nil { 698 pm.logger.Warnf("Unable decode TrieNodeData %v", err) 699 return errResp(ErrDecode, "msg %v: %v", msg, err) 700 } 701 pm.logger.Debugf("%d TrieNodeData received", len(trienodes)) 702 703 db, _ := pm.blockchain.StateCache().TrieDB().DiskDB().(neatdb.Database) 704 for _, tnode := range trienodes { 705 thash := crypto.Keccak256Hash(tnode) 706 if has, herr := db.Has(thash.Bytes()); !has && herr == nil { 707 puterr := db.Put(thash.Bytes(), tnode) 708 if puterr == nil { 709 pm.logger.Debugf("Insert TrieNodeData %x", thash) 710 } 711 } else if has { 712 pm.logger.Debugf("TrieNodeData %x already existed", thash) 713 } 714 } 715 default: 716 return errResp(ErrInvalidMsgCode, "%v", msg.Code) 717 } 718 return nil 719 } 720 721 func (pm *ProtocolManager) Enqueue(id string, block *types.Block) { 722 pm.fetcher.Enqueue(id, block) 723 } 724 725 func (pm *ProtocolManager) BroadcastBlock(block *types.Block, propagate bool) { 726 hash := block.Hash() 727 peers := pm.peers.PeersWithoutBlock(hash) 728 729 if propagate { 730 731 var td *big.Int 732 if parent := pm.blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1); parent != nil { 733 td = new(big.Int).Add(block.Difficulty(), pm.blockchain.GetTd(block.ParentHash(), block.NumberU64()-1)) 734 } else { 735 pm.logger.Error("Propagating dangling block", "number", block.Number(), "hash", hash) 736 return 737 } 738 739 transfer := peers[:int(math.Sqrt(float64(len(peers))))] 740 for _, peer := range transfer { 741 peer.SendNewBlock(block, td) 742 } 743 pm.logger.Trace("Propagated block", "hash", hash, "recipients", len(transfer), "duration", common.PrettyDuration(time.Since(block.ReceivedAt))) 744 return 745 } 746 747 if pm.blockchain.HasBlock(hash, block.NumberU64()) { 748 for _, peer := range peers { 749 peer.SendNewBlockHashes([]common.Hash{hash}, []uint64{block.NumberU64()}) 750 } 751 pm.logger.Trace("Announced block", "hash", hash, "recipients", len(peers), "duration", common.PrettyDuration(time.Since(block.ReceivedAt))) 752 } 753 } 754 755 func (pm *ProtocolManager) BroadcastTx(hash common.Hash, tx *types.Transaction) { 756 757 peers := pm.peers.PeersWithoutTx(hash) 758 759 for _, peer := range peers { 760 peer.SendTransactions(types.Transactions{tx}) 761 } 762 pm.logger.Trace("Broadcast transaction", "hash", hash, "recipients", len(peers)) 763 } 764 765 func (pm *ProtocolManager) BroadcastTX3ProofData(hash common.Hash, proofData *types.TX3ProofData) { 766 767 peers := pm.peers.PeersWithoutTX3ProofData(hash) 768 for _, peer := range peers { 769 peer.SendTX3ProofData([]*types.TX3ProofData{proofData}) 770 } 771 pm.logger.Trace("Broadcast TX3ProofData", "hash", hash, "recipients", len(peers)) 772 } 773 774 func (pm *ProtocolManager) BroadcastMessage(msgcode uint64, data interface{}) { 775 recipients := 0 776 for _, peer := range pm.peers.Peers() { 777 peer.Send(msgcode, data) 778 recipients++ 779 } 780 pm.logger.Trace("Broadcast p2p message", "code", msgcode, "recipients", recipients, "msg", data) 781 } 782 783 func (pm *ProtocolManager) TryFixBadPreimages() { 784 785 images := make(map[common.Hash][]byte) 786 787 var hashes []common.Hash 788 789 db, _ := pm.blockchain.StateCache().TrieDB().DiskDB().(neatdb.Database) 790 it := db.NewIteratorWithPrefix([]byte("secure-key-")) 791 for it.Next() { 792 keyHash := common.BytesToHash(it.Key()) 793 valueHash := crypto.Keccak256Hash(it.Value()) 794 if keyHash != valueHash { 795 796 hashes = append(hashes, keyHash) 797 } 798 799 images[keyHash] = common.CopyBytes(it.Value()) 800 } 801 it.Release() 802 803 if len(hashes) > 0 { 804 pm.preimageLogger.Critf("Found %d Bad Preimage(s)", len(hashes)) 805 pm.preimageLogger.Critf("Bad Preimages: %x", hashes) 806 807 pm.peers.BestPeer().RequestPreimages(hashes) 808 } 809 810 } 811 812 func (self *ProtocolManager) minedBroadcastLoop() { 813 814 for obj := range self.minedBlockSub.Chan() { 815 switch ev := obj.Data.(type) { 816 case core.NewMinedBlockEvent: 817 self.BroadcastBlock(ev.Block, true) 818 self.BroadcastBlock(ev.Block, false) 819 } 820 } 821 } 822 823 func (self *ProtocolManager) txBroadcastLoop() { 824 for { 825 select { 826 case event := <-self.txCh: 827 self.BroadcastTx(event.Tx.Hash(), event.Tx) 828 829 case <-self.txSub.Err(): 830 return 831 } 832 } 833 } 834 835 func (self *ProtocolManager) tx3PrfDtBroadcastLoop() { 836 for { 837 select { 838 case event := <-self.tx3PrfDtCh: 839 self.BroadcastTX3ProofData(event.Tx3PrfDt.Header.Hash(), event.Tx3PrfDt) 840 841 case <-self.tx3PrfDtSub.Err(): 842 return 843 } 844 } 845 } 846 847 type NodeInfo struct { 848 Network uint64 `json:"network"` 849 Difficulty *big.Int `json:"difficulty"` 850 Genesis common.Hash `json:"genesis"` 851 Config *params.ChainConfig `json:"config"` 852 Head common.Hash `json:"head"` 853 } 854 855 func (self *ProtocolManager) NodeInfo() *NodeInfo { 856 currentBlock := self.blockchain.CurrentBlock() 857 return &NodeInfo{ 858 Network: self.networkId, 859 Difficulty: self.blockchain.GetTd(currentBlock.Hash(), currentBlock.NumberU64()), 860 Genesis: self.blockchain.Genesis().Hash(), 861 Config: self.blockchain.Config(), 862 Head: currentBlock.Hash(), 863 } 864 } 865 866 func (self *ProtocolManager) FindPeers(targets map[common.Address]bool) map[common.Address]consensus.Peer { 867 m := make(map[common.Address]consensus.Peer) 868 for _, p := range self.peers.Peers() { 869 pubKey, err := p.ID().Pubkey() 870 if err != nil { 871 continue 872 } 873 addr := crypto.PubkeyToAddress(*pubKey) 874 if targets[addr] { 875 m[addr] = p 876 } 877 } 878 return m 879 }