基於泰嶽鏈實現Tendermint POS的細節 (二):換屆

對於公有區塊鏈來說,由於委員會成員會更迭,自然會有成員的退出和更新,本文介紹的是一種POS的實現,委員會之間的通信使用Tendermint,普通節點使用devp2p會存在兩個p2p連接。

這是基於上一篇基於以太坊實現Tendermint POS的細節 (一):選舉寫的,沒看的可以瞭解下。

PBFT Server初始化

初始化本地配置

  • 端口
  • IP
  • 私鑰

agentTendermint和應用協議的橋樑。

func (s *Taiyuechain) startPbftServer() error {
	priv, err := crypto.ToECDSA(s.config.CommitteeKey)

	cfg := config.DefaultConfig()
	cfg.P2P.ListenAddress1 = "tcp://0.0.0.0:" + strconv.Itoa(s.config.Port)
	cfg.P2P.ListenAddress2 = "tcp://0.0.0.0:" + strconv.Itoa(s.config.StandbyPort)

	n1, err := tbft.NewNode(cfg, "1", priv, s.agent)
	s.pbftServer = n1
	return n1.Start()
}

PBFT的幾種事件

委員會啓動

需要傳遞給Server界數,委員會成員,本屆開始高度。

		e.electionFeed.Send(types.ElectionEvent{
			Option:           types.CommitteeStart,
			CommitteeID:      e.committee.id,
			CommitteeMembers: members,
			BeginFastNumber:  e.committee.beginFastNumber,
		})

選舉點

訂閱區塊上鍊的chainHead事件,獲取當前上鍊高度。

	func (e *Election) subScribeEvent() {
		e.chainHeadSub = e.fastchain.SubscribeChainHeadEvent(e.chainHeadCh)
	}

當塊高度等於選舉點,計算本屆結束高度,和下屆委員會成員。

  • 本屆結束高度
    計算出本屆結束高度,通知server。
    		e.electionFeed.Send(types.ElectionEvent{
    			Option:           types.CommitteeOver,
    			CommitteeID:      e.committee.id,
    			CommitteeMembers: e.committee.Members(),
    			BeginFastNumber:  e.committee.beginFastNumber,
    			EndFastNumber:    e.committee.endFastNumber,
    		})
    
  • 下屆選舉
    需要計算下屆委員會成員,下屆開始高度
    		e.electionFeed.Send(types.ElectionEvent{
    			Option:           types.CommitteeSwitchover,
    			CommitteeID:      e.nextCommittee.id,
    			CommitteeMembers: e.nextCommittee.Members(),
    			BeginFastNumber:  e.nextCommittee.beginFastNumber,
    		})
    

換屆點

當塊高度等於換屆點,本屆委員會停止工作,啓動下屆委員會。

  • 本屆結束
    通知server退出,結束端口監聽
    	e.electionFeed.Send(types.ElectionEvent{
    		Option:           types.CommitteeOver,
    		CommitteeID:      e.committee.id,
    		CommitteeMembers: e.committee.Members(),
    		BeginFastNumber:  e.committee.beginFastNumber,
    		EndFastNumber:    e.committee.endFastNumber,
    	})
    
  • 下屆開始工作
    設置下屆委員會成員爲本屆成員,啓動委員會。
    	e.committee = e.nextCommittee
    
    	e.electionFeed.Send(types.ElectionEvent{
    		Option:           types.CommitteeStart,
    		CommitteeID:      e.committee.id,
    		CommitteeMembers: e.committee.Members(),
    		BeginFastNumber:  e.committee.beginFastNumber,
    	})
    

    同步中的問題

    當一個新節點啓動的時候,會向其他節點同步數據,這時候計算委員會會有一些問題。因爲當有一批數據上鍊時,只有最後一個區塊發出chainhead事件,這時候上面的流程會有跳過。
    func (e *Election) getCommitteeInfoByCommitteeId(committeeId *big.Int) *committee {
    	begin, end := types.GetEpochHeigth(committeeId)
    	committee := &committee{
    		id:              committeeId,
    		beginFastNumber: new(big.Int).Set(begin),
    		endFastNumber:   new(big.Int).Set(end),
    	}
    	caCertPubkeyList := e.getCACertList()
    	committee.members = e.assignmentCommitteeMember(caCertPubkeyList, committeeId)
    	return committee
    }
    
    計算最新高度的委員會成員,並賦值給當前屆,這樣區塊中籤名的驗證就可以通過了。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章