aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/dexon-foundation/dexon-consensus-core/core/configuration-chain.go
diff options
context:
space:
mode:
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.go312
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
-}