From 0542a6a1b13c3c1235f68a2d0cca23976c241ca9 Mon Sep 17 00:00:00 2001 From: Jimmy Hu Date: Mon, 5 Nov 2018 13:58:18 +0800 Subject: vendor: sync to latest core --- .../dexon-consensus/core/agreement-state.go | 2 +- .../dexon-consensus/core/agreement.go | 45 ++++++++++------ .../dexon-consensus/core/configuration-chain.go | 63 +++++++++++++++++----- .../dexon-consensus/core/consensus.go | 27 ++++++---- .../dexon-consensus/core/constant.go | 25 +++++++++ .../dexon-consensus/core/crypto.go | 4 ++ .../dexon-consensus/core/lattice-data.go | 3 ++ .../dexon-consensus/core/types/block.go | 3 +- .../dexon-consensus/core/types/position.go | 2 +- .../dexon-consensus/core/types/vote.go | 5 +- .../dexon-foundation/dexon-consensus/core/utils.go | 11 ++++ 11 files changed, 146 insertions(+), 44 deletions(-) create mode 100644 vendor/github.com/dexon-foundation/dexon-consensus/core/constant.go (limited to 'vendor/github.com') diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement-state.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement-state.go index 77569d549..fe329f832 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement-state.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement-state.go @@ -118,9 +118,9 @@ func newCommitState(a *agreementData) *commitState { func (s *commitState) state() agreementStateType { return stateCommit } func (s *commitState) clocks() int { return 2 } func (s *commitState) nextState() (agreementState, error) { - hash, ok := s.a.countVote(s.a.period, types.VotePreCom) s.a.lock.Lock() defer s.a.lock.Unlock() + hash, ok := s.a.countVoteNoLock(s.a.period, types.VotePreCom) if ok && hash != skipBlockHash { s.a.lockValue = hash s.a.lockRound = s.a.period 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 d6875bc45..f31b7efba 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement.go @@ -21,6 +21,7 @@ import ( "fmt" "math" "sync" + "sync/atomic" "time" "github.com/dexon-foundation/dexon-consensus/common" @@ -103,7 +104,7 @@ type agreementData struct { type agreement struct { state agreementState data *agreementData - aID types.Position + aID *atomic.Value notarySet map[types.NodeID]struct{} hasOutput bool lock sync.RWMutex @@ -126,6 +127,7 @@ func newAgreement( ID: ID, leader: leader, }, + aID: &atomic.Value{}, candidateBlock: make(map[common.Hash]*types.Block), fastForward: make(chan uint64, 1), authModule: authModule, @@ -138,9 +140,15 @@ func newAgreement( func (a *agreement) restart( notarySet map[types.NodeID]struct{}, aID types.Position, crs common.Hash) { - func() { + if !func() bool { a.lock.Lock() defer a.lock.Unlock() + if !isStop(aID) { + oldAID := a.agreementID() + if !isStop(oldAID) && !aID.Newer(&oldAID) { + return false + } + } a.data.lock.Lock() defer a.data.lock.Unlock() a.data.blocksLock.Lock() @@ -152,14 +160,17 @@ func (a *agreement) restart( a.data.requiredVote = len(notarySet)/3*2 + 1 a.data.leader.restart(crs) a.data.lockValue = nullBlockHash - a.data.lockRound = 1 + a.data.lockRound = 0 a.fastForward = make(chan uint64, 1) a.hasOutput = false a.state = newInitialState(a.data) a.notarySet = notarySet a.candidateBlock = make(map[common.Hash]*types.Block) - a.aID = *aID.Clone() - }() + a.aID.Store(aID) + return true + }() { + return + } if isStop(aID) { return @@ -226,14 +237,15 @@ func (a *agreement) clocks() int { // pullVotes returns if current agreement requires more votes to continue. func (a *agreement) pullVotes() bool { - return a.state.state() == statePullVote + a.data.lock.RLock() + defer a.data.lock.RUnlock() + return a.state.state() == statePullVote || + (a.state.state() == statePreCommit && (a.data.period%3) == 0) } // agreementID returns the current agreementID. func (a *agreement) agreementID() types.Position { - a.lock.RLock() - defer a.lock.RUnlock() - return a.aID + return a.aID.Load().(types.Position) } // nextState is called at the specific clock time. @@ -288,10 +300,11 @@ func (a *agreement) processVote(vote *types.Vote) error { if err := a.sanityCheck(vote); err != nil { return err } - if vote.Position != a.aID { + aID := a.agreementID() + if vote.Position != aID { // Agreement module has stopped. - if !isStop(a.aID) { - if a.aID.Newer(&vote.Position) { + if !isStop(aID) { + if aID.Newer(&vote.Position) { return nil } } @@ -335,7 +348,6 @@ func (a *agreement) processVote(vote *types.Vote) error { vote.BlockHash != a.data.lockValue { a.data.lockValue = hash a.data.lockRound = vote.Period - a.fastForward <- a.data.period + 1 return nil } // Condition 2. @@ -403,10 +415,11 @@ func (a *agreement) processBlock(block *types.Block) error { a.data.blocksLock.Lock() defer a.data.blocksLock.Unlock() - if block.Position != a.aID { + aID := a.agreementID() + if block.Position != aID { // Agreement module has stopped. - if !isStop(a.aID) { - if a.aID.Newer(&block.Position) { + if !isStop(aID) { + if aID.Newer(&block.Position) { return nil } } 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 5e5a587cb..bda2fdf62 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 @@ -39,18 +39,22 @@ var ( ) type configurationChain struct { - ID types.NodeID - recv dkgReceiver - gov Governance - dkg *dkgProtocol - logger common.Logger - dkgLock sync.RWMutex - dkgSigner map[uint64]*dkgShareSecret - gpk map[uint64]*DKGGroupPublicKey - dkgResult sync.RWMutex - tsig map[common.Hash]*tsigProtocol - tsigTouched map[common.Hash]struct{} - tsigReady *sync.Cond + ID types.NodeID + recv dkgReceiver + gov Governance + dkg *dkgProtocol + logger common.Logger + dkgLock sync.RWMutex + dkgSigner map[uint64]*dkgShareSecret + gpk map[uint64]*DKGGroupPublicKey + dkgResult sync.RWMutex + tsig map[common.Hash]*tsigProtocol + tsigTouched map[common.Hash]struct{} + tsigReady *sync.Cond + cache *NodeSetCache + dkgSet map[types.NodeID]struct{} + mpkReady bool + pendingPrvShare map[types.NodeID]*typesDKG.PrivateShare // TODO(jimmy-dexon): add timeout to pending psig. pendingPsig map[common.Hash][]*typesDKG.PartialSignature prevHash common.Hash @@ -60,6 +64,7 @@ func newConfigurationChain( ID types.NodeID, recv dkgReceiver, gov Governance, + cache *NodeSetCache, logger common.Logger) *configurationChain { return &configurationChain{ ID: ID, @@ -71,6 +76,7 @@ func newConfigurationChain( tsig: make(map[common.Hash]*tsigProtocol), tsigTouched: make(map[common.Hash]struct{}), tsigReady: sync.NewCond(&sync.Mutex{}), + cache: cache, pendingPsig: make(map[common.Hash][]*typesDKG.PartialSignature), } } @@ -78,6 +84,17 @@ func newConfigurationChain( func (cc *configurationChain) registerDKG(round uint64, threshold int) { cc.dkgLock.Lock() defer cc.dkgLock.Unlock() + if cc.dkg != nil { + cc.logger.Error("Previous DKG is not finished") + } + dkgSet, err := cc.cache.GetDKGSet(round) + if err != nil { + cc.logger.Error("Error getting DKG set from cache", "error", err) + return + } + cc.dkgSet = dkgSet + cc.pendingPrvShare = make(map[types.NodeID]*typesDKG.PrivateShare) + cc.mpkReady = false cc.dkg = newDKGProtocol( cc.ID, cc.recv, @@ -107,6 +124,13 @@ func (cc *configurationChain) runDKG(round uint64) error { // Phase 2(T = 0): Exchange DKG secret key share. cc.logger.Debug("Calling Governance.DKGMasterPublicKeys", "round", round) cc.dkg.processMasterPublicKeys(cc.gov.DKGMasterPublicKeys(round)) + cc.mpkReady = true + for _, prvShare := range cc.pendingPrvShare { + if err := cc.dkg.processPrivateShare(prvShare); err != nil { + cc.logger.Error("Failed to process private share", + "error", err) + } + } // Phase 3(T = 0~λ): Propose complaint. // Propose complaint is done in `processMasterPublicKeys`. cc.dkgLock.Unlock() @@ -286,6 +310,21 @@ func (cc *configurationChain) processPrivateShare( if cc.dkg == nil { return nil } + if _, exist := cc.dkgSet[prvShare.ProposerID]; !exist { + return ErrNotDKGParticipant + } + if !cc.mpkReady { + // TODO(jimmy-dexon): remove duplicated signature check in dkg module. + ok, err := verifyDKGPrivateShareSignature(prvShare) + if err != nil { + return err + } + if !ok { + return ErrIncorrectPrivateShareSignature + } + cc.pendingPrvShare[prvShare.ProposerID] = prvShare + return nil + } return cc.dkg.processPrivateShare(prvShare) } 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 29d4aa2c8..2eed101c7 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/consensus.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/consensus.go @@ -71,11 +71,11 @@ type consensusBAReceiver struct { } func (recv *consensusBAReceiver) ProposeVote(vote *types.Vote) { + if err := recv.agreementModule.prepareVote(vote); err != nil { + recv.consensus.logger.Error("Failed to prepare vote", "error", err) + return + } go func() { - if err := recv.agreementModule.prepareVote(vote); err != nil { - recv.consensus.logger.Error("Failed to prepare vote", "error", err) - return - } if err := recv.agreementModule.processVote(vote); err != nil { recv.consensus.logger.Error("Failed to process vote", "error", err) return @@ -336,6 +336,7 @@ func NewConsensus( ID, recv, gov, + nodeSetCache, logger) recv.cfgModule = cfgModule // Construct Consensus instance. @@ -393,6 +394,9 @@ func NewConsensus( // Run starts running DEXON Consensus. func (con *Consensus) Run(initBlock *types.Block) { + con.logger.Debug("Calling Governance.NotifyRoundHeight for genesis rounds", + "block", initBlock) + notifyGenesisRounds(initBlock, con.gov) // Setup context. con.ctx, con.ctxCancel = context.WithCancel(context.Background()) con.ccModule.init(initBlock) @@ -430,7 +434,10 @@ func (con *Consensus) Run(initBlock *types.Block) { for { <-con.tickerObj.Tick() for _, tick := range ticks { - go func(tick chan struct{}) { tick <- struct{}{} }(tick) + select { + case tick <- struct{}{}: + default: + } } } } @@ -926,9 +933,12 @@ func (con *Consensus) deliverBlock(b *types.Block) { // TODO(mission): clone types.FinalizationResult con.logger.Debug("Calling Application.BlockDelivered", "block", b) con.app.BlockDelivered(b.Hash, b.Position, b.Finalization) - if b.Position.Round+2 == con.roundToNotify { + if b.Position.Round+roundShift == con.roundToNotify { // Only the first block delivered of that round would // trigger this noitification. + con.logger.Debug("Calling Governance.NotifyRoundHeight", + "round", con.roundToNotify, + "height", b.Finalization.Height) con.gov.NotifyRoundHeight( con.roundToNotify, b.Finalization.Height) con.roundToNotify++ @@ -1002,10 +1012,9 @@ func (con *Consensus) prepareBlock(b *types.Block, if err = con.lattice.PrepareBlock(b, proposeTime); err != nil { return } - // TODO(mission): decide CRS by block's round, which could be determined by - // block's info (ex. position, timestamp). con.logger.Debug("Calling Governance.CRS", "round", 0) - if err = con.authModule.SignCRS(b, con.gov.CRS(0)); err != nil { + if err = + con.authModule.SignCRS(b, con.gov.CRS(b.Position.Round)); err != nil { return } return diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/constant.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/constant.go new file mode 100644 index 000000000..9a61c0abb --- /dev/null +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/constant.go @@ -0,0 +1,25 @@ +// Copyright 2018 The dexon-consensus Authors +// This file is part of the dexon-consensus library. +// +// The dexon-consensus library is free software: you can redistribute it +// and/or modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation, either version 3 of the License, +// or (at your option) any later version. +// +// The dexon-consensus library is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser +// General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the dexon-consensus library. If not, see +// . + +package core + +// round shift refers to the difference between block's round and config round +// derived from its state. +// +// For example, when round shift is 2, a block in round 0 should derive config +// for round 2. +const roundShift uint64 = 2 diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/crypto.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/crypto.go index 2b7f7a7fc..914ca0865 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/crypto.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/crypto.go @@ -121,11 +121,15 @@ func hashPosition(position types.Position) common.Hash { binaryChainID := make([]byte, 4) binary.LittleEndian.PutUint32(binaryChainID, position.ChainID) + binaryRound := make([]byte, 8) + binary.LittleEndian.PutUint64(binaryRound, position.Round) + binaryHeight := make([]byte, 8) binary.LittleEndian.PutUint64(binaryHeight, position.Height) return crypto.Keccak256Hash( binaryChainID, + binaryRound, binaryHeight, ) } diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/lattice-data.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/lattice-data.go index ca246612d..3f8c42bb5 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/lattice-data.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/lattice-data.go @@ -488,6 +488,9 @@ func (data *latticeData) prepareEmptyBlock(b *types.Block) { } b.Position.Height = chainTip.Position.Height + 1 b.Timestamp = chainTip.Timestamp.Add(chainTipConfig.minBlockTimeInterval) + b.Witness.Height = chainTip.Witness.Height + b.Witness.Data = make([]byte, len(chainTip.Witness.Data)) + copy(b.Witness.Data, chainTip.Witness.Data) acks = append(acks, chainTip.Hash) } b.Acks = common.NewSortedHashes(acks) 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 bde07d518..27416d8c9 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 @@ -209,8 +209,7 @@ func (b *Block) DecodeRLP(s *rlp.Stream) error { } func (b *Block) String() string { - return fmt.Sprintf("Block(%v:%d:%d)", b.Hash.String()[:6], - b.Position.ChainID, b.Position.Height) + return fmt.Sprintf("Block(%v:%s)", b.Hash.String()[:6], &b.Position) } // Clone returns a deep copy of a block. diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/types/position.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/position.go index 404f3035e..1fc7e6bf4 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/types/position.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/position.go @@ -29,7 +29,7 @@ type Position struct { } func (pos *Position) String() string { - return fmt.Sprintf("pos[%d:%d:%d]", pos.Round, pos.ChainID, pos.Height) + return fmt.Sprintf("[%d:%d:%d]", pos.Round, pos.ChainID, pos.Height) } // Equal checks if two positions are equal, it panics when their chainIDs diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/types/vote.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/vote.go index 32fb8982d..5b99f2253 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/types/vote.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/vote.go @@ -47,9 +47,8 @@ type Vote struct { } func (v *Vote) String() string { - return fmt.Sprintf("Vote[%s:%d:%d](%d:%d):%s", - v.ProposerID.String()[:6], v.Position.ChainID, v.Position.Height, - v.Period, v.Type, v.BlockHash.String()[:6]) + return fmt.Sprintf("Vote[%s:%s](%d:%d):%s", v.ProposerID.String()[:6], + &v.Position, v.Period, v.Type, v.BlockHash.String()[:6]) } // Clone returns a deep copy of a vote. diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/utils.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils.go index 6b9ce634f..9159be858 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/utils.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils.go @@ -159,3 +159,14 @@ func DiffUint64(a, b uint64) uint64 { } return b - a } + +// notifyGenesisRounds notifies governance to generate configs based on genesis +// state. +func notifyGenesisRounds(initBlock *types.Block, gov Governance) { + if initBlock.Position.Round != 0 || !initBlock.IsGenesis() { + return + } + for round := uint64(0); round < roundShift; round++ { + gov.NotifyRoundHeight(round, 0) + } +} -- cgit