@@ -219,14 +219,11 @@ func (s *Smr) ResetProposerStatus(tipBlock cctx.BlockInterface,
219219 s .mtx .Lock ()
220220 defer s .mtx .Unlock ()
221221
222- if bytes .Equal (s .getHighQC ().GetProposalId (), tipBlock .GetBlockid ()) {
222+ if bytes .Equal (s .getHighQC ().GetProposalId (), tipBlock .GetBlockid ()) &&
223+ s .validNewHighQC (tipBlock .GetBlockid (), validators ) {
223224 // 此处需要获取带签名的完整Justify
224225 return false , s .getCompleteHighQC (), nil
225226 }
226- // 单个节点不存在投票验证的hotstuff流程,因此返回true
227- if len (validators ) == 1 {
228- return false , nil , nil
229- }
230227
231228 // 从当前TipBlock开始往前追溯,交给smr根据状态进行回滚。
232229 // 在本地状态树上找到指代TipBlock的QC,若找不到,则在状态树上找和TipBlock同一分支上的最近值
@@ -384,10 +381,43 @@ func (s *Smr) ProcessProposal(viewNumber int64, proposalID []byte, parentID []by
384381 }
385382 go s .p2p .SendMessage (createNewBCtx (), netMsg , p2p .WithAccounts (s .removeLocalValidator (validatesIpInfo )))
386383 s .localProposal .Store (utils .F (proposalID ), proposal .Timestamp )
387- s .log .Debug ("smr:ProcessProposal::new proposal has been made" , "address" , s .address , "proposalID" , utils .F (proposalID ))
384+ // 若为单候选人情况,则此处需要特殊处理,矿工需要给自己提前签名
385+ if len (validatesIpInfo ) == 1 {
386+ s .voteToSelf (viewNumber , proposalID , parentQuorumCert )
387+ }
388+ s .log .Debug ("smr:ProcessProposal::new proposal has been made" , "address" , s .address , "proposalID" , utils .F (proposalID ), "target" , validatesIpInfo )
388389 return nil
389390}
390391
392+ func (s * Smr ) voteToSelf (viewNumber int64 , proposalID []byte , parent storage.QuorumCertInterface ) {
393+ selfVote := & storage.VoteInfo {
394+ ProposalId : proposalID ,
395+ ProposalView : viewNumber ,
396+ ParentId : parent .GetProposalId (),
397+ }
398+ selfLedgerInfo := & storage.LedgerCommitInfo {
399+ VoteInfoHash : proposalID ,
400+ }
401+ selfQC := storage .NewQuorumCert (selfVote , selfLedgerInfo , nil )
402+ selfSign , err := s .cryptoClient .SignVoteMsg (proposalID )
403+ if err != nil {
404+ s .log .Error ("smr::voteProposal::voteToSelf error" , "err" , err )
405+ return
406+ }
407+ s .qcVoteMsgs .LoadOrStore (utils .F (proposalID ), []* chainedBftPb.QuorumCertSign {selfSign })
408+ selfNode := & storage.ProposalNode {
409+ In : selfQC ,
410+ }
411+ if err := s .qcTree .UpdateQcStatus (selfNode ); err != nil {
412+ s .log .Error ("smr::voteProposal::updateQcStatus error" , "err" , err )
413+ return
414+ }
415+ // 更新本地smr状态机
416+ s .pacemaker .AdvanceView (selfQC )
417+ s .qcTree .UpdateHighQC (proposalID )
418+ s .log .Debug ("smr:voteProposal::done local voting" , "address" , s .address , "proposalID" , utils .F (proposalID ))
419+ }
420+
391421// reloadJustifyQC 与LibraBFT不同,返回一个指定的parentQC
392422func (s * Smr ) reloadJustifyQC (parentID []byte ) (storage.QuorumCertInterface , error ) {
393423 // 第一次proposal,highQC==rootQC==genesisQC
@@ -695,6 +725,9 @@ func (s *Smr) validNewHighQC(inProposalId []byte, validators []string) bool {
695725 if ! ok {
696726 return false
697727 }
728+ if len (validators ) == 1 {
729+ return len (signs ) == len (validators )
730+ }
698731 return s .saftyrules .CalVotesThreshold (len (signs ), len (validators ))
699732}
700733
0 commit comments