github.com/turingchain2020/turingchain@v1.1.21/system/p2p/dht/protocol/broadcast/query.go (about) 1 // Copyright Turing Corp. 2018 All Rights Reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package broadcast 6 7 import ( 8 "bytes" 9 "encoding/hex" 10 11 "github.com/turingchain2020/turingchain/common" 12 "github.com/turingchain2020/turingchain/common/merkle" 13 "github.com/turingchain2020/turingchain/types" 14 ) 15 16 func (p *broadcastProtocol) sendQueryData(query *types.P2PQueryData, p2pData *types.BroadCastData, pid string) bool { 17 log.Debug("P2PSendQueryData", "pid", pid) 18 p2pData.Value = &types.BroadCastData_Query{Query: query} 19 return true 20 } 21 22 func (p *broadcastProtocol) sendQueryReply(rep *types.P2PBlockTxReply, p2pData *types.BroadCastData, pid string) bool { 23 log.Debug("P2PSendQueryReply", "pid", pid) 24 p2pData.Value = &types.BroadCastData_BlockRep{BlockRep: rep} 25 return true 26 } 27 28 func (p *broadcastProtocol) recvQueryData(query *types.P2PQueryData, pid, peerAddr, version string) error { 29 30 var reply interface{} 31 if txReq := query.GetTxReq(); txReq != nil { 32 33 txHash := hex.EncodeToString(txReq.TxHash) 34 log.Debug("recvQueryTx", "txHash", txHash, "pid", pid) 35 //向mempool请求交易 36 resp, err := p.P2PEnv.QueryModule("mempool", types.EventTxListByHash, &types.ReqTxHashList{Hashes: []string{string(txReq.TxHash)}}) 37 if err != nil { 38 log.Error("recvQuery", "queryMempoolErr", err) 39 return errQueryMempool 40 } 41 42 txList, _ := resp.(*types.ReplyTxList) 43 //返回的数据检测 44 if len(txList.GetTxs()) != 1 || txList.GetTxs()[0] == nil { 45 log.Error("recvQueryTx", "txHash", txHash, "err", "recvNilTxFromMempool") 46 return errRecvMempool 47 } 48 p2pTx := &types.P2PTx{Tx: txList.Txs[0]} 49 //再次发送完整交易至节点, ttl重设为1 50 p2pTx.Route = &types.P2PRoute{TTL: 1} 51 reply = p2pTx 52 // 轻广播交易需要再次发送交易,删除发送过滤相关记录,确保不被拦截 53 removeIgnoreSendPeerAtomic(p.txSendFilter, txHash, pid) 54 55 } else if blcReq := query.GetBlockTxReq(); blcReq != nil { 56 57 log.Debug("recvQueryBlockTx", "hash", blcReq.BlockHash, "queryCount", len(blcReq.TxIndices), "pid", pid) 58 blcHash, _ := common.FromHex(blcReq.BlockHash) 59 if blcHash != nil { 60 resp, err := p.P2PEnv.QueryModule("blockchain", types.EventGetBlockByHashes, &types.ReqHashes{Hashes: [][]byte{blcHash}}) 61 if err != nil { 62 log.Error("recvQueryBlockTx", "queryBlockChainErr", err) 63 return errQueryBlockChain 64 } 65 blocks, ok := resp.(*types.BlockDetails) 66 if !ok || len(blocks.Items) != 1 || blocks.Items[0].Block == nil { 67 log.Error("recvQueryBlockTx", "blockHash", blcReq.BlockHash, "err", "blockNotExist") 68 return errRecvBlockChain 69 } 70 block := blocks.Items[0].Block 71 blockRep := &types.P2PBlockTxReply{BlockHash: blcReq.BlockHash} 72 blockRep.TxIndices = blcReq.TxIndices 73 for _, idx := range blcReq.TxIndices { 74 blockRep.Txs = append(blockRep.Txs, block.Txs[idx]) 75 } 76 //请求所有的交易 77 if len(blockRep.TxIndices) == 0 { 78 blockRep.Txs = block.Txs 79 } 80 reply = blockRep 81 } 82 } 83 84 if reply != nil { 85 if err := p.sendPeer(reply, pid, version); err != nil { 86 log.Error("recvQueryData", "pid", pid, "addr", peerAddr, "err", err) 87 return errSendPeer 88 } 89 } 90 return nil 91 } 92 93 func (p *broadcastProtocol) recvQueryReply(rep *types.P2PBlockTxReply, pid, peerAddr, version string) (err error) { 94 95 log.Debug("recvQueryReply", "hash", rep.BlockHash, "queryTxsCount", len(rep.GetTxIndices()), "pid", pid) 96 val, exist := p.ltBlockCache.Remove(rep.BlockHash) 97 block, _ := val.(*types.Block) 98 //not exist in cache or nil block 99 if !exist || block == nil { 100 log.Error("recvQueryReply", "hash", rep.BlockHash, "exist", exist, "isBlockNil", block == nil) 101 return errLtBlockNotExist 102 } 103 for i, idx := range rep.TxIndices { 104 block.Txs[idx] = rep.Txs[i] 105 } 106 107 //所有交易覆盖 108 if len(rep.TxIndices) == 0 { 109 block.Txs = rep.Txs 110 } 111 112 //计算的root hash是否一致 113 if bytes.Equal(block.TxHash, merkle.CalcMerkleRoot(p.ChainCfg, block.GetHeight(), block.Txs)) { 114 log.Debug("recvQueryReply", "height", block.GetHeight()) 115 //发送至blockchain执行 116 if err := p.postBlockChain(rep.BlockHash, pid, block); err != nil { 117 log.Error("recvQueryReply", "height", block.GetHeight(), "send block to blockchain Error", err.Error()) 118 return errSendBlockChain 119 } 120 return nil 121 } 122 123 // 区块校验仍然不通过,则尝试向对端请求整个区块 , txIndices空表示请求整个区块, 已请求过不再重复请求 124 if len(rep.TxIndices) == 0 { 125 log.Error("recvQueryReply", "height", block.GetHeight(), "hash", rep.BlockHash, "err", errBuildBlockFailed) 126 return errBuildBlockFailed 127 } 128 129 log.Debug("recvQueryReply", "getBlockRetry", block.GetHeight(), "hash", rep.BlockHash) 130 131 query := &types.P2PQueryData{ 132 Value: &types.P2PQueryData_BlockTxReq{ 133 BlockTxReq: &types.P2PBlockTxReq{ 134 BlockHash: rep.BlockHash, 135 TxIndices: nil, 136 }, 137 }, 138 } 139 block.Txs = nil 140 p.ltBlockCache.Add(rep.BlockHash, block, block.Size()) 141 //query peer 142 if err = p.sendPeer(query, pid, version); err != nil { 143 log.Error("recvQueryReply", "pid", pid, "addr", peerAddr, "err", err) 144 p.ltBlockCache.Remove(rep.BlockHash) 145 p.blockFilter.Remove(rep.BlockHash) 146 return errSendPeer 147 } 148 return 149 }