add ProcessQC implementation

This commit is contained in:
Jianrong 2021-11-22 20:43:24 +11:00
parent b9068974f5
commit bd60e1b0cf
3 changed files with 36 additions and 26 deletions

View file

@ -35,7 +35,7 @@ type XDPoS_v2 struct {
currentRound utils.Round
highestVotedRound utils.Round
highestQuorumCert *utils.QuorumCert
// LockQC in XDPoS Consensus 2.0, used in voting rule
// lockQuorumCert in XDPoS Consensus 2.0, used in voting rule
lockQuorumCert *utils.QuorumCert
highestTimeoutCert *utils.TimeoutCert
highestCommitBlock *utils.BlockInfo
@ -79,6 +79,8 @@ func (x *XDPoS_v2) SetNewRoundFaker(newRound utils.Round, resetTimer bool) {
// Utils for test to check currentRound value
func (x *XDPoS_v2) GetCurrentRound() utils.Round {
x.lock.Lock()
defer x.lock.Unlock()
return x.currentRound
}
@ -307,22 +309,27 @@ func (x *XDPoS_v2) verifyTC(timeoutCert *utils.TimeoutCert) error {
return nil
}
// Update local QC variables including highestQC & lockQC, as well as update commit blockInfo before call
/*
1. Update HighestQC and LockQC
2. Update commit block info (TODO)
3. Check QC round >= node's currentRound. If yes, call setNewRound
*/
func (x *XDPoS_v2) processQC(quorumCert *utils.QuorumCert) error {
// Update local QC variables including highestQC & lockQuorumCert, as well as update commit blockInfo before call
func (x *XDPoS_v2) processQC(blockCahinReader consensus.ChainReader, quorumCert *utils.QuorumCert) error {
// 1. Update HighestQC
if x.highestQuorumCert == nil || quorumCert.ProposedBlockInfo.Round > x.highestQuorumCert.ProposedBlockInfo.Round {
x.highestQuorumCert = quorumCert
//TODO: do I need a clone?
x.highestQuorumCert = quorumCert
}
//TODO: x.blockchain.getBlock(quorumCert.ProposedBlockInfo.Hash) then get the QC inside that block header
//TODO: update lockQC
// 2. Get QC from header and update lockQuorumCert
proposedBlockHeader := blockCahinReader.GetHeaderByHash(quorumCert.ProposedBlockInfo.Hash)
var decodedExtraField utils.ExtraFields_v2
utils.DecodeBytesExtraFields(proposedBlockHeader.Extra, &decodedExtraField)
x.lockQuorumCert = &decodedExtraField.QuorumCert
// 3. Update commit block info
//TODO: find parent and grandparent and grandgrandparent block, check round number, if so, commit grandgrandparent
if quorumCert.ProposedBlockInfo.Round >= x.currentRound {
x.setNewRound(quorumCert.ProposedBlockInfo.Round + 1)
err := x.setNewRound(quorumCert.ProposedBlockInfo.Round + 1)
if err != nil {
return err
}
}
return nil
}
@ -364,8 +371,8 @@ func (x *XDPoS_v2) verifyVotingRule(header *types.Header) error {
Make sure this node has not voted for this round. We can have a variable highestVotedRound, and check currentRound > highestVotedRound.
HotStuff Voting rule:
header's round == local current round, AND (one of the following two:)
header's block extends LockQC's ProposedBlockInfo (we need a isExtending(block_a, block_b) function), OR
header's QC's ProposedBlockInfo.Round > LockQC's ProposedBlockInfo.Round
header's block extends lockQuorumCert's ProposedBlockInfo (we need a isExtending(block_a, block_b) function), OR
header's QC's ProposedBlockInfo.Round > lockQuorumCert's ProposedBlockInfo.Round
*/
return nil
}

View file

@ -4,6 +4,7 @@ import (
"github.com/XinFinOrg/XDPoSChain/consensus"
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS"
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
"github.com/XinFinOrg/XDPoSChain/core"
"github.com/XinFinOrg/XDPoSChain/log"
lru "github.com/hashicorp/golang-lru"
)
@ -18,10 +19,11 @@ type broadcastTimeoutFn func(*utils.Timeout)
type broadcastSyncInfoFn func(*utils.SyncInfo)
type Bfter struct {
broadcastCh chan interface{}
quit chan struct{}
consensus ConsensusFns
broadcast BroadcastFns
blockCahinReader *core.BlockChain
broadcastCh chan interface{}
quit chan struct{}
consensus ConsensusFns
broadcast BroadcastFns
// Message Cache
knownVotes *lru.ARCCache
@ -46,17 +48,18 @@ type BroadcastFns struct {
SyncInfo broadcastSyncInfoFn
}
func New(broadcasts BroadcastFns) *Bfter {
func New(broadcasts BroadcastFns, blockCahinReader *core.BlockChain) *Bfter {
knownVotes, _ := lru.NewARC(messageLimit)
knownSyncInfos, _ := lru.NewARC(messageLimit)
knownTimeouts, _ := lru.NewARC(messageLimit)
return &Bfter{
quit: make(chan struct{}),
broadcastCh: make(chan interface{}),
broadcast: broadcasts,
knownVotes: knownVotes,
knownSyncInfos: knownSyncInfos,
knownTimeouts: knownTimeouts,
quit: make(chan struct{}),
broadcastCh: make(chan interface{}),
broadcast: broadcasts,
knownVotes: knownVotes,
knownSyncInfos: knownSyncInfos,
knownTimeouts: knownTimeouts,
blockCahinReader: blockCahinReader,
}
}

View file

@ -227,7 +227,7 @@ func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, ne
Timeout: manager.BroadcastTimeout,
SyncInfo: manager.BroadcastSyncInfo,
}
manager.bfter = bfter.New(broadcasts)
manager.bfter = bfter.New(broadcasts, blockchain)
if blockchain.Config().XDPoS != nil {
manager.bfter.SetConsensusFuns(engine)
}