From 5d30e58203e27153c9b7a0dd23c349035e175f13 Mon Sep 17 00:00:00 2001 From: Jimmy Hu Date: Tue, 12 Mar 2019 12:23:16 +0800 Subject: vendor: sync to latest core and fix conflict --- .../dexon-consensus/core/blockchain.go | 30 ++-- .../dexon-consensus/core/configuration-chain.go | 54 ++++--- .../dexon-consensus/core/consensus.go | 5 +- .../dexon-consensus/core/dkg-tsig-protocol.go | 130 ++--------------- .../dexon-consensus/core/interfaces.go | 2 +- .../dexon-consensus/core/syncer/consensus.go | 44 +++--- .../dexon-consensus/core/types/dkg/dkg.go | 161 +++++++++++++++++++++ .../dexon-foundation/dexon-consensus/core/utils.go | 4 - .../dexon-consensus/core/utils/utils.go | 5 + 9 files changed, 250 insertions(+), 185 deletions(-) (limited to 'vendor/github.com/dexon-foundation') 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 aacb65de2..b6c8b1da5 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/blockchain.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/blockchain.go @@ -311,21 +311,23 @@ func (bc *blockChain) addBlock(b *types.Block) error { return nil } +func (bc *blockChain) shouldAddRandomness(r *types.BlockRandomnessResult) bool { + bc.lock.RLock() + defer bc.lock.RUnlock() + if bc.lastDelivered != nil && + bc.lastDelivered.Position.Newer(r.Position) { + return false + } + _, exists := bc.pendingRandomnesses[r.Position] + if exists { + return false + } + b := bc.findPendingBlock(r.Position) + return b == nil || len(b.Finalization.Randomness) == 0 +} + func (bc *blockChain) addRandomness(r *types.BlockRandomnessResult) error { - if func() bool { - bc.lock.RLock() - defer bc.lock.RUnlock() - if bc.lastDelivered != nil && - bc.lastDelivered.Position.Newer(r.Position) { - return true - } - _, exists := bc.pendingRandomnesses[r.Position] - if exists { - return true - } - b := bc.findPendingBlock(r.Position) - return b != nil && len(b.Finalization.Randomness) > 0 - }() { + if !bc.shouldAddRandomness(r) { return nil } ok, err := bc.verifyRandomness(r.BlockHash, r.Position.Round, r.Randomness) 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 ad4d7e633..9e8df6bd1 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 @@ -48,7 +48,7 @@ type configurationChain struct { logger common.Logger dkgLock sync.RWMutex dkgSigner map[uint64]*dkgShareSecret - gpk map[uint64]*DKGGroupPublicKey + npks map[uint64]*typesDKG.NodePublicKeys dkgResult sync.RWMutex tsig map[common.Hash]*tsigProtocol tsigTouched map[common.Hash]struct{} @@ -76,7 +76,7 @@ func newConfigurationChain( gov: gov, logger: logger, dkgSigner: make(map[uint64]*dkgShareSecret), - gpk: make(map[uint64]*DKGGroupPublicKey), + npks: make(map[uint64]*typesDKG.NodePublicKeys), tsig: make(map[common.Hash]*tsigProtocol), tsigTouched: make(map[common.Hash]struct{}), tsigReady: sync.NewCond(&sync.Mutex{}), @@ -221,7 +221,7 @@ func (cc *configurationChain) runDKG(round uint64) error { } cc.logger.Debug("Calling Governance.DKGMasterPublicKeys", "round", round) cc.logger.Debug("Calling Governance.DKGComplaints", "round", round) - gpk, err := NewDKGGroupPublicKey(round, + npks, err := typesDKG.NewNodePublicKeys(round, cc.gov.DKGMasterPublicKeys(round), cc.gov.DKGComplaints(round), cc.dkg.threshold) @@ -229,19 +229,19 @@ func (cc *configurationChain) runDKG(round uint64) error { return err } qualifies := "" - for nID := range gpk.qualifyNodeIDs { + for nID := range npks.QualifyNodeIDs { qualifies += fmt.Sprintf("%s ", nID.String()[:6]) } cc.logger.Info("Qualify Nodes", "nodeID", cc.ID, "round", round, - "count", len(gpk.qualifyIDs), + "count", len(npks.QualifyIDs), "qualifies", qualifies) - if _, exist := gpk.qualifyNodeIDs[cc.ID]; !exist { + if _, exist := npks.QualifyNodeIDs[cc.ID]; !exist { cc.logger.Warn("Self is not in Qualify Nodes") return nil } - signer, err := cc.dkg.recoverShareSecret(gpk.qualifyIDs) + signer, err := cc.dkg.recoverShareSecret(npks.QualifyIDs) if err != nil { return err } @@ -252,7 +252,7 @@ func (cc *configurationChain) runDKG(round uint64) error { cc.dkgResult.Lock() defer cc.dkgResult.Unlock() cc.dkgSigner[round] = signer - cc.gpk[round] = gpk + cc.npks[round] = npks return nil } @@ -265,46 +265,44 @@ func (cc *configurationChain) isDKGFinal(round uint64) bool { } func (cc *configurationChain) getDKGInfo( - round uint64) (*DKGGroupPublicKey, *dkgShareSecret, error) { - getFromCache := func() (*DKGGroupPublicKey, *dkgShareSecret) { + round uint64) (*typesDKG.NodePublicKeys, *dkgShareSecret, error) { + getFromCache := func() (*typesDKG.NodePublicKeys, *dkgShareSecret) { cc.dkgResult.RLock() defer cc.dkgResult.RUnlock() - gpk := cc.gpk[round] + npks := cc.npks[round] signer := cc.dkgSigner[round] - return gpk, signer + return npks, signer } - gpk, signer := getFromCache() - if gpk == nil || signer == nil { + npks, signer := getFromCache() + if npks == nil || signer == nil { if err := cc.recoverDKGInfo(round); err != nil { return nil, nil, err } - gpk, signer = getFromCache() + npks, signer = getFromCache() } - if gpk == nil || signer == nil { + if npks == nil || signer == nil { return nil, nil, ErrDKGNotReady } - return gpk, signer, nil + return npks, signer, nil } func (cc *configurationChain) recoverDKGInfo(round uint64) error { cc.dkgResult.Lock() defer cc.dkgResult.Unlock() _, signerExists := cc.dkgSigner[round] - _, gpkExists := cc.gpk[round] - if signerExists && gpkExists { + _, npksExists := cc.npks[round] + if signerExists && npksExists { return nil } if !cc.gov.IsDKGFinal(round) { return ErrDKGNotReady } - - threshold := getDKGThreshold( - utils.GetConfigWithPanic(cc.gov, round, cc.logger)) // Restore group public key. - gpk, err := NewDKGGroupPublicKey(round, + npks, err := typesDKG.NewNodePublicKeys(round, cc.gov.DKGMasterPublicKeys(round), cc.gov.DKGComplaints(round), - threshold) + utils.GetDKGThreshold( + utils.GetConfigWithPanic(cc.gov, round, cc.logger))) if err != nil { return err } @@ -313,7 +311,7 @@ func (cc *configurationChain) recoverDKGInfo(round uint64) error { if err != nil { return err } - cc.gpk[round] = gpk + cc.npks[round] = npks cc.dkgSigner[round] = &dkgShareSecret{ privateKey: &prvKey, } @@ -351,8 +349,8 @@ func (cc *configurationChain) untouchTSigHash(hash common.Hash) { func (cc *configurationChain) runTSig( round uint64, hash common.Hash) ( crypto.Signature, error) { - gpk, _, _ := cc.getDKGInfo(round) - if gpk == nil { + npks, _, _ := cc.getDKGInfo(round) + if npks == nil { return crypto.Signature{}, ErrDKGNotReady } cc.tsigReady.L.Lock() @@ -360,7 +358,7 @@ func (cc *configurationChain) runTSig( if _, exist := cc.tsig[hash]; exist { return crypto.Signature{}, ErrTSigAlreadyRunning } - cc.tsig[hash] = newTSigProtocol(gpk, hash) + cc.tsig[hash] = newTSigProtocol(npks, hash) pendingPsig := cc.pendingPsig[hash] delete(cc.pendingPsig, hash) go func() { 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 050bfe7e5..ccb332684 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/consensus.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/consensus.go @@ -814,7 +814,7 @@ func (con *Consensus) initialRound( return } con.logger.Info("Selected as DKG set", "round", nextRound) - con.cfgModule.registerDKG(nextRound, getDKGThreshold(config)) + con.cfgModule.registerDKG(nextRound, utils.GetDKGThreshold(config)) con.event.RegisterHeight(startHeight+config.RoundLength*2/3, func(uint64) { func() { @@ -1070,6 +1070,9 @@ func (con *Consensus) ProcessBlockRandomnessResult( if rand.Position.Round == 0 { return nil } + if !con.bcModule.shouldAddRandomness(rand) { + return nil + } if err := con.bcModule.addRandomness(rand); err != nil { return err } 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 45fe822e1..6c812db73 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 @@ -37,10 +37,6 @@ var ( "not a qualified DKG participant") ErrIDShareNotFound = fmt.Errorf( "private share not found for specific ID") - ErrNotReachThreshold = fmt.Errorf( - "threshold not reach") - ErrInvalidThreshold = fmt.Errorf( - "invalid threshold") ErrIncorrectPrivateShareSignature = fmt.Errorf( "incorrect private share signature") ErrMismatchPartialSignatureHash = fmt.Errorf( @@ -102,17 +98,6 @@ type dkgShareSecret struct { privateKey *dkg.PrivateKey } -// DKGGroupPublicKey is the result of DKG protocol. -type DKGGroupPublicKey struct { - round uint64 - qualifyIDs dkg.IDs - qualifyNodeIDs map[types.NodeID]struct{} - idMap map[types.NodeID]dkg.ID - publicKeys map[types.NodeID]*dkg.PublicKey - groupPublicKey *dkg.PublicKey - threshold int -} - // TSigVerifier is the interface verifying threshold signature. type TSigVerifier interface { VerifySignature(hash common.Hash, sig crypto.Signature) bool @@ -144,7 +129,7 @@ type TSigVerifierCache struct { } type tsigProtocol struct { - groupPublicKey *DKGGroupPublicKey + nodePublicKeys *typesDKG.NodePublicKeys hash common.Hash sigs map[dkg.ID]dkg.PartialSignature threshold int @@ -385,7 +370,7 @@ func (d *dkgProtocol) proposeFinalize() { func (d *dkgProtocol) recoverShareSecret(qualifyIDs dkg.IDs) ( *dkgShareSecret, error) { if len(qualifyIDs) < d.threshold { - return nil, ErrNotReachThreshold + return nil, typesDKG.ErrNotReachThreshold } prvKey, err := d.prvShares.RecoverPrivateKey(qualifyIDs) if err != nil { @@ -402,96 +387,7 @@ func (ss *dkgShareSecret) sign(hash common.Hash) dkg.PartialSignature { return dkg.PartialSignature(sig) } -// NewDKGGroupPublicKey creats a DKGGroupPublicKey instance. -func NewDKGGroupPublicKey( - round uint64, - mpks []*typesDKG.MasterPublicKey, complaints []*typesDKG.Complaint, - threshold int) ( - *DKGGroupPublicKey, error) { - - if len(mpks) < threshold { - return nil, ErrInvalidThreshold - } - - // Calculate qualify members. - disqualifyIDs := map[types.NodeID]struct{}{} - complaintsByID := map[types.NodeID]map[types.NodeID]struct{}{} - for _, complaint := range complaints { - if complaint.IsNack() { - if _, exist := complaintsByID[complaint.PrivateShare.ProposerID]; !exist { - complaintsByID[complaint.PrivateShare.ProposerID] = - make(map[types.NodeID]struct{}) - } - complaintsByID[complaint.PrivateShare.ProposerID][complaint.ProposerID] = - struct{}{} - } else { - disqualifyIDs[complaint.PrivateShare.ProposerID] = struct{}{} - } - } - for nID, complaints := range complaintsByID { - if len(complaints) > threshold { - disqualifyIDs[nID] = struct{}{} - } - } - qualifyIDs := make(dkg.IDs, 0, len(mpks)-len(disqualifyIDs)) - if cap(qualifyIDs) < threshold { - return nil, ErrNotReachThreshold - } - qualifyNodeIDs := make(map[types.NodeID]struct{}) - mpkMap := make(map[dkg.ID]*typesDKG.MasterPublicKey, cap(qualifyIDs)) - idMap := make(map[types.NodeID]dkg.ID) - for _, mpk := range mpks { - if _, exist := disqualifyIDs[mpk.ProposerID]; exist { - continue - } - mpkMap[mpk.DKGID] = mpk - idMap[mpk.ProposerID] = mpk.DKGID - qualifyIDs = append(qualifyIDs, mpk.DKGID) - qualifyNodeIDs[mpk.ProposerID] = struct{}{} - } - // Recover qualify members' public key. - pubKeys := make(map[types.NodeID]*dkg.PublicKey, len(qualifyIDs)) - for _, recvID := range qualifyIDs { - pubShares := dkg.NewEmptyPublicKeyShares() - for _, id := range qualifyIDs { - pubShare, err := mpkMap[id].PublicKeyShares.Share(recvID) - if err != nil { - return nil, err - } - if err := pubShares.AddShare(id, pubShare); err != nil { - return nil, err - } - } - pubKey, err := pubShares.RecoverPublicKey(qualifyIDs) - if err != nil { - return nil, err - } - pubKeys[mpkMap[recvID].ProposerID] = pubKey - } - // Recover Group Public Key. - pubShares := make([]*dkg.PublicKeyShares, 0, len(qualifyIDs)) - for _, id := range qualifyIDs { - pubShares = append(pubShares, &mpkMap[id].PublicKeyShares) - } - groupPK := dkg.RecoverGroupPublicKey(pubShares) - return &DKGGroupPublicKey{ - round: round, - qualifyIDs: qualifyIDs, - qualifyNodeIDs: qualifyNodeIDs, - idMap: idMap, - publicKeys: pubKeys, - threshold: threshold, - groupPublicKey: groupPK, - }, nil -} - -// VerifySignature verifies if the signature is correct. -func (gpk *DKGGroupPublicKey) VerifySignature( - hash common.Hash, sig crypto.Signature) bool { - return gpk.groupPublicKey.VerifySignature(hash, sig) -} - -// NewTSigVerifierCache creats a DKGGroupPublicKey instance. +// NewTSigVerifierCache creats a TSigVerifierCache instance. func NewTSigVerifierCache( intf TSigVerifierCacheInterface, cacheSize int) *TSigVerifierCache { return &TSigVerifierCache{ @@ -528,10 +424,10 @@ func (tc *TSigVerifierCache) Update(round uint64) (bool, error) { if !tc.intf.IsDKGFinal(round) { return false, nil } - gpk, err := NewDKGGroupPublicKey(round, + gpk, err := typesDKG.NewGroupPublicKey(round, tc.intf.DKGMasterPublicKeys(round), tc.intf.DKGComplaints(round), - int(utils.GetConfigWithPanic(tc.intf, round, nil).DKGSetSize/3)+1) + utils.GetDKGThreshold(utils.GetConfigWithPanic(tc.intf, round, nil))) if err != nil { return false, err } @@ -568,17 +464,17 @@ func (tc *TSigVerifierCache) Get(round uint64) (TSigVerifier, bool) { } func newTSigProtocol( - gpk *DKGGroupPublicKey, + npks *typesDKG.NodePublicKeys, hash common.Hash) *tsigProtocol { return &tsigProtocol{ - groupPublicKey: gpk, + nodePublicKeys: npks, hash: hash, - sigs: make(map[dkg.ID]dkg.PartialSignature, gpk.threshold+1), + sigs: make(map[dkg.ID]dkg.PartialSignature, npks.Threshold+1), } } func (tsig *tsigProtocol) sanityCheck(psig *typesDKG.PartialSignature) error { - _, exist := tsig.groupPublicKey.publicKeys[psig.ProposerID] + _, exist := tsig.nodePublicKeys.PublicKeys[psig.ProposerID] if !exist { return ErrNotQualifyDKGParticipant } @@ -597,17 +493,17 @@ func (tsig *tsigProtocol) sanityCheck(psig *typesDKG.PartialSignature) error { func (tsig *tsigProtocol) processPartialSignature( psig *typesDKG.PartialSignature) error { - if psig.Round != tsig.groupPublicKey.round { + if psig.Round != tsig.nodePublicKeys.Round { return nil } - id, exist := tsig.groupPublicKey.idMap[psig.ProposerID] + id, exist := tsig.nodePublicKeys.IDMap[psig.ProposerID] if !exist { return ErrNotQualifyDKGParticipant } if err := tsig.sanityCheck(psig); err != nil { return err } - pubKey := tsig.groupPublicKey.publicKeys[psig.ProposerID] + pubKey := tsig.nodePublicKeys.PublicKeys[psig.ProposerID] if !pubKey.VerifySignature( tsig.hash, crypto.Signature(psig.PartialSignature)) { return ErrIncorrectPartialSignature @@ -617,7 +513,7 @@ func (tsig *tsigProtocol) processPartialSignature( } func (tsig *tsigProtocol) signature() (crypto.Signature, error) { - if len(tsig.sigs) < tsig.groupPublicKey.threshold { + if len(tsig.sigs) < tsig.nodePublicKeys.Threshold { return crypto.Signature{}, ErrNotEnoughtPartialSignatures } ids := make(dkg.IDs, 0, len(tsig.sigs)) diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/interfaces.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/interfaces.go index b7e000ae6..45a1fc7d5 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/interfaces.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/interfaces.go @@ -129,7 +129,7 @@ type Governance interface { // AddDKGMPKReady adds a DKG ready message. AddDKGMPKReady(round uint64, ready *typesDKG.MPKReady) - // IsDKGFinal checks if DKG is ready. + // IsDKGMPKReady checks if DKG's master public key preparation is ready. IsDKGMPKReady(round uint64) bool // AddDKGFinalize adds a DKG finalize message. diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/syncer/consensus.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/syncer/consensus.go index 305339687..25911ce5f 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/syncer/consensus.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/syncer/consensus.go @@ -250,11 +250,6 @@ func (con *Consensus) SyncBlocks( // syncing is done. if con.checkIfSynced(blocks) { con.stopBuffering() - con.dummyCancel, con.dummyFinished = utils.LaunchDummyReceiver( - context.Background(), con.network.ReceiveChan(), - func(msg interface{}) { - con.dummyMsgBuffer = append(con.dummyMsgBuffer, msg) - }) con.syncedLastBlock = blocks[len(blocks)-1] synced = true } @@ -302,24 +297,38 @@ func (con *Consensus) GetSyncedConsensus() (*core.Consensus, error) { // This method is mainly for caller to stop the syncer before synced, the syncer // would call this method automatically after being synced. func (con *Consensus) stopBuffering() { - if func() bool { + if func() (notBuffering bool) { con.lock.RLock() defer con.lock.RUnlock() - return !con.duringBuffering + notBuffering = !con.duringBuffering + return }() { return } - con.lock.Lock() - defer con.lock.Unlock() - if !con.duringBuffering { + if func() (alreadyCanceled bool) { + con.lock.Lock() + defer con.lock.Unlock() + if !con.duringBuffering { + alreadyCanceled = true + return + } + con.duringBuffering = false + con.logger.Trace("syncer is about to stop") + // Stop network and CRS routines, wait until they are all stoped. + con.ctxCancel() + return + }() { return } - con.duringBuffering = false - con.logger.Trace("syncer is about to stop") - // Stop network and CRS routines, wait until they are all stoped. - con.ctxCancel() con.logger.Trace("stop syncer modules") con.moduleWaitGroup.Wait() + // Since there is no one waiting for the receive channel of fullnode, we + // need to launch a dummy receiver right away. + con.dummyCancel, con.dummyFinished = utils.LaunchDummyReceiver( + context.Background(), con.network.ReceiveChan(), + func(msg interface{}) { + con.dummyMsgBuffer = append(con.dummyMsgBuffer, msg) + }) // Stop agreements. con.logger.Trace("stop syncer agreement modules") con.stopAgreement() @@ -506,11 +515,6 @@ func (con *Consensus) startCRSMonitor() { con.latestCRSRound = round }() for func() bool { - con.lock.RLock() - defer con.lock.RUnlock() - if !con.duringBuffering { - return false - } select { case <-con.ctx.Done(): return false @@ -552,9 +556,9 @@ func (con *Consensus) startCRSMonitor() { func (con *Consensus) stopAgreement() { if con.agreementModule.inputChan != nil { close(con.agreementModule.inputChan) - con.agreementModule.inputChan = nil } con.agreementWaitGroup.Wait() + con.agreementModule.inputChan = nil close(con.receiveChan) close(con.pullChan) } 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 db58168a2..1052ccb9f 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 @@ -31,6 +31,12 @@ import ( "github.com/dexon-foundation/dexon-consensus/core/types" ) +// Errors for typesDKG package. +var ( + ErrNotReachThreshold = fmt.Errorf("threshold not reach") + ErrInvalidThreshold = fmt.Errorf("invalid threshold") +) + // NewID creates a DKGID from NodeID. func NewID(ID types.NodeID) cryptoDKG.ID { return cryptoDKG.NewID(ID.Hash[:]) @@ -276,3 +282,158 @@ func (final *Finalize) Equal(other *Finalize) bool { func (c *Complaint) IsNack() bool { return len(c.PrivateShare.Signature.Signature) == 0 } + +// GroupPublicKey is the result of DKG protocol. +type GroupPublicKey struct { + Round uint64 + QualifyIDs cryptoDKG.IDs + QualifyNodeIDs map[types.NodeID]struct{} + IDMap map[types.NodeID]cryptoDKG.ID + GroupPublicKey *cryptoDKG.PublicKey + Threshold int +} + +// VerifySignature verifies if the signature is correct. +func (gpk *GroupPublicKey) VerifySignature( + hash common.Hash, sig crypto.Signature) bool { + return gpk.GroupPublicKey.VerifySignature(hash, sig) +} + +func calcQualifyNodes( + mpks []*MasterPublicKey, complaints []*Complaint, threshold int) ( + qualifyIDs cryptoDKG.IDs, qualifyNodeIDs map[types.NodeID]struct{}, err error) { + if len(mpks) < threshold { + err = ErrInvalidThreshold + return + } + + // Calculate qualify members. + disqualifyIDs := map[types.NodeID]struct{}{} + complaintsByID := map[types.NodeID]map[types.NodeID]struct{}{} + for _, complaint := range complaints { + if complaint.IsNack() { + if _, exist := complaintsByID[complaint.PrivateShare.ProposerID]; !exist { + complaintsByID[complaint.PrivateShare.ProposerID] = + make(map[types.NodeID]struct{}) + } + complaintsByID[complaint.PrivateShare.ProposerID][complaint.ProposerID] = + struct{}{} + } else { + disqualifyIDs[complaint.PrivateShare.ProposerID] = struct{}{} + } + } + for nID, complaints := range complaintsByID { + if len(complaints) > threshold { + disqualifyIDs[nID] = struct{}{} + } + } + qualifyIDs = make(cryptoDKG.IDs, 0, len(mpks)-len(disqualifyIDs)) + if cap(qualifyIDs) < threshold { + err = ErrNotReachThreshold + return + } + qualifyNodeIDs = make(map[types.NodeID]struct{}) + for _, mpk := range mpks { + if _, exist := disqualifyIDs[mpk.ProposerID]; exist { + continue + } + qualifyIDs = append(qualifyIDs, mpk.DKGID) + qualifyNodeIDs[mpk.ProposerID] = struct{}{} + } + return +} + +// NewGroupPublicKey creats a GroupPublicKey instance. +func NewGroupPublicKey( + round uint64, + mpks []*MasterPublicKey, complaints []*Complaint, + threshold int) ( + *GroupPublicKey, error) { + qualifyIDs, qualifyNodeIDs, err := + calcQualifyNodes(mpks, complaints, threshold) + if err != nil { + return nil, err + } + mpkMap := make(map[cryptoDKG.ID]*MasterPublicKey, cap(qualifyIDs)) + idMap := make(map[types.NodeID]cryptoDKG.ID) + for _, mpk := range mpks { + if _, exist := qualifyNodeIDs[mpk.ProposerID]; !exist { + continue + } + mpkMap[mpk.DKGID] = mpk + idMap[mpk.ProposerID] = mpk.DKGID + } + // Recover Group Public Key. + pubShares := make([]*cryptoDKG.PublicKeyShares, 0, len(qualifyIDs)) + for _, id := range qualifyIDs { + pubShares = append(pubShares, &mpkMap[id].PublicKeyShares) + } + groupPK := cryptoDKG.RecoverGroupPublicKey(pubShares) + return &GroupPublicKey{ + Round: round, + QualifyIDs: qualifyIDs, + QualifyNodeIDs: qualifyNodeIDs, + IDMap: idMap, + Threshold: threshold, + GroupPublicKey: groupPK, + }, nil +} + +// NodePublicKeys is the result of DKG protocol. +type NodePublicKeys struct { + Round uint64 + QualifyIDs cryptoDKG.IDs + QualifyNodeIDs map[types.NodeID]struct{} + IDMap map[types.NodeID]cryptoDKG.ID + PublicKeys map[types.NodeID]*cryptoDKG.PublicKey + Threshold int +} + +// NewNodePublicKeys creats a NodePublicKeys instance. +func NewNodePublicKeys( + round uint64, + mpks []*MasterPublicKey, complaints []*Complaint, + threshold int) ( + *NodePublicKeys, error) { + qualifyIDs, qualifyNodeIDs, err := + calcQualifyNodes(mpks, complaints, threshold) + if err != nil { + return nil, err + } + mpkMap := make(map[cryptoDKG.ID]*MasterPublicKey, cap(qualifyIDs)) + idMap := make(map[types.NodeID]cryptoDKG.ID) + for _, mpk := range mpks { + if _, exist := qualifyNodeIDs[mpk.ProposerID]; !exist { + continue + } + mpkMap[mpk.DKGID] = mpk + idMap[mpk.ProposerID] = mpk.DKGID + } + // Recover qualify members' public key. + pubKeys := make(map[types.NodeID]*cryptoDKG.PublicKey, len(qualifyIDs)) + for _, recvID := range qualifyIDs { + pubShares := cryptoDKG.NewEmptyPublicKeyShares() + for _, id := range qualifyIDs { + pubShare, err := mpkMap[id].PublicKeyShares.Share(recvID) + if err != nil { + return nil, err + } + if err := pubShares.AddShare(id, pubShare); err != nil { + return nil, err + } + } + pubKey, err := pubShares.RecoverPublicKey(qualifyIDs) + if err != nil { + return nil, err + } + pubKeys[mpkMap[recvID].ProposerID] = pubKey + } + return &NodePublicKeys{ + Round: round, + QualifyIDs: qualifyIDs, + QualifyNodeIDs: qualifyNodeIDs, + IDMap: idMap, + PublicKeys: pubKeys, + Threshold: threshold, + }, nil +} 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 46aa77a6b..f7dee757f 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/utils.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils.go @@ -229,10 +229,6 @@ func isTravisCI() bool { return isCI() && os.Getenv("TRAVIS") == "true" } -func getDKGThreshold(config *types.Config) int { - return int(config.DKGSetSize/3) + 1 -} - // checkWithCancel is a helper to perform periodic checking with cancel. func checkWithCancel(parentCtx context.Context, interval time.Duration, checker func() bool) (ret bool) { 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 220240c5a..b8bd95ec4 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 @@ -133,3 +133,8 @@ func LaunchDummyReceiver( }() return dummyCancel, finishedChan } + +// GetDKGThreshold return expected threshold for given DKG set size. +func GetDKGThreshold(config *types.Config) int { + return int(config.DKGSetSize/3) + 1 +} -- cgit v1.2.3