diff options
author | Jimmy Hu <jimmy.hu@dexon.org> | 2019-04-02 19:04:17 +0800 |
---|---|---|
committer | Wei-Ning Huang <w@byzantine-lab.io> | 2019-06-15 22:09:55 +0800 |
commit | 35917e287ceb506f98c80c9e25ead762738d58b5 (patch) | |
tree | a338e1c78c6a6a70ba803631c313b9bfab275c9a /vendor/github.com/dexon-foundation/dexon-consensus | |
parent | bd0a9ffa31539f43e4deb3aaf6e48a72571253fa (diff) | |
download | go-tangerine-35917e287ceb506f98c80c9e25ead762738d58b5.tar go-tangerine-35917e287ceb506f98c80c9e25ead762738d58b5.tar.gz go-tangerine-35917e287ceb506f98c80c9e25ead762738d58b5.tar.bz2 go-tangerine-35917e287ceb506f98c80c9e25ead762738d58b5.tar.lz go-tangerine-35917e287ceb506f98c80c9e25ead762738d58b5.tar.xz go-tangerine-35917e287ceb506f98c80c9e25ead762738d58b5.tar.zst go-tangerine-35917e287ceb506f98c80c9e25ead762738d58b5.zip |
vendor: sync to latest core
Diffstat (limited to 'vendor/github.com/dexon-foundation/dexon-consensus')
11 files changed, 243 insertions, 188 deletions
diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement-mgr.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement-mgr.go index 423174c48..8cb4c2e37 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement-mgr.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement-mgr.go @@ -22,11 +22,11 @@ import ( "errors" "math" "sync" - "sync/atomic" "time" "github.com/dexon-foundation/dexon-consensus/common" "github.com/dexon-foundation/dexon-consensus/core/types" + typesDKG "github.com/dexon-foundation/dexon-consensus/core/types/dkg" "github.com/dexon-foundation/dexon-consensus/core/utils" ) @@ -35,6 +35,7 @@ var ( ErrPreviousRoundIsNotFinished = errors.New("previous round is not finished") ErrRoundOutOfRange = errors.New("round out of range") ErrInvalidBlock = errors.New("invalid block") + ErrNoValidLeader = errors.New("no valid leader") ) const maxResultCache = 100 @@ -89,7 +90,9 @@ func newAgreementMgrConfig(prev agreementMgrConfig, config *types.Config, } type baRoundSetting struct { - notarySet map[types.NodeID]struct{} + round uint64 + dkgSet map[types.NodeID]struct{} + threshold int ticker Ticker crs common.Hash } @@ -132,13 +135,9 @@ func newAgreementMgr(con *Consensus) (mgr *agreementMgr, err error) { voteFilter: utils.NewVoteFilter(), } mgr.recv = &consensusBAReceiver{ - consensus: con, - restartNotary: make(chan types.Position, 1), - roundValue: &atomic.Value{}, - changeNotaryHeightValue: &atomic.Value{}, + consensus: con, + restartNotary: make(chan types.Position, 1), } - mgr.recv.updateRound(uint64(0)) - mgr.recv.changeNotaryHeightValue.Store(uint64(0)) return mgr, nil } @@ -177,6 +176,19 @@ func (mgr *agreementMgr) run() { }() } +func (mgr *agreementMgr) calcLeader( + dkgSet map[types.NodeID]struct{}, + crs common.Hash, pos types.Position) ( + types.NodeID, error) { + nodeSet := types.NewNodeSetFromMap(dkgSet) + leader := nodeSet.GetSubSet(1, types.NewNodeLeaderTarget( + crs, pos.Height)) + for nID := range leader { + return nID, nil + } + return types.NodeID{}, ErrNoValidLeader +} + func (mgr *agreementMgr) config(round uint64) *agreementMgrConfig { mgr.lock.RLock() defer mgr.lock.RUnlock() @@ -201,13 +213,6 @@ func (mgr *agreementMgr) notifyRoundEvents(evts []utils.RoundEventParam) error { } if lastCfg.RoundID() == e.Round { mgr.configs[len(mgr.configs)-1].ExtendLength() - // It's not an atomic operation to update an atomic value based - // on another. However, it's the best way so far to extend - // length of round without refactoring. - if mgr.recv.round() == e.Round { - mgr.recv.changeNotaryHeightValue.Store( - mgr.configs[len(mgr.configs)-1].RoundEndHeight()) - } } else if lastCfg.RoundID()+1 == e.Round { mgr.configs = append(mgr.configs, newAgreementMgrConfig( lastCfg, e.Config, e.CRS)) @@ -285,10 +290,6 @@ func (mgr *agreementMgr) processAgreementResult( } } else if result.Position.Newer(aID) { mgr.logger.Info("Fast syncing BA", "position", result.Position) - nIDs, err := mgr.cache.GetNotarySet(result.Position.Round) - if err != nil { - return err - } if result.Position.Round < DKGDelayRound { mgr.logger.Debug("Calling Network.PullBlocks for fast syncing BA", "hash", result.BlockHash) @@ -299,13 +300,19 @@ func (mgr *agreementMgr) processAgreementResult( } } } - mgr.logger.Debug("Calling Governance.CRS", "round", result.Position.Round) - crs := utils.GetCRSWithPanic(mgr.gov, result.Position.Round, mgr.logger) - leader, err := mgr.cache.GetLeaderNode(result.Position) + setting := mgr.generateSetting(result.Position.Round) + if setting == nil { + mgr.logger.Warn("unable to get setting", "round", + result.Position.Round) + return ErrConfigurationNotReady + } + leader, err := mgr.calcLeader(setting.dkgSet, setting.crs, result.Position) if err != nil { return err } - mgr.baModule.restart(nIDs, result.Position, leader, crs) + mgr.baModule.restart( + setting.dkgSet, setting.threshold, + result.Position, leader, setting.crs) if result.Position.Round >= DKGDelayRound { return mgr.baModule.processAgreementResult(result) } @@ -333,57 +340,87 @@ func (mgr *agreementMgr) stop() { mgr.waitGroup.Wait() } +func (mgr *agreementMgr) generateSetting(round uint64) *baRoundSetting { + curConfig := mgr.config(round) + if curConfig == nil { + return nil + } + var dkgSet map[types.NodeID]struct{} + if round >= DKGDelayRound { + _, qualidifed, err := typesDKG.CalcQualifyNodes( + mgr.gov.DKGMasterPublicKeys(round), + mgr.gov.DKGComplaints(round), + utils.GetDKGThreshold(mgr.gov.Configuration(round)), + ) + if err != nil { + mgr.logger.Error("Failed to get gpk", "round", round, "error", err) + return nil + } + dkgSet = qualidifed + } + if len(dkgSet) == 0 { + var err error + dkgSet, err = mgr.cache.GetNotarySet(round) + if err != nil { + mgr.logger.Error("Failed to get notarySet", "round", round) + return nil + } + } + return &baRoundSetting{ + crs: curConfig.crs, + dkgSet: dkgSet, + round: round, + threshold: utils.GetBAThreshold(&types.Config{ + NotarySetSize: curConfig.notarySetSize}), + } +} + func (mgr *agreementMgr) runBA(initRound uint64) { // These are round based variables. var ( currentRound uint64 nextRound = initRound curConfig = mgr.config(initRound) - setting = baRoundSetting{} + setting = &baRoundSetting{} tickDuration time.Duration + ticker Ticker ) // Check if this routine needs to awake in this round and prepare essential // variables when yes. - checkRound := func() (isNotary bool) { + checkRound := func() (isDKG bool) { defer func() { currentRound = nextRound nextRound++ }() // Wait until the configuartion for next round is ready. for { - if curConfig = mgr.config(nextRound); curConfig != nil { + if setting = mgr.generateSetting(nextRound); setting != nil { break } else { mgr.logger.Debug("Round is not ready", "round", nextRound) time.Sleep(1 * time.Second) } } - // Check if this node in notary set of this chain in this round. - notarySet, err := mgr.cache.GetNotarySet(nextRound) - if err != nil { - panic(err) - } - setting.crs = curConfig.crs - setting.notarySet = notarySet - _, isNotary = setting.notarySet[mgr.ID] - if isNotary { - mgr.logger.Info("Selected as notary set", + _, isDKG = setting.dkgSet[mgr.ID] + if isDKG { + mgr.logger.Info("Selected as dkg set", "ID", mgr.ID, "round", nextRound) } else { - mgr.logger.Info("Not selected as notary set", + mgr.logger.Info("Not selected as dkg set", "ID", mgr.ID, "round", nextRound) } // Setup ticker if tickDuration != curConfig.lambdaBA { - if setting.ticker != nil { - setting.ticker.Stop() + if ticker != nil { + ticker.Stop() } - setting.ticker = newTicker(mgr.gov, nextRound, TickerBA) + ticker = newTicker(mgr.gov, nextRound, TickerBA) tickDuration = curConfig.lambdaBA } + setting.ticker = ticker return } Loop: @@ -395,15 +432,25 @@ Loop: } mgr.recv.isNotary = checkRound() // Run BA for this round. - mgr.recv.updateRound(currentRound) - mgr.recv.changeNotaryHeightValue.Store(curConfig.RoundEndHeight()) mgr.recv.restartNotary <- types.Position{ - Round: mgr.recv.round(), + Round: currentRound, Height: math.MaxUint64, } mgr.voteFilter = utils.NewVoteFilter() mgr.recv.emptyBlockHashMap = &sync.Map{} - if err := mgr.baRoutineForOneRound(&setting); err != nil { + if currentRound >= DKGDelayRound && mgr.recv.isNotary { + var err error + mgr.recv.npks, mgr.recv.psigSigner, err = + mgr.con.cfgModule.getDKGInfo(currentRound, false) + if err != nil { + mgr.logger.Warn("cannot get dkg info", + "round", currentRound, "error", err) + } + } else { + mgr.recv.npks = nil + mgr.recv.psigSigner = nil + } + if err := mgr.baRoutineForOneRound(setting); err != nil { mgr.logger.Error("BA routine failed", "error", err, "nodeID", mgr.ID) @@ -419,7 +466,7 @@ func (mgr *agreementMgr) baRoutineForOneRound( oldPos := agr.agreementID() restart := func(restartPos types.Position) (breakLoop bool, err error) { if !isStop(restartPos) { - if restartPos.Round > oldPos.Round { + if restartPos.Height+1 >= mgr.config(setting.round).RoundEndHeight() { for { select { case <-mgr.ctx.Done(): @@ -427,14 +474,12 @@ func (mgr *agreementMgr) baRoutineForOneRound( default: } tipRound := mgr.bcModule.tipRound() - if tipRound > restartPos.Round { - // It's a vary rare that this go routine sleeps for entire round. + if tipRound > setting.round { break - } else if tipRound != restartPos.Round { - mgr.logger.Debug("Waiting blockChain to change round...", - "pos", restartPos) } else { - break + mgr.logger.Debug("Waiting blockChain to change round...", + "curRound", setting.round, + "tipRound", tipRound) } time.Sleep(100 * time.Millisecond) } @@ -459,9 +504,6 @@ func (mgr *agreementMgr) baRoutineForOneRound( default: } nextHeight, nextTime = mgr.bcModule.nextBlock() - if isStop(oldPos) && nextHeight == 0 { - break - } if isStop(restartPos) { break } @@ -473,18 +515,18 @@ func (mgr *agreementMgr) baRoutineForOneRound( time.Sleep(100 * time.Millisecond) } nextPos := types.Position{ - Round: recv.round(), + Round: setting.round, Height: nextHeight, } oldPos = nextPos var leader types.NodeID - leader, err = mgr.cache.GetLeaderNode(nextPos) + leader, err = mgr.calcLeader(setting.dkgSet, setting.crs, nextPos) if err != nil { return } time.Sleep(nextTime.Sub(time.Now())) setting.ticker.Restart() - agr.restart(setting.notarySet, nextPos, leader, setting.crs) + agr.restart(setting.dkgSet, setting.threshold, nextPos, leader, setting.crs) return } Loop: diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement.go index f2a9e3def..b122a4ddf 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement.go @@ -160,7 +160,8 @@ func newAgreement( // restart the agreement func (a *agreement) restart( - notarySet map[types.NodeID]struct{}, aID types.Position, leader types.NodeID, + notarySet map[types.NodeID]struct{}, + threshold int, aID types.Position, leader types.NodeID, crs common.Hash) { if !func() bool { a.lock.Lock() @@ -181,7 +182,7 @@ func (a *agreement) restart( a.data.votes[1] = newVoteListMap() a.data.period = 2 a.data.blocks = make(map[types.NodeID]*types.Block) - a.data.requiredVote = len(notarySet)*2/3 + 1 + a.data.requiredVote = threshold a.data.leader.restart(crs) a.data.lockValue = types.SkipBlockHash a.data.lockIter = 0 @@ -289,9 +290,11 @@ func (a *agreement) restart( } func (a *agreement) stop() { - a.restart(make(map[types.NodeID]struct{}), types.Position{ - Height: math.MaxUint64, - }, types.NodeID{}, common.Hash{}) + a.restart(make(map[types.NodeID]struct{}), int(math.MaxInt32), + types.Position{ + Height: math.MaxUint64, + }, + types.NodeID{}, common.Hash{}) } func isStop(aID types.Position) bool { @@ -399,6 +402,9 @@ func (a *agreement) prepareVote(vote *types.Vote) (err error) { } func (a *agreement) updateFilter(filter *utils.VoteFilter) { + if isStop(a.agreementID()) { + return + } a.lock.RLock() defer a.lock.RUnlock() a.data.lock.RLock() @@ -417,6 +423,7 @@ func (a *agreement) processVote(vote *types.Vote) error { return err } aID := a.agreementID() + // Agreement module has stopped. if isStop(aID) { // Hacky way to not drop first votes for genesis height. diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/blockchain.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/blockchain.go index 2d67d626f..9fbb86162 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/blockchain.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/blockchain.go @@ -137,11 +137,14 @@ type blockChain struct { vGetter tsigVerifierGetter app Application logger common.Logger - pendingRandomnesses map[types.Position]*types.AgreementResult + pendingRandomnesses map[types.Position][]byte configs []blockChainConfig pendingBlocks pendingBlockRecords confirmedBlocks types.BlocksByPosition dMoment time.Time + + // Do not access this variable besides processAgreementResult. + lastPosition types.Position } func newBlockChain(nID types.NodeID, dMoment time.Time, initBlock *types.Block, @@ -157,7 +160,7 @@ func newBlockChain(nID types.NodeID, dMoment time.Time, initBlock *types.Block, logger: logger, dMoment: dMoment, pendingRandomnesses: make( - map[types.Position]*types.AgreementResult), + map[types.Position][]byte), } } @@ -629,10 +632,7 @@ func (bc *blockChain) confirmBlock(b *types.Block) { func (bc *blockChain) setRandomnessFromPending(b *types.Block) bool { if r, exist := bc.pendingRandomnesses[b.Position]; exist { - if !r.BlockHash.Equal(b.Hash) { - panic(fmt.Errorf("mismathed randomness: %s %s", b, r)) - } - b.Randomness = r.Randomness + b.Randomness = r delete(bc.pendingRandomnesses, b.Position) return true } @@ -643,6 +643,9 @@ func (bc *blockChain) processAgreementResult(result *types.AgreementResult) erro if result.Position.Round < DKGDelayRound { return nil } + if !result.Position.Newer(bc.lastPosition) { + return ErrSkipButNoError + } ok, err := bc.verifyRandomness( result.BlockHash, result.Position.Round, result.Randomness) if err != nil { @@ -656,6 +659,19 @@ func (bc *blockChain) processAgreementResult(result *types.AgreementResult) erro if !result.Position.Newer(bc.lastDelivered.Position) { return nil } - bc.pendingRandomnesses[result.Position] = result + bc.pendingRandomnesses[result.Position] = result.Randomness + bc.lastPosition = bc.lastDelivered.Position return nil } + +func (bc *blockChain) addBlockRandomness(pos types.Position, rand []byte) { + if pos.Round < DKGDelayRound { + return + } + bc.lock.Lock() + defer bc.lock.Unlock() + if !pos.Newer(bc.lastDelivered.Position) { + return + } + bc.pendingRandomnesses[pos] = rand +} diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/configuration-chain.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/configuration-chain.go index c8aac38bc..fbd504d24 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/configuration-chain.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/configuration-chain.go @@ -586,8 +586,19 @@ func (cc *configurationChain) recoverDKGInfo( // Restore group public key. cc.logger.Debug("Calling Governance.DKGMasterPublicKeys for recoverDKGInfo", "round", round) + mpk := cc.gov.DKGMasterPublicKeys(round) cc.logger.Debug("Calling Governance.DKGComplaints for recoverDKGInfo", "round", round) + comps := cc.gov.DKGComplaints(round) + qualifies, _, err := typesDKG.CalcQualifyNodes(mpk, comps, threshold) + if err != nil { + return err + } + if len(qualifies) < + utils.GetDKGValidThreshold(utils.GetConfigWithPanic( + cc.gov, round, cc.logger)) { + return typesDKG.ErrNotReachThreshold + } npks, err := typesDKG.NewNodePublicKeys(round, cc.gov.DKGMasterPublicKeys(round), cc.gov.DKGComplaints(round), diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/consensus.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/consensus.go index 57b30383c..e657c6449 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/consensus.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/consensus.go @@ -22,7 +22,6 @@ import ( "encoding/hex" "fmt" "sync" - "sync/atomic" "time" "github.com/dexon-foundation/dexon-consensus/common" @@ -60,23 +59,13 @@ var ( // consensusBAReceiver implements agreementReceiver. type consensusBAReceiver struct { - consensus *Consensus - agreementModule *agreement - changeNotaryHeightValue *atomic.Value - roundValue *atomic.Value - emptyBlockHashMap *sync.Map - isNotary bool - restartNotary chan types.Position - npks *typesDKG.NodePublicKeys - psigSigner *dkgShareSecret -} - -func (recv *consensusBAReceiver) round() uint64 { - return recv.roundValue.Load().(uint64) -} - -func (recv *consensusBAReceiver) changeNotaryHeight() uint64 { - return recv.changeNotaryHeightValue.Load().(uint64) + consensus *Consensus + agreementModule *agreement + emptyBlockHashMap *sync.Map + isNotary bool + restartNotary chan types.Position + npks *typesDKG.NodePublicKeys + psigSigner *dkgShareSecret } func (recv *consensusBAReceiver) emptyBlockHash(pos types.Position) ( @@ -99,17 +88,13 @@ func (recv *consensusBAReceiver) emptyBlockHash(pos types.Position) ( } func (recv *consensusBAReceiver) VerifyPartialSignature(vote *types.Vote) bool { - if recv.round() >= DKGDelayRound && vote.BlockHash != types.SkipBlockHash { + if vote.Position.Round >= DKGDelayRound && vote.BlockHash != types.SkipBlockHash { if vote.Type == types.VoteCom || vote.Type == types.VoteFastCom { - if recv.npks == nil || recv.npks.Round != vote.Position.Round { - var err error - recv.npks, _, err = - recv.consensus.cfgModule.getDKGInfo(vote.Position.Round, true) - if err != nil || recv.npks == nil { - recv.consensus.logger.Warn("cannot get npks", - "round", vote.Position.Round, "error", err) - return false - } + if recv.npks == nil { + return false + } + if vote.Position.Round != recv.npks.Round { + return false } pubKey, exist := recv.npks.PublicKeys[vote.ProposerID] if !exist { @@ -138,11 +123,9 @@ func (recv *consensusBAReceiver) ProposeVote(vote *types.Vote) { if !recv.isNotary { return } - if recv.round() >= DKGDelayRound && vote.BlockHash != types.SkipBlockHash { + if recv.psigSigner != nil && + vote.BlockHash != types.SkipBlockHash { if vote.Type == types.VoteCom || vote.Type == types.VoteFastCom { - if recv.psigSigner == nil { - return - } if vote.BlockHash == types.NullBlockHash { hash, err := recv.emptyBlockHash(vote.Position) if err != nil { @@ -272,7 +255,7 @@ func (recv *consensusBAReceiver) ConfirmBlock( if vote.BlockHash != hash { continue } - if recv.round() >= DKGDelayRound { + if block.Position.Round >= DKGDelayRound { ID, exist := recv.npks.IDMap[vote.ProposerID] if !exist { continue @@ -282,7 +265,7 @@ func (recv *consensusBAReceiver) ConfirmBlock( } voteList = append(voteList, *vote) } - if recv.round() >= DKGDelayRound { + if block.Position.Round >= DKGDelayRound { rand, err := cryptoDKG.RecoverSignature(psigs, IDs) if err != nil { recv.consensus.logger.Warn("Unable to recover randomness", @@ -303,17 +286,13 @@ func (recv *consensusBAReceiver) ConfirmBlock( IsEmptyBlock: isEmptyBlockConfirmed, Randomness: block.Randomness, } + recv.consensus.baMgr.touchAgreementResult(result) recv.consensus.logger.Debug("Broadcast AgreementResult", "result", result) recv.consensus.network.BroadcastAgreementResult(result) if block.IsEmpty() { - if err := - recv.consensus.bcModule.processAgreementResult( - result); err != nil { - recv.consensus.logger.Warn( - "Failed to process agreement result", - "result", result) - } + recv.consensus.bcModule.addBlockRandomness( + block.Position, block.Randomness) } if block.Position.Round >= DKGDelayRound { recv.consensus.logger.Debug( @@ -385,23 +364,7 @@ CleanChannelLoop: break CleanChannelLoop } } - newPos := block.Position - changeNotaryHeight := recv.changeNotaryHeight() - if block.Position.Height+1 >= changeNotaryHeight { - recv.consensus.logger.Info("Round will change", - "block", block, - "change-height", changeNotaryHeight) - newPos.Round++ - recv.updateRound(newPos.Round) - } - currentRound := recv.round() - if block.Position.Height > changeNotaryHeight && - block.Position.Round < currentRound { - panic(fmt.Errorf( - "round not switch when confirming: %s, %d, should switch at %d, %s", - block, currentRound, changeNotaryHeight, newPos)) - } - recv.restartNotary <- newPos + recv.restartNotary <- block.Position } func (recv *consensusBAReceiver) PullBlocks(hashes common.Hashes) { @@ -420,18 +383,6 @@ func (recv *consensusBAReceiver) ReportForkBlock(b1, b2 *types.Block) { recv.consensus.gov.ReportForkBlock(b1, b2) } -func (recv *consensusBAReceiver) updateRound(round uint64) { - recv.roundValue.Store(round) - var err error - _, recv.psigSigner, err = - recv.consensus.cfgModule.getDKGInfo(round, false) - if err != nil { - recv.consensus.logger.Warn("cannot get dkg info", - "round", round, "error", err) - recv.psigSigner = nil - } -} - // consensusDKGReceiver implements dkgReceiver. type consensusDKGReceiver struct { ID types.NodeID @@ -774,12 +725,13 @@ func (con *Consensus) prepare(initBlock *types.Block) (err error) { // modules see the up-to-date node set, we need to make sure this action // should be taken as the first one. con.roundEvent.Register(func(evts []utils.RoundEventParam) { - defer elapse("purge-node-set", evts[len(evts)-1])() + defer elapse("purge-cache", evts[len(evts)-1])() for _, e := range evts { if e.Reset == 0 { continue } con.nodeSetCache.Purge(e.Round + 1) + con.tsigVerifierCache.Purge(e.Round + 1) } }) // Register round event handler to abort previous running DKG if any. @@ -895,13 +847,64 @@ func (con *Consensus) prepare(initBlock *types.Block) (err error) { e := evts[len(evts)-1] defer elapse("touch-NodeSetCache", e)() con.event.RegisterHeight(e.NextTouchNodeSetCacheHeight(), func(uint64) { - if err := con.nodeSetCache.Touch(e.Round + 1); err != nil { - con.logger.Warn("Failed to update nodeSetCache", - "round", e.Round+1, - "error", err) + if e.Reset == 0 { + return } + go func() { + nextRound := e.Round + 1 + if err := con.nodeSetCache.Touch(nextRound); err != nil { + con.logger.Warn("Failed to update nodeSetCache", + "round", nextRound, + "error", err) + } + }() }) }) + con.roundEvent.Register(func(evts []utils.RoundEventParam) { + e := evts[len(evts)-1] + if e.Reset != 0 { + return + } + defer elapse("touch-DKGCache", e)() + go func() { + if _, err := + con.tsigVerifierCache.Update(e.Round); err != nil { + con.logger.Warn("Failed to update tsig cache", + "round", e.Round, + "error", err) + } + }() + go func() { + threshold := utils.GetDKGThreshold( + utils.GetConfigWithPanic(con.gov, e.Round, con.logger)) + // Restore group public key. + con.logger.Debug( + "Calling Governance.DKGMasterPublicKeys for recoverDKGInfo", + "round", e.Round) + con.logger.Debug( + "Calling Governance.DKGComplaints for recoverDKGInfo", + "round", e.Round) + _, qualifies, err := typesDKG.CalcQualifyNodes( + con.gov.DKGMasterPublicKeys(e.Round), + con.gov.DKGComplaints(e.Round), + threshold) + if err != nil { + con.logger.Warn("Failed to calculate dkg set", + "round", e.Round, + "error", err) + return + } + if _, exist := qualifies[con.ID]; !exist { + return + } + if _, _, err := + con.cfgModule.getDKGInfo(e.Round, true); err != nil { + con.logger.Warn("Failed to recover DKG info", + "round", e.Round, + "error", err) + } + }() + }) // checkCRS is a generator of checker to check if CRS for that round is // ready or not. checkCRS := func(round uint64) func() bool { @@ -1090,12 +1093,7 @@ func (con *Consensus) generateBlockRandomness(blocks []*types.Block) { Position: block.Position, Randomness: sig.Signature[:], } - if err := con.bcModule.processAgreementResult(result); err != nil { - con.logger.Error("Failed to process BlockRandomness", - "result", result, - "error", err) - return - } + con.bcModule.addBlockRandomness(block.Position, sig.Signature[:]) con.logger.Debug("Broadcast BlockRandomness", "block", block, "result", result) @@ -1320,8 +1318,7 @@ MessageLoop: // ProcessVote is the entry point to submit ont vote to a Consensus instance. func (con *Consensus) ProcessVote(vote *types.Vote) (err error) { - v := vote.Clone() - err = con.baMgr.processVote(v) + err = con.baMgr.processVote(vote) return } @@ -1338,6 +1335,9 @@ func (con *Consensus) ProcessAgreementResult( } if err := con.bcModule.processAgreementResult(rand); err != nil { con.baMgr.untouchAgreementResult(rand) + if err == ErrSkipButNoError { + return nil + } return err } // Syncing BA Module. diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/dkg-tsig-protocol.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/dkg-tsig-protocol.go index 9a71bea1f..e4ae14c2c 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/dkg-tsig-protocol.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/dkg-tsig-protocol.go @@ -555,7 +555,7 @@ func (tc *TSigVerifierCache) UpdateAndGet(round uint64) ( return v, ok, nil } -// Purge the cache and returns if success. +// Purge the cache. func (tc *TSigVerifierCache) Purge(round uint64) { tc.lock.Lock() defer tc.lock.Unlock() diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/types/block.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/block.go index cff954652..1dcd41b9e 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/types/block.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/block.go @@ -83,7 +83,7 @@ type Block struct { Payload []byte `json:"payload"` PayloadHash common.Hash `json:"payload_hash"` Witness Witness `json:"witness"` - Randomness []byte `json:"finalization"` + Randomness []byte `json:"randomness"` Signature crypto.Signature `json:"signature"` CRSSignature crypto.Signature `json:"crs_signature"` diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/types/dkg/dkg.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/dkg/dkg.go index 301cef7da..e9b22bcb0 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/types/dkg/dkg.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/dkg/dkg.go @@ -345,7 +345,7 @@ func CalcQualifyNodes( } } for nID, complaints := range complaintsByID { - if len(complaints) > threshold { + if len(complaints) >= threshold { disqualifyIDs[nID] = struct{}{} } } diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/nodeset-cache.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/nodeset-cache.go index 89ebd2409..89dcfc86b 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/nodeset-cache.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/nodeset-cache.go @@ -36,10 +36,9 @@ var ( ) type sets struct { - crs common.Hash - nodeSet *types.NodeSet - notarySet map[types.NodeID]struct{} - leaderNode map[uint64]types.NodeID + crs common.Hash + nodeSet *types.NodeSet + notarySet map[types.NodeID]struct{} } // NodeSetCacheInterface interface specifies interface used by NodeSetCache. @@ -133,30 +132,6 @@ func (cache *NodeSetCache) GetNotarySet( return cache.cloneMap(IDs.notarySet), nil } -// GetLeaderNode returns the BA leader of the position. -func (cache *NodeSetCache) GetLeaderNode(pos types.Position) ( - types.NodeID, error) { - IDs, err := cache.getOrUpdate(pos.Round) - if err != nil { - return types.NodeID{}, err - } - cache.lock.Lock() - defer cache.lock.Unlock() - if _, exist := IDs.leaderNode[pos.Height]; !exist { - notarySet := types.NewNodeSetFromMap(IDs.notarySet) - leader := notarySet.GetSubSet(1, types.NewNodeLeaderTarget( - IDs.crs, pos.Height)) - if len(leader) != 1 { - panic(errors.New("length of leader is not one")) - } - for nID := range leader { - IDs.leaderNode[pos.Height] = nID - break - } - } - return IDs.leaderNode[pos.Height], nil -} - // Purge a specific round. func (cache *NodeSetCache) Purge(rID uint64) { cache.lock.Lock() @@ -238,10 +213,9 @@ func (cache *NodeSetCache) update(round uint64) (nIDs *sets, err error) { return } nIDs = &sets{ - crs: crs, - nodeSet: nodeSet, - notarySet: make(map[types.NodeID]struct{}), - leaderNode: make(map[uint64]types.NodeID, cfg.RoundLength), + crs: crs, + nodeSet: nodeSet, + notarySet: make(map[types.NodeID]struct{}), } nIDs.notarySet = nodeSet.GetSubSet( int(cfg.NotarySetSize), types.NewNotarySetTarget(crs)) diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/round-event.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/round-event.go index 472c7247b..602d2da16 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/round-event.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/round-event.go @@ -79,7 +79,7 @@ func (e RoundEventParam) NextRoundHeight() uint64 { // NextTouchNodeSetCacheHeight returns the height to touch the node set cache. func (e RoundEventParam) NextTouchNodeSetCacheHeight() uint64 { - return e.BeginHeight + e.Config.RoundLength*9/10 + return e.BeginHeight + e.Config.RoundLength/2 } // NextDKGResetHeight returns the height to reset DKG for next period. diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/utils.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/utils.go index e6739ce2b..1a372c70c 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/utils.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/utils.go @@ -144,6 +144,11 @@ func GetDKGValidThreshold(config *types.Config) int { return int(config.NotarySetSize * 5 / 6) } +// GetBAThreshold return threshold for BA votes. +func GetBAThreshold(config *types.Config) int { + return int(config.NotarySetSize*2/3 + 1) +} + // GetNextRoundValidationHeight returns the block height to check if the next // round is ready. func GetNextRoundValidationHeight(begin, length uint64) uint64 { |