diff options
Diffstat (limited to 'vendor/github.com/dexon-foundation/dexon-consensus-core/core/configuration-chain.go')
-rw-r--r-- | vendor/github.com/dexon-foundation/dexon-consensus-core/core/configuration-chain.go | 312 |
1 files changed, 0 insertions, 312 deletions
diff --git a/vendor/github.com/dexon-foundation/dexon-consensus-core/core/configuration-chain.go b/vendor/github.com/dexon-foundation/dexon-consensus-core/core/configuration-chain.go deleted file mode 100644 index 5e5a587cb..000000000 --- a/vendor/github.com/dexon-foundation/dexon-consensus-core/core/configuration-chain.go +++ /dev/null @@ -1,312 +0,0 @@ -// 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 -// <http://www.gnu.org/licenses/>. - -package core - -import ( - "fmt" - "sync" - "time" - - "github.com/dexon-foundation/dexon-consensus/common" - "github.com/dexon-foundation/dexon-consensus/core/crypto" - "github.com/dexon-foundation/dexon-consensus/core/types" - typesDKG "github.com/dexon-foundation/dexon-consensus/core/types/dkg" -) - -// Errors for configuration chain.. -var ( - ErrDKGNotRegistered = fmt.Errorf( - "not yet registered in DKG protocol") - ErrTSigAlreadyRunning = fmt.Errorf( - "tsig is already running") - ErrDKGNotReady = fmt.Errorf( - "DKG is not ready") -) - -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 - // TODO(jimmy-dexon): add timeout to pending psig. - pendingPsig map[common.Hash][]*typesDKG.PartialSignature - prevHash common.Hash -} - -func newConfigurationChain( - ID types.NodeID, - recv dkgReceiver, - gov Governance, - logger common.Logger) *configurationChain { - return &configurationChain{ - ID: ID, - recv: recv, - gov: gov, - logger: logger, - dkgSigner: make(map[uint64]*dkgShareSecret), - gpk: make(map[uint64]*DKGGroupPublicKey), - tsig: make(map[common.Hash]*tsigProtocol), - tsigTouched: make(map[common.Hash]struct{}), - tsigReady: sync.NewCond(&sync.Mutex{}), - pendingPsig: make(map[common.Hash][]*typesDKG.PartialSignature), - } -} - -func (cc *configurationChain) registerDKG(round uint64, threshold int) { - cc.dkgLock.Lock() - defer cc.dkgLock.Unlock() - cc.dkg = newDKGProtocol( - cc.ID, - cc.recv, - round, - threshold) -} - -func (cc *configurationChain) runDKG(round uint64) error { - cc.dkgLock.Lock() - defer cc.dkgLock.Unlock() - if cc.dkg == nil || cc.dkg.round != round { - return ErrDKGNotRegistered - } - if func() bool { - cc.dkgResult.RLock() - defer cc.dkgResult.RUnlock() - _, exist := cc.gpk[round] - return exist - }() { - return nil - } - - ticker := newTicker(cc.gov, round, TickerDKG) - cc.dkgLock.Unlock() - <-ticker.Tick() - cc.dkgLock.Lock() - // Phase 2(T = 0): Exchange DKG secret key share. - cc.logger.Debug("Calling Governance.DKGMasterPublicKeys", "round", round) - cc.dkg.processMasterPublicKeys(cc.gov.DKGMasterPublicKeys(round)) - // Phase 3(T = 0~λ): Propose complaint. - // Propose complaint is done in `processMasterPublicKeys`. - cc.dkgLock.Unlock() - <-ticker.Tick() - cc.dkgLock.Lock() - // Phase 4(T = λ): Propose nack complaints. - cc.dkg.proposeNackComplaints() - cc.dkgLock.Unlock() - <-ticker.Tick() - cc.dkgLock.Lock() - // Phase 5(T = 2λ): Propose Anti nack complaint. - cc.logger.Debug("Calling Governance.DKGComplaints", "round", round) - cc.dkg.processNackComplaints(cc.gov.DKGComplaints(round)) - cc.dkgLock.Unlock() - <-ticker.Tick() - cc.dkgLock.Lock() - // Phase 6(T = 3λ): Rebroadcast anti nack complaint. - // Rebroadcast is done in `processPrivateShare`. - cc.dkgLock.Unlock() - <-ticker.Tick() - cc.dkgLock.Lock() - // Phase 7(T = 4λ): Enforce complaints and nack complaints. - cc.logger.Debug("Calling Governance.DKGComplaints", "round", round) - cc.dkg.enforceNackComplaints(cc.gov.DKGComplaints(round)) - // Enforce complaint is done in `processPrivateShare`. - // Phase 8(T = 5λ): DKG finalize. - cc.dkgLock.Unlock() - <-ticker.Tick() - cc.dkgLock.Lock() - cc.dkg.proposeFinalize() - // Phase 9(T = 6λ): DKG is ready. - cc.dkgLock.Unlock() - <-ticker.Tick() - cc.dkgLock.Lock() - // Normally, IsDKGFinal would return true here. Use this for in case of - // unexpected network fluctuation and ensure the robustness of DKG protocol. - cc.logger.Debug("Calling Governance.IsDKGFinal", "round", round) - for !cc.gov.IsDKGFinal(round) { - cc.logger.Info("DKG is not ready yet. Try again later...", - "nodeID", cc.ID) - time.Sleep(500 * time.Millisecond) - } - cc.logger.Debug("Calling Governance.DKGMasterPublicKeys", "round", round) - cc.logger.Debug("Calling Governance.DKGComplaints", "round", round) - gpk, err := NewDKGGroupPublicKey(round, - cc.gov.DKGMasterPublicKeys(round), - cc.gov.DKGComplaints(round), - cc.dkg.threshold) - if err != nil { - return err - } - signer, err := cc.dkg.recoverShareSecret(gpk.qualifyIDs) - if err != nil { - return err - } - qualifies := "" - for nID := range gpk.qualifyNodeIDs { - qualifies += fmt.Sprintf("%s ", nID.String()[:6]) - } - cc.logger.Info("Qualify Nodes", - "nodeID", cc.ID, - "round", round, - "count", len(gpk.qualifyIDs), - "qualifies", qualifies) - cc.dkgResult.Lock() - defer cc.dkgResult.Unlock() - cc.dkgSigner[round] = signer - cc.gpk[round] = gpk - return nil -} - -func (cc *configurationChain) preparePartialSignature( - round uint64, hash common.Hash) (*typesDKG.PartialSignature, error) { - signer, exist := func() (*dkgShareSecret, bool) { - cc.dkgResult.RLock() - defer cc.dkgResult.RUnlock() - signer, exist := cc.dkgSigner[round] - return signer, exist - }() - if !exist { - return nil, ErrDKGNotReady - } - return &typesDKG.PartialSignature{ - ProposerID: cc.ID, - Round: round, - Hash: hash, - PartialSignature: signer.sign(hash), - }, nil -} - -func (cc *configurationChain) touchTSigHash(hash common.Hash) (first bool) { - cc.tsigReady.L.Lock() - defer cc.tsigReady.L.Unlock() - _, exist := cc.tsigTouched[hash] - cc.tsigTouched[hash] = struct{}{} - return !exist -} - -func (cc *configurationChain) untouchTSigHash(hash common.Hash) { - cc.tsigReady.L.Lock() - defer cc.tsigReady.L.Unlock() - delete(cc.tsigTouched, hash) -} - -func (cc *configurationChain) runTSig( - round uint64, hash common.Hash) ( - crypto.Signature, error) { - gpk, exist := func() (*DKGGroupPublicKey, bool) { - cc.dkgResult.RLock() - defer cc.dkgResult.RUnlock() - gpk, exist := cc.gpk[round] - return gpk, exist - }() - if !exist { - return crypto.Signature{}, ErrDKGNotReady - } - cc.tsigReady.L.Lock() - defer cc.tsigReady.L.Unlock() - if _, exist := cc.tsig[hash]; exist { - return crypto.Signature{}, ErrTSigAlreadyRunning - } - cc.tsig[hash] = newTSigProtocol(gpk, hash) - pendingPsig := cc.pendingPsig[hash] - delete(cc.pendingPsig, hash) - go func() { - for _, psig := range pendingPsig { - if err := cc.processPartialSignature(psig); err != nil { - cc.logger.Error("failed to process partial signature", - "nodeID", cc.ID, - "error", err) - } - } - }() - var signature crypto.Signature - var err error - for func() bool { - signature, err = cc.tsig[hash].signature() - return err == ErrNotEnoughtPartialSignatures - }() { - // TODO(jimmy-dexon): add a timeout here. - cc.tsigReady.Wait() - } - delete(cc.tsig, hash) - if err != nil { - return crypto.Signature{}, err - } - return signature, nil -} - -func (cc *configurationChain) runBlockTSig( - round uint64, hash common.Hash) (crypto.Signature, error) { - sig, err := cc.runTSig(round, hash) - if err != nil { - return crypto.Signature{}, err - } - cc.logger.Info("Block TSIG", - "nodeID", cc.ID, - "round", round, - "signature", sig) - return sig, nil -} - -func (cc *configurationChain) runCRSTSig( - round uint64, crs common.Hash) ([]byte, error) { - sig, err := cc.runTSig(round, crs) - cc.logger.Info("CRS", - "nodeID", cc.ID, - "round", round+1, - "signature", sig) - return sig.Signature[:], err -} - -func (cc *configurationChain) processPrivateShare( - prvShare *typesDKG.PrivateShare) error { - cc.dkgLock.Lock() - defer cc.dkgLock.Unlock() - if cc.dkg == nil { - return nil - } - return cc.dkg.processPrivateShare(prvShare) -} - -func (cc *configurationChain) processPartialSignature( - psig *typesDKG.PartialSignature) error { - cc.tsigReady.L.Lock() - defer cc.tsigReady.L.Unlock() - if _, exist := cc.tsig[psig.Hash]; !exist { - ok, err := verifyDKGPartialSignatureSignature(psig) - if err != nil { - return err - } - if !ok { - return ErrIncorrectPartialSignatureSignature - } - cc.pendingPsig[psig.Hash] = append(cc.pendingPsig[psig.Hash], psig) - return nil - } - if err := cc.tsig[psig.Hash].processPartialSignature(psig); err != nil { - return err - } - cc.tsigReady.Broadcast() - return nil -} |