github.com/turingchain2020/turingchain@v1.1.21/blockchain/proc.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 blockchain
     6  
     7  //message callback
     8  import (
     9  	"fmt"
    10  	"sync/atomic"
    11  
    12  	"github.com/turingchain2020/turingchain/common"
    13  	"github.com/turingchain2020/turingchain/queue"
    14  	"github.com/turingchain2020/turingchain/types"
    15  )
    16  
    17  //ProcRecvMsg blockchain模块的消息接收处理
    18  func (chain *BlockChain) ProcRecvMsg() {
    19  	defer chain.recvwg.Done()
    20  	reqnum := make(chan struct{}, 1000)
    21  	for msg := range chain.client.Recv() {
    22  		chainlog.Debug("blockchain recv", "msg", types.GetEventName(int(msg.Ty)), "id", msg.ID, "cap", len(reqnum))
    23  		msgtype := msg.Ty
    24  		reqnum <- struct{}{}
    25  		atomic.AddInt32(&chain.runcount, 1)
    26  		if chain.procLocalDB(msgtype, msg, reqnum) {
    27  			continue
    28  		}
    29  		switch msgtype {
    30  		case types.EventQueryTx:
    31  			go chain.processMsg(msg, reqnum, chain.queryTx)
    32  		case types.EventGetBlocks:
    33  			go chain.processMsg(msg, reqnum, chain.getBlocks)
    34  		case types.EventSyncBlock: // block
    35  			go chain.processMsg(msg, reqnum, chain.addBlock)
    36  		case types.EventGetBlockHeight:
    37  			go chain.processMsg(msg, reqnum, chain.getBlockHeight)
    38  		case types.EventTxHashList:
    39  			go chain.processMsg(msg, reqnum, chain.txHashList)
    40  		case types.EventGetHeaders:
    41  			go chain.processMsg(msg, reqnum, chain.getHeaders)
    42  		case types.EventGetLastHeader:
    43  			go chain.processMsg(msg, reqnum, chain.getLastHeader)
    44  		case types.EventAddBlockDetail:
    45  			go chain.processMsg(msg, reqnum, chain.addBlockDetail)
    46  		case types.EventBroadcastAddBlock: //block
    47  			go chain.processMsg(msg, reqnum, chain.broadcastAddBlock)
    48  		case types.EventGetTransactionByAddr:
    49  			go chain.processMsg(msg, reqnum, chain.getTransactionByAddr)
    50  		case types.EventGetTransactionByHash:
    51  			go chain.processMsg(msg, reqnum, chain.getTransactionByHashes)
    52  		case types.EventGetBlockOverview: //blockOverview
    53  			go chain.processMsg(msg, reqnum, chain.getBlockOverview)
    54  		case types.EventGetAddrOverview: //addrOverview
    55  			go chain.processMsg(msg, reqnum, chain.getAddrOverview)
    56  		case types.EventGetBlockHash: //GetBlockHash
    57  			go chain.processMsg(msg, reqnum, chain.getBlockHash)
    58  			//订阅指定类型的交易回执
    59  		case types.EventSubscribePush:
    60  			go chain.processMsg(msg, reqnum, chain.subscribePush)
    61  		case types.EventAddBlockHeaders:
    62  			go chain.processMsg(msg, reqnum, chain.addBlockHeaders)
    63  		case types.EventGetLastBlock:
    64  			go chain.processMsg(msg, reqnum, chain.getLastBlock)
    65  		case types.EventIsSync:
    66  			go chain.processMsg(msg, reqnum, chain.isSync)
    67  		case types.EventIsNtpClockSync:
    68  			go chain.processMsg(msg, reqnum, chain.isNtpClockSyncFunc)
    69  		case types.EventGetLastBlockSequence:
    70  			go chain.processMsg(msg, reqnum, chain.getLastBlockSequence)
    71  		case types.EventGetBlockSequences:
    72  			go chain.processMsg(msg, reqnum, chain.getBlockSequences)
    73  		case types.EventGetBlockByHashes:
    74  			go chain.processMsg(msg, reqnum, chain.getBlockByHashes)
    75  		case types.EventGetBlockBySeq:
    76  			go chain.processMsg(msg, reqnum, chain.getBlockBySeq)
    77  		case types.EventDelParaChainBlockDetail:
    78  			go chain.processMsg(msg, reqnum, chain.delParaChainBlockDetail)
    79  		case types.EventAddParaChainBlockDetail:
    80  			go chain.processMsg(msg, reqnum, chain.addParaChainBlockDetail)
    81  		case types.EventGetSeqByHash:
    82  			go chain.processMsg(msg, reqnum, chain.getSeqByHash)
    83  		case types.EventListPushes:
    84  			go chain.processMsg(msg, reqnum, chain.listPush)
    85  		case types.EventGetPushLastNum:
    86  			go chain.processMsg(msg, reqnum, chain.getPushLastNum)
    87  		case types.EventGetLastBlockMainSequence:
    88  			go chain.processMsg(msg, reqnum, chain.GetLastBlockMainSequence)
    89  		case types.EventGetMainSeqByHash:
    90  			go chain.processMsg(msg, reqnum, chain.GetMainSeqByHash)
    91  		//para共识模块操作blockchain db的事件
    92  		case types.EventSetValueByKey:
    93  			go chain.processMsg(msg, reqnum, chain.setValueByKey)
    94  		case types.EventGetValueByKey:
    95  			go chain.processMsg(msg, reqnum, chain.getValueByKey)
    96  		//通过平行链title获取平行链的交易
    97  		case types.EventGetParaTxByTitle:
    98  			go chain.processMsg(msg, reqnum, chain.getParaTxByTitle)
    99  
   100  			//获取拥有此title交易的区块高度
   101  		case types.EventGetHeightByTitle:
   102  			go chain.processMsg(msg, reqnum, chain.getHeightByTitle)
   103  
   104  			//通过区块高度列表+title获取平行链交易
   105  		case types.EventGetParaTxByTitleAndHeight:
   106  			go chain.processMsg(msg, reqnum, chain.getParaTxByTitleAndHeight)
   107  			// 获取chunk record
   108  		case types.EventGetChunkRecord:
   109  			go chain.processMsg(msg, reqnum, chain.getChunkRecord)
   110  			// 获取chunk record
   111  		case types.EventAddChunkRecord:
   112  			go chain.processMsg(msg, reqnum, chain.addChunkRecord)
   113  			// 从localdb中获取Chunk BlockBody
   114  		case types.EventGetChunkBlockBody:
   115  			go chain.processMsg(msg, reqnum, chain.getChunkBlockBody)
   116  			// 用于chunk同步区块
   117  		case types.EventAddChunkBlock:
   118  			go chain.processMsg(msg, reqnum, chain.addChunkBlock)
   119  		default:
   120  			go chain.processMsg(msg, reqnum, chain.unknowMsg)
   121  		}
   122  	}
   123  }
   124  
   125  func (chain *BlockChain) unknowMsg(msg *queue.Message) {
   126  	chainlog.Warn("ProcRecvMsg unknow msg", "msgtype", msg.Ty)
   127  }
   128  
   129  func (chain *BlockChain) listPush(msg *queue.Message) {
   130  	cbs, err := chain.ProcListPush()
   131  	if err != nil {
   132  		chainlog.Error("listPush", "err", err.Error())
   133  		msg.Reply(chain.client.NewMessage("rpc", types.EventListPushes, err))
   134  		return
   135  	}
   136  	msg.Reply(chain.client.NewMessage("rpc", types.EventListPushes, cbs))
   137  }
   138  func (chain *BlockChain) getPushLastNum(msg *queue.Message) {
   139  	data := (msg.Data).(*types.ReqString)
   140  
   141  	num, _ := chain.ProcGetLastPushSeq(data.Data)
   142  	lastNum := &types.Int64{Data: num}
   143  	msg.Reply(chain.client.NewMessage("rpc", types.EventGetPushLastNum, lastNum))
   144  }
   145  
   146  func (chain *BlockChain) queryTx(msg *queue.Message) {
   147  	txhash := (msg.Data).(*types.ReqHash)
   148  	txDetail, err := chain.ProcQueryTxMsg(txhash.Hash)
   149  	if err != nil {
   150  		chainlog.Debug("ProcQueryTxMsg", "err", err.Error())
   151  		msg.Reply(chain.client.NewMessage("rpc", types.EventTransactionDetail, err))
   152  	} else {
   153  		msg.Reply(chain.client.NewMessage("rpc", types.EventTransactionDetail, txDetail))
   154  	}
   155  }
   156  
   157  func (chain *BlockChain) getBlocks(msg *queue.Message) {
   158  	requestblocks := (msg.Data).(*types.ReqBlocks)
   159  	blocks, err := chain.ProcGetBlockDetailsMsg(requestblocks)
   160  	if err != nil {
   161  		chainlog.Error("ProcGetBlockDetailsMsg", "err", err.Error())
   162  		msg.Reply(chain.client.NewMessage("rpc", types.EventBlocks, err))
   163  	} else {
   164  		//chainlog.Debug("ProcGetBlockDetailsMsg", "success", "ok")
   165  		msg.Reply(chain.client.NewMessage("rpc", types.EventBlocks, blocks))
   166  	}
   167  }
   168  
   169  func (chain *BlockChain) addBlock(msg *queue.Message) {
   170  	var reply types.Reply
   171  	reply.IsOk = true
   172  	blockpid := msg.Data.(*types.BlockPid)
   173  	//chainlog.Error("addBlock", "height", blockpid.Block.Height, "pid", blockpid.Pid)
   174  	if chain.GetDownloadSyncStatus() == fastDownLoadMode {
   175  		err := chain.WriteBlockToDbTemp(blockpid.Block, true)
   176  		if err != nil {
   177  			chainlog.Error("WriteBlockToDbTemp", "height", blockpid.Block.Height, "err", err.Error())
   178  			reply.IsOk = false
   179  			reply.Msg = []byte(err.Error())
   180  		}
   181  		//downLoadTask 运行时设置对应的blockdone
   182  		if chain.downLoadTask.InProgress() {
   183  			chain.downLoadTask.Done(blockpid.Block.GetHeight())
   184  		}
   185  	} else {
   186  		_, err := chain.ProcAddBlockMsg(false, &types.BlockDetail{Block: blockpid.Block}, blockpid.Pid)
   187  		if err != nil {
   188  			chainlog.Error("ProcAddBlockMsg", "height", blockpid.Block.Height, "err", err.Error())
   189  			reply.IsOk = false
   190  			reply.Msg = []byte(err.Error())
   191  		}
   192  		chainlog.Debug("EventAddBlock", "height", blockpid.Block.Height, "pid", blockpid.Pid, "success", "ok")
   193  	}
   194  	msg.Reply(chain.client.NewMessage("p2p", types.EventReply, &reply))
   195  }
   196  
   197  func (chain *BlockChain) getBlockHeight(msg *queue.Message) {
   198  	var replyBlockHeight types.ReplyBlockHeight
   199  	replyBlockHeight.Height = chain.GetBlockHeight()
   200  	//chainlog.Debug("EventGetBlockHeight", "success", "ok")
   201  	msg.Reply(chain.client.NewMessage("consensus", types.EventReplyBlockHeight, &replyBlockHeight))
   202  }
   203  
   204  func (chain *BlockChain) txHashList(msg *queue.Message) {
   205  	txhashlist := (msg.Data).(*types.TxHashList)
   206  	duptxhashlist, err := chain.GetDuplicateTxHashList(txhashlist)
   207  	if err != nil {
   208  		chainlog.Error("txHashList", "err", err.Error())
   209  		msg.Reply(chain.client.NewMessage("consensus", types.EventTxHashListReply, err))
   210  		return
   211  	}
   212  	//chainlog.Debug("EventTxHashList", "success", "ok")
   213  	msg.Reply(chain.client.NewMessage("consensus", types.EventTxHashListReply, duptxhashlist))
   214  }
   215  
   216  func (chain *BlockChain) getHeaders(msg *queue.Message) {
   217  	requestblocks := (msg.Data).(*types.ReqBlocks)
   218  	headers, err := chain.ProcGetHeadersMsg(requestblocks)
   219  	if err != nil {
   220  		chainlog.Error("ProcGetHeadersMsg", "err", err.Error())
   221  		msg.Reply(chain.client.NewMessage("rpc", types.EventHeaders, err))
   222  	} else {
   223  		//chainlog.Debug("EventGetHeaders", "success", "ok")
   224  		msg.Reply(chain.client.NewMessage("rpc", types.EventHeaders, headers))
   225  	}
   226  }
   227  
   228  func (chain *BlockChain) isSync(msg *queue.Message) {
   229  	ok := chain.IsCaughtUp()
   230  	msg.Reply(chain.client.NewMessage("", types.EventReplyIsSync, &types.IsCaughtUp{Iscaughtup: ok}))
   231  }
   232  
   233  func (chain *BlockChain) getLastHeader(msg *queue.Message) {
   234  	header, err := chain.ProcGetLastHeaderMsg()
   235  	if err != nil {
   236  		chainlog.Error("ProcGetLastHeaderMsg", "err", err.Error())
   237  		msg.Reply(chain.client.NewMessage("account", types.EventHeader, err))
   238  	} else {
   239  		//chainlog.Debug("EventGetLastHeader", "success", "ok")
   240  		msg.Reply(chain.client.NewMessage("account", types.EventHeader, header))
   241  	}
   242  }
   243  
   244  //共识过来的block是没有被执行的,首先判断此block的parent block是否是当前best链的tip
   245  //在blockchain执行时需要做tx的去重处理,所以在执行成功之后需要将最新区块详情返回给共识模块
   246  func (chain *BlockChain) addBlockDetail(msg *queue.Message) {
   247  	blockDetail := msg.Data.(*types.BlockDetail)
   248  	Height := blockDetail.Block.Height
   249  	chainlog.Debug("EventAddBlockDetail", "height", blockDetail.Block.Height, "parent", common.ToHex(blockDetail.Block.ParentHash))
   250  	blockDetail, err := chain.ProcAddBlockMsg(true, blockDetail, "self")
   251  	if err != nil {
   252  		chainlog.Error("addBlockDetail", "height", Height, "procAddBlockMsg err", err.Error())
   253  		msg.Reply(chain.client.NewMessage("consensus", types.EventAddBlockDetail, err))
   254  		return
   255  	}
   256  	if blockDetail == nil {
   257  		err = types.ErrExecBlockNil
   258  		chainlog.Error("addBlockDetail", "height", Height, "nil block err", err.Error())
   259  		msg.Reply(chain.client.NewMessage("consensus", types.EventAddBlockDetail, err))
   260  		return
   261  	}
   262  	chainlog.Debug("addBlockDetail success ", "Height", Height, "hash", common.HashHex(blockDetail.Block.Hash(chain.client.GetConfig())))
   263  	msg.Reply(chain.client.NewMessage("consensus", types.EventAddBlockDetail, blockDetail))
   264  }
   265  
   266  //超前太多或者落后太多的广播区块都不做处理:
   267  //当本节点在同步阶段并且远远落后主网最新高度时不处理广播block,暂定落后128个区块
   268  //以免广播区块占用go goroutine资源
   269  //目前回滚只支持10000个区块,所以收到落后10000高度之外的广播区块也不做处理
   270  func (chain *BlockChain) broadcastAddBlock(msg *queue.Message) {
   271  	var reply types.Reply
   272  	reply.IsOk = true
   273  	blockwithpid := msg.Data.(*types.BlockPid)
   274  
   275  	castheight := blockwithpid.Block.Height
   276  	curheight := chain.GetBlockHeight()
   277  
   278  	futureMaximum := castheight > curheight+BackBlockNum
   279  	backWardMaximum := curheight > MaxRollBlockNum && castheight < curheight-MaxRollBlockNum
   280  
   281  	if futureMaximum || backWardMaximum {
   282  		chainlog.Debug("EventBroadcastAddBlock", "curheight", curheight, "castheight", castheight, "hash", common.ToHex(blockwithpid.Block.Hash(chain.client.GetConfig())), "pid", blockwithpid.Pid)
   283  		msg.Reply(chain.client.NewMessage("", types.EventReply, &reply))
   284  		return
   285  	}
   286  	_, err := chain.ProcAddBlockMsg(true, &types.BlockDetail{Block: blockwithpid.Block}, blockwithpid.Pid)
   287  	if err != nil {
   288  		chainlog.Error("EventBroadcastAddBlock", "height", castheight, "err", err.Error())
   289  		reply.IsOk = false
   290  		reply.Msg = []byte(err.Error())
   291  	}
   292  	chainlog.Debug("EventBroadcastAddBlock", "height", castheight, "hash", common.ToHex(blockwithpid.Block.Hash(chain.client.GetConfig())), "pid", blockwithpid.Pid)
   293  
   294  	msg.Reply(chain.client.NewMessage("", types.EventReply, &reply))
   295  }
   296  
   297  func (chain *BlockChain) getTransactionByAddr(msg *queue.Message) {
   298  	addr := (msg.Data).(*types.ReqAddr)
   299  	//chainlog.Warn("EventGetTransactionByAddr", "req", addr)
   300  	replyTxInfos, err := chain.ProcGetTransactionByAddr(addr)
   301  	if err != nil {
   302  		chainlog.Error("ProcGetTransactionByAddr", "err", err.Error())
   303  		msg.Reply(chain.client.NewMessage("rpc", types.EventReplyTxInfo, err))
   304  	} else {
   305  		//chainlog.Debug("EventGetTransactionByAddr", "success", "ok")
   306  		msg.Reply(chain.client.NewMessage("rpc", types.EventReplyTxInfo, replyTxInfos))
   307  	}
   308  }
   309  
   310  func (chain *BlockChain) getTransactionByHashes(msg *queue.Message) {
   311  	txhashs := (msg.Data).(*types.ReqHashes)
   312  	//chainlog.Info("EventGetTransactionByHash", "hash", txhashs)
   313  	TransactionDetails, err := chain.ProcGetTransactionByHashes(txhashs.Hashes)
   314  	if err != nil {
   315  		chainlog.Error("ProcGetTransactionByHashes", "err", err.Error())
   316  		msg.Reply(chain.client.NewMessage("rpc", types.EventTransactionDetails, err))
   317  	} else {
   318  		//chainlog.Debug("EventGetTransactionByHash", "success", "ok")
   319  		msg.Reply(chain.client.NewMessage("rpc", types.EventTransactionDetails, TransactionDetails))
   320  	}
   321  }
   322  
   323  func (chain *BlockChain) getBlockOverview(msg *queue.Message) {
   324  	ReqHash := (msg.Data).(*types.ReqHash)
   325  	BlockOverview, err := chain.ProcGetBlockOverview(ReqHash)
   326  	if err != nil {
   327  		chainlog.Error("ProcGetBlockOverview", "err", err.Error())
   328  		msg.Reply(chain.client.NewMessage("rpc", types.EventReplyBlockOverview, err))
   329  	} else {
   330  		//chainlog.Debug("ProcGetBlockOverview", "success", "ok")
   331  		msg.Reply(chain.client.NewMessage("rpc", types.EventReplyBlockOverview, BlockOverview))
   332  	}
   333  }
   334  
   335  func (chain *BlockChain) getAddrOverview(msg *queue.Message) {
   336  	addr := (msg.Data).(*types.ReqAddr)
   337  	AddrOverview, err := chain.ProcGetAddrOverview(addr)
   338  	if err != nil {
   339  		chainlog.Error("ProcGetAddrOverview", "err", err.Error())
   340  		msg.Reply(chain.client.NewMessage("rpc", types.EventReplyAddrOverview, err))
   341  	} else {
   342  		//chainlog.Debug("ProcGetAddrOverview", "success", "ok")
   343  		msg.Reply(chain.client.NewMessage("rpc", types.EventReplyAddrOverview, AddrOverview))
   344  	}
   345  }
   346  
   347  func (chain *BlockChain) getBlockHash(msg *queue.Message) {
   348  	height := (msg.Data).(*types.ReqInt)
   349  	replyhash, err := chain.ProcGetBlockHash(height)
   350  	if err != nil {
   351  		chainlog.Error("ProcGetBlockHash", "err", err.Error())
   352  		msg.Reply(chain.client.NewMessage("rpc", types.EventBlockHash, err))
   353  	} else {
   354  		//chainlog.Debug("ProcGetBlockHash", "success", "ok")
   355  		msg.Reply(chain.client.NewMessage("rpc", types.EventBlockHash, replyhash))
   356  	}
   357  }
   358  
   359  func (chain *BlockChain) addBlockHeaders(msg *queue.Message) {
   360  	var reply types.Reply
   361  	reply.IsOk = true
   362  	headerspid := msg.Data.(*types.HeadersPid)
   363  	err := chain.ProcAddBlockHeadersMsg(headerspid.Headers, headerspid.Pid)
   364  	if err != nil {
   365  		chainlog.Error("addBlockHeaders", "err", err.Error())
   366  		reply.IsOk = false
   367  		reply.Msg = []byte(err.Error())
   368  	} else {
   369  	}
   370  	chainlog.Debug("addBlockHeaders", "pid", headerspid.Pid, "success", "ok")
   371  	msg.Reply(chain.client.NewMessage("p2p", types.EventReply, &reply))
   372  }
   373  
   374  func (chain *BlockChain) getLastBlock(msg *queue.Message) {
   375  	block, err := chain.ProcGetLastBlockMsg()
   376  	if err != nil {
   377  		chainlog.Error("ProcGetLastBlockMsg", "err", err.Error())
   378  		msg.Reply(chain.client.NewMessage("consensus", types.EventBlock, err))
   379  	} else {
   380  		//chainlog.Debug("ProcGetLastBlockMsg", "success", "ok")
   381  		msg.Reply(chain.client.NewMessage("consensus", types.EventBlock, block))
   382  	}
   383  }
   384  
   385  func (chain *BlockChain) isNtpClockSyncFunc(msg *queue.Message) {
   386  	ok := chain.GetNtpClockSyncStatus()
   387  	msg.Reply(chain.client.NewMessage("", types.EventReplyIsNtpClockSync, &types.IsNtpClockSync{Isntpclocksync: ok}))
   388  }
   389  
   390  type funcProcess func(msg *queue.Message)
   391  
   392  func (chain *BlockChain) processMsg(msg *queue.Message, reqnum chan struct{}, cb funcProcess) {
   393  	beg := types.Now()
   394  	//NOTE: 由于部分msg做了内存回收处理,业务逻辑处理后不能对msg进行引用访问, 相关数据提前保存
   395  	ty := msg.Ty
   396  	defer func() {
   397  		<-reqnum
   398  		atomic.AddInt32(&chain.runcount, -1)
   399  		chainlog.Debug("process", "cost", types.Since(beg), "msg", types.GetEventName(int(ty)))
   400  		if r := recover(); r != nil {
   401  			chainlog.Error("blockchain panic error", "err", r)
   402  			msg.Reply(chain.client.NewMessage("", ty, fmt.Errorf("%s:%v", types.ErrExecPanic.Error(), r)))
   403  			return
   404  		}
   405  	}()
   406  	cb(msg)
   407  }
   408  
   409  //获取最新的block执行序列号
   410  func (chain *BlockChain) getLastBlockSequence(msg *queue.Message) {
   411  	var lastSequence types.Int64
   412  	var err error
   413  	lastSequence.Data, err = chain.blockStore.LoadBlockLastSequence()
   414  	if err != nil {
   415  		chainlog.Debug("getLastBlockSequence", "err", err)
   416  	}
   417  	msg.Reply(chain.client.NewMessage("rpc", types.EventReplyLastBlockSequence, &lastSequence))
   418  }
   419  
   420  //获取指定区间的block执行序列信息,包含blockhash和操作类型:add/del
   421  func (chain *BlockChain) getBlockSequences(msg *queue.Message) {
   422  	requestSequences := (msg.Data).(*types.ReqBlocks)
   423  	BlockSequences, err := chain.GetBlockSequences(requestSequences)
   424  	if err != nil {
   425  		chainlog.Error("GetBlockSequences", "err", err.Error())
   426  		msg.Reply(chain.client.NewMessage("rpc", types.EventReplyBlockSequences, err))
   427  	} else {
   428  		msg.Reply(chain.client.NewMessage("rpc", types.EventReplyBlockSequences, BlockSequences))
   429  	}
   430  }
   431  
   432  func (chain *BlockChain) getBlockByHashes(msg *queue.Message) {
   433  	blockhashes := (msg.Data).(*types.ReqHashes)
   434  	BlockDetails, err := chain.GetBlockByHashes(blockhashes.Hashes)
   435  	if err != nil {
   436  		chainlog.Error("GetBlockByHashes", "err", err.Error())
   437  		msg.Reply(chain.client.NewMessage("rpc", types.EventBlocks, err))
   438  	} else {
   439  		msg.Reply(chain.client.NewMessage("rpc", types.EventBlocks, BlockDetails))
   440  	}
   441  }
   442  
   443  func (chain *BlockChain) getBlockBySeq(msg *queue.Message) {
   444  	seq := (msg.Data).(*types.Int64)
   445  	req := &types.ReqBlocks{Start: seq.Data, End: seq.Data, IsDetail: false, Pid: []string{}}
   446  	sequences, err := chain.GetBlockSequences(req)
   447  	if err != nil {
   448  		chainlog.Error("getBlockBySeq", "seqUpdateChan err", err.Error())
   449  		msg.Reply(chain.client.NewMessage("rpc", types.EventGetBlockBySeq, err))
   450  		return
   451  	}
   452  	reqHashes := &types.ReqHashes{Hashes: [][]byte{sequences.Items[0].Hash}}
   453  	blocks, err := chain.GetBlockByHashes(reqHashes.Hashes)
   454  	if err != nil {
   455  		chainlog.Error("getBlockBySeq", "hash err", err.Error())
   456  		msg.Reply(chain.client.NewMessage("rpc", types.EventGetBlockBySeq, err))
   457  		return
   458  	}
   459  
   460  	blockSeq := &types.BlockSeq{
   461  		Num:    seq.Data,
   462  		Seq:    sequences.Items[0],
   463  		Detail: blocks.Items[0],
   464  	}
   465  	msg.Reply(chain.client.NewMessage("rpc", types.EventGetBlockBySeq, blockSeq))
   466  
   467  }
   468  
   469  //平行链del block的处理
   470  func (chain *BlockChain) delParaChainBlockDetail(msg *queue.Message) {
   471  	var parablockDetail *types.ParaChainBlockDetail
   472  	var reply types.Reply
   473  	reply.IsOk = true
   474  	parablockDetail = msg.Data.(*types.ParaChainBlockDetail)
   475  
   476  	chainlog.Debug("delParaChainBlockDetail", "height", parablockDetail.Blockdetail.Block.Height, "hash", common.HashHex(parablockDetail.Blockdetail.Block.Hash(chain.client.GetConfig())))
   477  
   478  	// 平行链上P2P模块关闭,不用广播区块
   479  	err := chain.ProcDelParaChainBlockMsg(false, parablockDetail, "self")
   480  	if err != nil {
   481  		chainlog.Error("ProcDelParaChainBlockMsg", "err", err.Error())
   482  		reply.IsOk = false
   483  		reply.Msg = []byte(err.Error())
   484  	}
   485  	chainlog.Debug("delParaChainBlockDetail", "success", "ok")
   486  	msg.Reply(chain.client.NewMessage("p2p", types.EventReply, &reply))
   487  }
   488  
   489  //平行链add block的处理
   490  func (chain *BlockChain) addParaChainBlockDetail(msg *queue.Message) {
   491  	parablockDetail := msg.Data.(*types.ParaChainBlockDetail)
   492  
   493  	//根据配置chain.cfgBatchSync和parablockDetail.IsSync
   494  	//来决定写数据库时是否需要刷盘,主要是为了同步阶段提高执行区块的效率
   495  	if !parablockDetail.IsSync && !chain.cfgBatchSync {
   496  		atomic.CompareAndSwapInt32(&chain.isbatchsync, 1, 0)
   497  	} else {
   498  		atomic.CompareAndSwapInt32(&chain.isbatchsync, 0, 1)
   499  	}
   500  
   501  	chainlog.Debug("EventAddParaChainBlockDetail", "height", parablockDetail.Blockdetail.Block.Height, "hash", common.HashHex(parablockDetail.Blockdetail.Block.Hash(chain.client.GetConfig())))
   502  	// 平行链上P2P模块关闭,不用广播区块
   503  	blockDetail, err := chain.ProcAddParaChainBlockMsg(false, parablockDetail, "self")
   504  	if err != nil {
   505  		chainlog.Error("ProcAddParaChainBlockMsg", "err", err.Error())
   506  		msg.Reply(chain.client.NewMessage("p2p", types.EventReply, err))
   507  	}
   508  	chainlog.Debug("EventAddParaChainBlockDetail", "success", "ok")
   509  	msg.Reply(chain.client.NewMessage("p2p", types.EventReply, blockDetail))
   510  }
   511  
   512  //parachian 通过blockhash获取对应的seq,只记录了addblock时的seq
   513  func (chain *BlockChain) getSeqByHash(msg *queue.Message) {
   514  	blockhash := (msg.Data).(*types.ReqHash)
   515  	seq, err := chain.ProcGetSeqByHash(blockhash.Hash)
   516  	if err != nil {
   517  		chainlog.Error("getSeqByHash", "err", err.Error())
   518  		msg.Reply(chain.client.NewMessage("rpc", types.EventReply, err))
   519  	}
   520  	msg.Reply(chain.client.NewMessage("rpc", types.EventGetSeqByHash, &types.Int64{Data: seq}))
   521  }
   522  
   523  //获取指定地址参与的tx交易计数
   524  func (chain *BlockChain) localAddrTxCount(msg *queue.Message) {
   525  	reqkey := (msg.Data).(*types.ReqKey)
   526  
   527  	count := types.Int64{}
   528  	var counts int64
   529  
   530  	TxsCount, err := chain.blockStore.db.Get(reqkey.Key)
   531  	if err != nil && err != types.ErrNotFound {
   532  		counts = 0
   533  		chainlog.Error("localAddrTxCount", "err", err.Error())
   534  		msg.Reply(chain.client.NewMessage("rpc", types.EventLocalReplyValue, &types.Int64{Data: counts}))
   535  		return
   536  	}
   537  	if len(TxsCount) == 0 {
   538  		counts = 0
   539  		chainlog.Error("localAddrTxCount", "TxsCount", "0")
   540  		msg.Reply(chain.client.NewMessage("rpc", types.EventLocalReplyValue, &types.Int64{Data: counts}))
   541  		return
   542  	}
   543  	err = types.Decode(TxsCount, &count)
   544  	if err != nil {
   545  		counts = 0
   546  		chainlog.Error("localAddrTxCount", "types.Decode", err)
   547  		msg.Reply(chain.client.NewMessage("rpc", types.EventLocalReplyValue, &types.Int64{Data: counts}))
   548  		return
   549  	}
   550  	counts = count.Data
   551  	msg.Reply(chain.client.NewMessage("rpc", types.EventLocalReplyValue, &types.Int64{Data: counts}))
   552  }
   553  
   554  //GetLastBlockMainSequence 获取最新的block执行序列号
   555  func (chain *BlockChain) GetLastBlockMainSequence(msg *queue.Message) {
   556  	var lastSequence types.Int64
   557  	var err error
   558  	lastSequence.Data, err = chain.blockStore.LoadBlockLastMainSequence()
   559  	if err != nil {
   560  		chainlog.Debug("GetLastBlockMainSequence", "err", err)
   561  		msg.Reply(chain.client.NewMessage("rpc", types.EventReplyLastBlockMainSequence, err))
   562  		return
   563  	}
   564  	msg.Reply(chain.client.NewMessage("rpc", types.EventReplyLastBlockMainSequence, &lastSequence))
   565  }
   566  
   567  //GetMainSeqByHash parachian 通过blockhash获取对应的seq,只记录了addblock时的seq
   568  func (chain *BlockChain) GetMainSeqByHash(msg *queue.Message) {
   569  	blockhash := (msg.Data).(*types.ReqHash)
   570  	seq, err := chain.ProcGetMainSeqByHash(blockhash.Hash)
   571  	if err != nil {
   572  		chainlog.Error("GetMainSeqByHash", "err", err.Error())
   573  		msg.Reply(chain.client.NewMessage("rpc", types.EventReplyMainSeqByHash, err))
   574  		return
   575  	}
   576  	msg.Reply(chain.client.NewMessage("rpc", types.EventReplyMainSeqByHash, &types.Int64{Data: seq}))
   577  }
   578  
   579  //setValueByKey 设置kv对到blockchain db中
   580  func (chain *BlockChain) setValueByKey(msg *queue.Message) {
   581  	var reply types.Reply
   582  	reply.IsOk = true
   583  	if !chain.isParaChain {
   584  		reply.IsOk = false
   585  		reply.Msg = []byte("Must Para Chain Support!")
   586  		msg.Reply(chain.client.NewMessage("", types.EventReply, &reply))
   587  		return
   588  	}
   589  	kvs := (msg.Data).(*types.LocalDBSet)
   590  	err := chain.SetValueByKey(kvs)
   591  	if err != nil {
   592  		chainlog.Error("setValueByKey", "err", err.Error())
   593  		reply.IsOk = false
   594  		reply.Msg = []byte(err.Error())
   595  	}
   596  	msg.Reply(chain.client.NewMessage("", types.EventReply, &reply))
   597  }
   598  
   599  //GetValueByKey 获取value通过key从blockchain db中
   600  func (chain *BlockChain) getValueByKey(msg *queue.Message) {
   601  	if !chain.isParaChain {
   602  		msg.Reply(chain.client.NewMessage("", types.EventLocalReplyValue, nil))
   603  		return
   604  	}
   605  	keys := (msg.Data).(*types.LocalDBGet)
   606  	values := chain.GetValueByKey(keys)
   607  	msg.Reply(chain.client.NewMessage("", types.EventLocalReplyValue, values))
   608  }
   609  
   610  //getParaTxByTitle //通过平行链title获取平行链的交易
   611  func (chain *BlockChain) getParaTxByTitle(msg *queue.Message) {
   612  	req := (msg.Data).(*types.ReqParaTxByTitle)
   613  	reply, err := chain.GetParaTxByTitle(req)
   614  	if err != nil {
   615  		chainlog.Error("getParaTxByTitle", "req", req, "err", err.Error())
   616  		msg.Reply(chain.client.NewMessage("", types.EventReplyParaTxByTitle, err))
   617  		return
   618  	}
   619  	msg.Reply(chain.client.NewMessage("", types.EventReplyParaTxByTitle, reply))
   620  }
   621  
   622  //getHeightByTitle //获取拥有此title交易的区块高度
   623  func (chain *BlockChain) getHeightByTitle(msg *queue.Message) {
   624  	req := (msg.Data).(*types.ReqHeightByTitle)
   625  	reply, err := chain.LoadParaTxByTitle(req)
   626  	if err != nil {
   627  		chainlog.Error("getHeightByTitle", "req", req, "err", err.Error())
   628  		msg.Reply(chain.client.NewMessage("", types.EventReplyHeightByTitle, err))
   629  		return
   630  	}
   631  	msg.Reply(chain.client.NewMessage("", types.EventReplyHeightByTitle, reply))
   632  }
   633  
   634  //getParaTxByTitleAndHeight //通过区块高度列表+title获取平行链交易
   635  func (chain *BlockChain) getParaTxByTitleAndHeight(msg *queue.Message) {
   636  	req := (msg.Data).(*types.ReqParaTxByHeight)
   637  	reply, err := chain.GetParaTxByHeight(req)
   638  	if err != nil {
   639  		chainlog.Error("getParaTxByTitleAndHeight", "req", req, "err", err.Error())
   640  		msg.Reply(chain.client.NewMessage("", types.EventReplyParaTxByTitle, err))
   641  		return
   642  	}
   643  	msg.Reply(chain.client.NewMessage("", types.EventReplyParaTxByTitle, reply))
   644  }
   645  
   646  // getChunkRecord // 获取当前chunk record
   647  func (chain *BlockChain) getChunkRecord(msg *queue.Message) {
   648  	req := (msg.Data).(*types.ReqChunkRecords)
   649  	reply, err := chain.GetChunkRecord(req)
   650  	if err != nil {
   651  		chainlog.Error("getChunkRecord", "req", req, "err", err.Error())
   652  		msg.Reply(chain.client.NewMessage("", types.EventGetChunkRecord, &types.Reply{IsOk: false, Msg: []byte(err.Error())}))
   653  		return
   654  	}
   655  	chainlog.Debug("getChunkRecord", "start", req.Start, "end", req.End)
   656  	msg.Reply(chain.client.NewMessage("", types.EventGetChunkRecord, reply))
   657  }
   658  
   659  // addChunkRecord // 添加chunk record
   660  func (chain *BlockChain) addChunkRecord(msg *queue.Message) {
   661  	req := (msg.Data).(*types.ChunkRecords)
   662  	chain.AddChunkRecord(req)
   663  	for _, info := range req.Infos {
   664  		chain.chunkRecordTask.Done(info.ChunkNum)
   665  		chainlog.Debug("addChunkRecord", "chunkNum", info.ChunkNum, "chunkHash", common.ToHex(info.ChunkHash))
   666  	}
   667  }
   668  
   669  // getChunkBlockBody // 获取chunk BlockBody
   670  func (chain *BlockChain) getChunkBlockBody(msg *queue.Message) {
   671  	req := (msg.Data).(*types.ChunkInfoMsg)
   672  	if req.End < (atomic.LoadInt64(&chain.maxSerialChunkNum)-int64(DelRollbackChunkNum)+1)*chain.cfg.ChunkblockNum {
   673  		msg.Reply(chain.client.NewMessage("", types.EventGetChunkBlockBody, types.ErrNotFound))
   674  		return
   675  	}
   676  	reply, err := chain.GetChunkBlockBody(req)
   677  	if err != nil {
   678  		msg.Reply(chain.client.NewMessage("", types.EventGetChunkBlockBody, &types.Reply{IsOk: false, Msg: []byte(err.Error())}))
   679  		return
   680  	}
   681  	chainlog.Debug("getChunkBlockBody", "start", req.Start, "end", req.End, "chunkHash", common.ToHex(req.ChunkHash))
   682  	msg.Reply(chain.client.NewMessage("", types.EventGetChunkBlockBody, reply))
   683  }
   684  
   685  // addChunkBlock // 添加chunk Block
   686  func (chain *BlockChain) addChunkBlock(msg *queue.Message) {
   687  	blocks := (msg.Data).(*types.Blocks)
   688  	if blocks == nil || len(blocks.Items) == 0 {
   689  		str := "blocks is nil"
   690  		chainlog.Error("addChunkBlock", "err", str)
   691  		return
   692  	}
   693  
   694  	if chain.GetDownloadSyncStatus() == chunkDownLoadMode {
   695  		for _, blk := range blocks.Items {
   696  			chain.WriteBlockToDbTemp(blk, true)
   697  			//downLoadTask 运行时设置对应的blockdone
   698  			if chain.downLoadTask.InProgress() {
   699  				chain.downLoadTask.Done(blk.Height)
   700  			}
   701  		}
   702  	} else {
   703  		for _, blk := range blocks.Items {
   704  			_, err := chain.ProcAddBlockMsg(false, &types.BlockDetail{Block: blk}, "-self") //这里认为非自己节点
   705  			if err != nil {
   706  				chainlog.Error("addChunkBlock ProcAddBlockMsg", "height", blk.Height, "err", err.Error())
   707  				return
   708  			}
   709  		}
   710  	}
   711  	chainlog.Debug("addChunkBlock", "start", blocks.Items[0].Height, "end", blocks.Items[len(blocks.Items)-1].Height)
   712  }
   713  
   714  func (chain *BlockChain) subscribePush(msg *queue.Message) {
   715  	reply := &types.ReplySubscribePush{
   716  		IsOk: true,
   717  		Msg:  "Succeed",
   718  	}
   719  	subReq := (msg.Data).(*types.PushSubscribeReq)
   720  	err := chain.procSubscribePush(subReq)
   721  	if err != nil {
   722  		reply.IsOk = false
   723  		reply.Msg = err.Error()
   724  		msg.Reply(chain.client.NewMessage("rpc", types.EventReplySubscribePush, reply))
   725  		return
   726  	}
   727  
   728  	msg.Reply(chain.client.NewMessage("rpc", types.EventReplySubscribePush, reply))
   729  }