[blockchain-031] tendermint的主要目录代码概述 blockchain/mempool/consensus/rpc以及本地读块和验证块

1.blockchain目录
  1.1 reator.go 
    BlockchainReactor结构体,这里有BlocPool和BlockStore和BlockExecutor,BlockRequest通道,TimeoutsCh通道
      BlockPool是存放区块的池,如果是fastSync,就立刻开始Start(),然后bcR开始poolRoutine()协程进行区块同步。
      respondToPeer,如果本机有某个块,把它发给请求这个块的节点。
      Receive,从peer节点接收到消息,处理消息:请求块的,返回块的,请求状态的,返回状态的
      poolRoutine(),很长很重要。比如每次同步数据,要取两个,因为第一个块的有些确认信息,要根据第二个块的信息获取。


  1.2 store.go
    一个简单的level db 存储。存三种信息,blockmeta, block part, commit.
    LoadBlock从数据库读某个高度的块。
    LoadBlockPart读块的数据
    这是一个很简单的东东
  
  1.3 pool.go
    BlockPool 启动服务,有锁,记录其他peer的请求命令,记录其他peer的节点信息,有请求通道和超时通道
    启动时,makeRequestersRoutine()函数运行
    这也是一个比较简单的东东


2. mempool目录
  2.1 reactor.go
    MempoolReactor 启动服务,操作mempool
    Receive函数,从其他peer那里接受到trans然后放到mempool做check
    broadcastTxRoutine函数,把新的mempool的txs发给peer,如果没有新的tx进来,可能block会永远锁住。


  2.2 mempool.go 主要是处理txs的
    mempool是一个有序的内存池,存放txs。这些txs将会被推送给consensus round。在txs被加入到mempool之前,会被abci server的checktx函数处理。
    mempool把tx推给proxyAppConn,然后从proxy得到一个(req, res)的tuple流。 
    mempool用一个可并发的linked-list存储好的txs,多个协程并发调用.NextWait安全遍历linked-list获取每一个元素。
    Consensus调用Update()和Reap()做同步; 有些peer调用CheckTx(); 有些Peer遍历txs; 一个协程周期调用GarbageCollectTxs()垃圾收集。


    clist.CList 并发链list
    txCache 存放tx的缓存
    proxyAppConn app连接代理(不知道是代理abci server还是其他peer)
    
    函数FlushAppConn,让异步的resCb调用执行
    函数resCb,对abci服务的回调函数。
    
  2.3 综上所述,mempool是一个存放还没有被打包的txs的地方,然后,有其他协程从这里读取txs,生成块,然后再进行投票到区块链的操作。


3.  consensus目录


  3.1 state.go 
    3.1.1 ConsensusState 共识算法实现,处理vote和proposal,达成一致。将block提交到链上,并执行一些应用。内部状态机 从peer获得输入,内部validator,以及定时器。
      函数createProposalBlock(),创建块。它被defaultDecideProposal调用。defaultDecideProposal被赋值给decideProposal。decideProposal被enterPropose调用。
      enterPropose被handleTimeout函数调用。handleTimeout被receiveRoutine函数调用。
      receiveRoutine函数是主协程,当它的timeoutTicker定时器被触发,就执行一次handleTimeout,然后进行一次提交。
      receiveRoutine被OnStart()函数调用。
      consensus共识,最后一轮提交给peer,然后再返回一个成功的消息,发到一个channel,通知mempool的。


3.rpc目录
  3.1 rpc/core目录
    3.1.1 mempool.go 这是rpc操作到mempool的各种函数,其中BroadcastTxCommit是新txs提交commit函数。
      这里的memppool对象,是rpc/core/pipe.go:49的types.Mempool
      types.Mempool定义在tendermint/types/service.go:21,是interface。这里解释说,Mempool是ConsensusState使用的,提交block时候需要进行同步,这样app可以重设状态。(没看懂)
      在pipe.go有个函数SetMempool,是设置Mempool的,这个函数只被调用一次,也就是tendermint/node/node.go:446: rpccore.SetMempool(n.mempoolReactor.Mempool),也就是说,这里的mempool是mempool/mempool。 
    3.1.2 对BroadcastTxCommit进行分析:
      提交是否成功,是从deliverTxResCh取值进行判断,超时是失败。
      tx用来生成q查询语句
      deliverTxResCh和q被eventBus提交给mempool(提交到mempool就等待commit消息回来,如果超时等不到,就失败,在超时之前,会做一次checktx,如果checktx失败,就不等了,直接返回错误),这一步的提交,就等结果了。在mempool/mempool.go里如何处理这一步?肯定会有一个将commit结果写入到channel的步骤,也就是源码的      
    3.1.3 以前,在"Added to prevote"步骤,出现了错误,没有进行下午,然后过了几秒,出现Timed out,在
I[04-26|06:09:12.561] Added to prevote                             module=consensus vote="Vote{0:6B09230E6A6D 14119/00/1(Prevote) DDB2114740D6 {/232021B125E3.../} @ 2018-04-26T06:09:12.512Z}" prevotes="VoteSet{H:14119 R:0 T:1 +2/3:<nil> BA{2:X_} map[]}"


I[04-26|06:09:15.438] Timed out                                    module=consensus dur=3s height=14119 round=0 step=RoundStepPropose
      这个代码在consensus/state.go:1377,也就是addVote函数。这个函数被tryAddVote函数调用。tryAddVote函数被handleMsg函数调用。handleMsg被receiveRoutine调用。
      所以下次调试,要在这里进行。
      


--------------------
1. 如何从levedb里读取块


func (bcR *BlockchainReactor) respondToPeer(msg *bcBlockRequestMessage, src p2p.Peer) (queued bool) {
block := bcR.store.LoadBlock(msg.Height)
if block != nil {
msg := &bcBlockResponseMessage{Block: block}
return src.TrySend(BlockchainChannel, struct{ BlockchainMessage }{msg})
}


bcR.Logger.Info("Peer asking for a block we don't have", "src", src, "height", msg.Height)


return src.TrySend(BlockchainChannel, struct{ BlockchainMessage }{
&bcNoBlockResponseMessage{Height: msg.Height},
})
}




2.如何验证一个块的有效性
在blockchain/reactor.go的poolRoutine函数


3. 如何存储一个块,同上。





猜你喜欢

转载自blog.csdn.net/u011539200/article/details/80222636