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  }