TM的完整日志可以在这里获取。本文用的日志文件来自TM v0.16。
I[03-25|04:40:48.219] Starting multiAppConn module=proxy impl=multiAppConn
I[03-25|04:40:48.219] Starting localClient module=abci-client connection=query impl=localClient
I[03-25|04:40:48.219] Starting localClient module=abci-client connection=mempool impl=localClient
I[03-25|04:40:48.219] Starting localClient module=abci-client connection=consensus impl=localClient
首先,创建了多个应用连接(multiAppConn),具体是三个连接(query,mempool和consensu)。注意:这里的应用是指在本地以dummy运行。
接着Tendermint Core和应用完成了一次握手。
I[03-25|04:40:48.219] ABCI Handshake module=consensus appHeight=0 appHash=
I[03-25|04:40:48.219] ABCI Replay Blocks module=consensus appHeight=0 storeHeight=0 stateHeight=0
I[03-25|04:40:48.219] Completed ABCI Handshake - Tendermint and App are synced module=consensus appHeight=0 appHash=
之后,开启了一系列的服务(为正式启动node做准备),例如事件开关(event switch),reactor以及为了检测IP地址,完成了UPNP发现。
I[03-25|04:40:48.219] This node is a validator module=consensus addr=BD8F0160796AEC1E6454C55CCA6AF15EACF94A2D pubKey={PubKeyInner:PubKeyEd25519{7A4BCE42785BF1B008E2B2B9117FB617153597E9E3BBE00BB93889DFA7885461}}
I[03-25|04:40:48.243] Starting Node module=main impl=Node
I[03-25|04:40:48.243] Starting EventBus module=events impl=EventBus
I[03-25|04:40:48.243] Starting RPC HTTP server on tcp socket 0.0.0.0:46657 module=rpc-server
I[03-25|04:40:48.244] Local listener module=p2p ip=:: port=46656
I[03-25|04:40:48.244] Getting UPNP external address module=p2p
I[03-25|04:40:51.244] Could not perform UPNP discover module=p2p err="read udp4 0.0.0.0:50863: i/o timeout"
I[03-25|04:40:51.244] Starting DefaultListener module=p2p impl=Listener(@172.31.22.212:46656)
I[03-25|04:40:51.244] P2P Node ID module=main ID=6082741e5b3494908078fe5f473563f1c483d79e file=/opt/datadir/tendermint/config/node_key.json
I[03-25|04:40:51.244] Starting P2P Switch module=p2p impl="P2P Switch"
I[03-25|04:40:51.244] Starting EvidenceReactor module=evidence impl=EvidenceReactor
I[03-25|04:40:51.245] Starting PEXReactor module=p2p impl=PEXReactor
I[03-25|04:40:51.245] Starting AddrBook module=p2p book=/opt/datadir/tendermint/config/addrbook.json impl=AddrBook
I[03-25|04:40:51.245] Starting MempoolReactor module=mempool impl=MempoolReactor
I[03-25|04:40:51.245] Starting BlockchainReactor module=blockchain impl=BlockchainReactor
I[03-25|04:40:51.245] Starting ConsensusReactor module=consensus impl=ConsensusReactor
I[03-25|04:40:51.245] ConsensusReactor module=consensus fastSync=false
I[03-25|04:40:51.245] Starting ConsensusState module=consensus impl=ConsensusState
I[03-25|04:40:51.245] Starting baseWAL module=consensus wal=/opt/datadir/tendermint/data/cs.wal/wal impl=baseWAL
I[03-25|04:40:51.247] Starting TimeoutTicker module=consensus impl=TimeoutTicker
注意第一行,Tendermint Core报告,“此节点是验证人”。这里也可以只是观察人(正规节点)。第二行报告,Starting Node,这预示系统正式进入启动node的处理逻辑中。
接着,我们中继了来自WAL的所有消息。
I[03-25|04:40:51.248] Catchup by replaying consensus messages module=consensus height=1
I[03-25|04:40:51.248] Replay: Done module=consensus
“Started node”消息预示着node启动完毕,随时准备区块创建。
I[03-25|04:40:51.248] Started node module=main nodeInfo="NodeInfo{pk: {PubKeyEd25519{54E665EFA8EF7AD5763C421129F66FBD367B253788543C0E1B9CF047C45771D3}}, moniker: bootnode-hongkong, network: test-chain-MErM3n [listen 172.31.22.212:46656], version: 0.16.0 ([wire_version=0.7.2 p2p_version=0.5.0 consensus_version=v1/0.2.2 rpc_version=0.7.0/3 tx_index=on rpc_addr=tcp://0.0.0.0:46657])}"
接着是一个标准的区块创建过程,即进入到新的一轮中,提案一个区块,接收超过2/3的预投票(prevote),接着预提交(precommit)并且最终提交一个区块(finalise)。其中的细节,可以参阅介绍Tendermint共识的其他文章。
I[03-25|04:40:51.250] enterNewRound(1/0). Current: 1/0/RoundStepNewHeight module=consensus
I[03-25|04:40:51.250] enterPropose(1/0). Current: 1/0/RoundStepNewRound module=consensus
I[03-25|04:40:51.250] enterPropose: Our turn to propose module=consensus proposer=BD8F0160796AEC1E6454C55CCA6AF15EACF94A2D privValidator="PrivValidator{BD8F0160796AEC1E6454C55CCA6AF15EACF94A2D LH:0, LR:0, LS:0}"
I[03-25|04:40:51.253] Signed proposal module=consensus height=1 round=0 proposal="Proposal{1/0 1:57D9BC19067F (-1,:0:000000000000) {/3FB2AD239E88.../} @ 2018-03-25T04:40:51.250Z}"
I[03-25|04:40:51.259] Received complete proposal block module=consensus height=1 hash=2CFA5BC56A2E5D0BB94B84EB35AD05CC8F47CC49
I[03-25|04:40:51.259] enterPrevote(1/0). Current: 1/0/RoundStepPropose module=consensus
I[03-25|04:40:51.259] enterPrevote: ProposalBlock is valid module=consensus height=1 round=0
I[03-25|04:40:51.261] Signed and pushed vote module=consensus height=1 round=0 vote="Vote{0:BD8F0160796A 1/00/1(Prevote) 2CFA5BC56A2E {/347B4DC16274.../} @ 2018-03-25T04:40:51.259Z}" err=null
I[03-25|04:40:51.265] Added to prevote module=consensus vote="Vote{0:BD8F0160796A 1/00/1(Prevote) 2CFA5BC56A2E {/347B4DC16274.../} @ 2018-03-25T04:40:51.259Z}" prevotes="VoteSet{H:1 R:0 T:1 +2/3:2CFA5BC56A2E5D0BB94B84EB35AD05CC8F47CC49:1:57D9BC19067F BA{1:X} map[]}"
I[03-25|04:40:51.265] enterPrecommit(1/0). Current: 1/0/RoundStepPrevote module=consensus
I[03-25|04:40:51.265] enterPrecommit: +2/3 prevoted proposal block. Locking module=consensus hash=2CFA5BC56A2E5D0BB94B84EB35AD05CC8F47CC49
I[03-25|04:40:51.267] Signed and pushed vote module=consensus height=1 round=0 vote="Vote{0:BD8F0160796A 1/00/2(Precommit) 2CFA5BC56A2E {/1AB356C41018.../} @ 2018-03-25T04:40:51.265Z}" err=null
I[03-25|04:40:51.271] Added to precommit module=consensus vote="Vote{0:BD8F0160796A 1/00/2(Precommit) 2CFA5BC56A2E {/1AB356C41018.../} @ 2018-03-25T04:40:51.265Z}" precommits="VoteSet{H:1 R:0 T:2 +2/3:2CFA5BC56A2E5D0BB94B84EB35AD05CC8F47CC49:1:57D9BC19067F BA{1:X} map[]}"
I[03-25|04:40:51.271] enterCommit(1/0). Current: 1/0/RoundStepPrecommit module=consensus
I[03-25|04:40:51.274] Finalizing commit of block with 0 txs module=consensus height=1 hash=2CFA5BC56A2E5D0BB94B84EB35AD05CC8F47CC49 root=
I[03-25|04:40:51.274] Block{
Header{
ChainID: test-chain-MErM3n
Height: 1
Time: 2018-03-25 12:40:51.25 +0800 CST
NumTxs: 0
TotalTxs: 0
LastBlockID: :0:000000000000
LastCommit:
Data:
Validators: 7DBC0AC152D72CA2DA37CAB8D6D5A73B8DA9DC43
App:
Conensus: 0B8CEF95EC57AC2D96038FD0AE3901C14FAE8E73
Results:
Evidence:
}#2CFA5BC56A2E5D0BB94B84EB35AD05CC8F47CC49
Data{
}#
Data{
}#
Commit{
BlockID: :0:000000000000
Precommits:
}#
}#2CFA5BC56A2E5D0BB94B84EB35AD05CC8F47CC49 module=consensus
I[03-25|04:40:51.279] Executed block module=state height=1 validTxs=0 invalidTxs=0
I[03-25|04:40:51.281] Committed state module=state height=1 txs=0 appHash=0000000000000000
I[03-25|04:40:51.281] Recheck txs module=mempool numtxs=0 height=1
你可能在Tendermint的日志中看到下面这些模块。这里简单综述一下它们是做什么的。
abci-client:Tendermint充当有关一个应用的ABCI客户端,并且维护3个连接:mempool,consensu和query。
blockchain:提供存储,pool(一组peers)以及在peers之间存储以及交换区块的reactor。
consensus:Tendermint core的核心,实现了共识算法。包括两个“子模块”:wal(write-ahead logging,预写式日志)用于保证数据完整性和replay:宕机恢复后replay区块和消息。
events:简单的事件通知系统。你可以用过调用subscribe RPC方法来订阅。
mempool:内存池模块会处理所有流入系统的交易,不论它们是来自peers(即peers也可以产生交易)还是应用(应用也可以产生交易,当然主要是应用产生)。
p2p:围绕点对点通信提供了抽象。
rpc:Tendermint的RPC服务。
rpc-server:RPC服务器。
state:表示最近的状态和执行子模块(根据应用执行区块)。
types:一组公开暴露的类型和方法。
区块链的日志体系很强大,通过日志我们可以知道很多技术细节。我想日志体系可能是构建基础服务类软件的重器之一吧。本文翻译了官方文档之“如何阅读日志”,在尊重原文的基础上,略做了少许注释。有关TM的更多细节可以参考我们的文章。它们是:
1、安装Tendermint
2、Windows下编译Tendermint源码遇到的坑
3、TM白皮书
4、Tendermint源码分析—协议参数部分
5、Tendermint的初始化流程分析
6、Tendermint源码分析之peer建立连接