@@ -24,7 +24,7 @@ import (
2424
2525const (
2626 tickOnCalcBlock = time .Second
27- syncOnstatusChangeTimeout = 1 * time .Minute
27+ syncOnStatusChangeTimeout = 1 * time .Minute
2828
2929 statusFollowing = 0
3030 statusMining = 1
@@ -65,21 +65,26 @@ func (t *Miner) ProcBlock(ctx xctx.XContext, block *lpb.InternalBlock) error {
6565 return nil
6666}
6767
68+ // Start
6869// 启动矿工,周期检查矿工身份
69- // 同一时间,矿工状态是唯一的。0:休眠中 1:同步区块中 2:打包区块中
70+ // 同一时间,矿工状态是唯一的
71+ // 0:休眠中 1:同步区块中 2:打包区块中
7072func (t * Miner ) Start () {
73+ var err error
74+
7175 // 用于监测退出
7276 t .exitWG .Add (1 )
7377 defer t .exitWG .Done ()
7478
75- var err error
79+ // 节点初始状态为同步节点
7680 t .status = statusFollowing
7781
82+ // 开启挖矿前先同步区块
7883 ctx := & xctx.BaseCtx {
7984 XLog : t .log ,
8085 Timer : timer .NewXTimer (),
8186 }
82- t .syncWithNeighbors (ctx )
87+ _ = t .syncWithNeighbors (ctx )
8388
8489 // 启动矿工循环
8590 for ! t .IsExit () {
@@ -124,6 +129,7 @@ func (t *Miner) step() error {
124129 Timer : timer .NewXTimer (),
125130 }
126131
132+ // 账本和状态机最新区块id不一致,需要进行一次同步
127133 if ! bytes .Equal (ledgerTipId , stateTipId ) {
128134 err := t .ctx .State .Walk (ledgerTipId , false )
129135 if err != nil {
@@ -136,37 +142,51 @@ func (t *Miner) step() error {
136142 ctx .GetLog ().Trace ("miner step" , "ledgerTipHeight" , ledgerTipHeight , "ledgerTipId" ,
137143 utils .F (ledgerTipId ), "stateTipId" , utils .F (stateTipId ))
138144
145+ // 如果上次角色是非矿工,则尝试同步网络最新区块
146+ // 注意:这里出现错误也要继续执行,防止恶意节点错误出块导致流程无法继续执行
147+ if t .status == statusFollowing {
148+ err := t .syncWithValidators (ctx , syncOnStatusChangeTimeout )
149+ ctx .GetLog ().Trace ("miner syncWithValidators before CompeteMaster" , "originTipHeight" , ledgerTipHeight ,
150+ "currentLedgerHeight" , t .ctx .Ledger .GetMeta ().TrunkHeight , "err" , err )
151+ trace ("syncUpValidators" )
152+ }
153+
139154 // 通过共识检查矿工身份
140155 isMiner , isSync , err := t .ctx .Consensus .CompeteMaster (ledgerTipHeight + 1 )
141156 trace ("competeMaster" )
142157 ctx .GetLog ().Trace ("compete master result" , "height" , ledgerTipHeight + 1 , "isMiner" , isMiner , "isSync" , isSync , "err" , err )
143158 if err != nil {
144159 return err
145160 }
146- // 如需要同步,尝试同步网络最新区块
147- if isMiner && isSync {
148- err = t .syncWithValidators (ctx , syncOnstatusChangeTimeout )
149- if err != nil {
150- return err
151- }
152- }
153- trace ("syncUpValidators" )
154161
155162 // 如果是矿工,出块
156163 if isMiner {
157- if t .status == statusFollowing {
164+ if t .status == statusFollowing || isSync {
158165 ctx .GetLog ().Info ("miner change follow=>miner" ,
159166 "miner" , t .ctx .Address .Address ,
160167 "netAddr" , t .ctx .EngCtx .Net .PeerInfo ().Id ,
161168 "height" , t .ctx .Ledger .GetMeta ().GetTrunkHeight (),
162169 )
170+
163171 // 在由非矿工向矿工切换的这次"边沿触发",主动向所有的验证集合的最长链进行一次区块同步
164- err = t .syncWithValidators (ctx , syncOnstatusChangeTimeout )
172+ err = t .syncWithValidators (ctx , syncOnStatusChangeTimeout )
165173 if err != nil {
174+ ctx .GetLog ().Error ("miner change follow=>miner syncWithValidators failed" , "err" , err )
166175 return err
167176 }
177+
178+ // 由于同步了最长链,所以这里需要检查链是否增长
179+ // 由于pos和poa类共识依赖账本高度来判断状态,如果链发生变化则表明CompeteMaster的结果需要重新根据当前最新高度计算
180+ if ledgerTipHeight != t .ctx .Ledger .GetMeta ().TrunkHeight {
181+ ctx .GetLog ().Trace ("miner change follow=>miner" , "originTipHeight" , ledgerTipHeight , "currentLedgerHeight" ,
182+ t .ctx .Ledger .GetMeta ().TrunkHeight , "isMiner" , isMiner , "isSync" , isSync )
183+ return nil
184+ }
185+ trace ("syncUpValidators" )
168186 }
169187 t .status = statusMining
188+
189+ // 开始挖矿
170190 err = t .mining (ctx )
171191 if err != nil {
172192 return err
@@ -192,7 +212,7 @@ func (t *Miner) step() error {
192212 return nil
193213}
194214
195- // 挖矿生产区块
215+ // mining 挖矿生产区块
196216func (t * Miner ) mining (ctx xctx.XContext ) error {
197217 ctx .GetLog ().Debug ("mining start." )
198218
@@ -213,6 +233,7 @@ func (t *Miner) mining(ctx xctx.XContext) error {
213233 }
214234 // 重置高度
215235 height = t .ctx .Ledger .GetMeta ().TrunkHeight + 1
236+ ctx .GetLog ().Debug ("truncateTarget result" , "newHeight" , height )
216237 }
217238
218239 // 2.打包区块
@@ -249,6 +270,8 @@ func (t *Miner) mining(ctx xctx.XContext) error {
249270 "blockId" , utils .F (block .GetBlockid ()))
250271 return err
251272 }
273+
274+ // 5.可插拔共识,根据区块高度确认是否需要切换升级共识实例
252275 err = t .ctx .Consensus .SwitchConsensus (block .Height )
253276 if err != nil {
254277 ctx .GetLog ().Warn ("SwitchConsensus failed" , "bcname" , t .ctx .BCName ,
0 commit comments