From 6aee32cd8c3d7f0c7d99bf1fe4951fdf6c534be9 Mon Sep 17 00:00:00 2001 From: Mission Liao Date: Tue, 25 Dec 2018 10:06:35 +0800 Subject: vendor: sync DEXON core and fix conflicts/missings (#101) Merging these commits in DEXON consensus core: - https://github.com/dexon-foundation/dexon-consensus/commit/dce509a13ef5873b9cae3c1cabdb97e219b6fb7d - https://github.com/dexon-foundation/dexon-consensus/commit/6d1c1aeea0d3e75d10cbb2712c68b4c422ba8ba6 - https://github.com/dexon-foundation/dexon-consensus/commit/c1ed57c4abaf1f4758e52f082bb7114ad00c8b39 --- core/vm/governance.go | 10 +- .../dexon-consensus/core/agreement-mgr.go | 6 +- .../dexon-consensus/core/agreement.go | 11 +- .../dexon-consensus/core/authenticator.go | 156 ---------- .../dexon-consensus/core/configuration-chain.go | 4 +- .../dexon-consensus/core/consensus.go | 118 +++++--- .../dexon-consensus/core/crypto.go | 292 ------------------- .../dexon-consensus/core/dkg-tsig-protocol.go | 14 +- .../dexon-consensus/core/lattice.go | 45 +-- .../dexon-consensus/core/leader-selector.go | 3 +- .../dexon-consensus/core/syncer/consensus.go | 26 +- .../dexon-consensus/core/total-ordering.go | 20 +- .../dexon-foundation/dexon-consensus/core/utils.go | 43 ++- .../dexon-consensus/core/utils/crypto.go | 317 +++++++++++++++++++++ .../dexon-consensus/core/utils/signer.go | 126 ++++++++ vendor/vendor.json | 46 +-- 16 files changed, 646 insertions(+), 591 deletions(-) delete mode 100644 vendor/github.com/dexon-foundation/dexon-consensus/core/authenticator.go delete mode 100644 vendor/github.com/dexon-foundation/dexon-consensus/core/crypto.go create mode 100644 vendor/github.com/dexon-foundation/dexon-consensus/core/utils/crypto.go create mode 100644 vendor/github.com/dexon-foundation/dexon-consensus/core/utils/signer.go diff --git a/core/vm/governance.go b/core/vm/governance.go index 597399dd5..8be5b03b2 100644 --- a/core/vm/governance.go +++ b/core/vm/governance.go @@ -31,6 +31,8 @@ import ( coreCommon "github.com/dexon-foundation/dexon-consensus/common" "github.com/dexon-foundation/dexon-consensus/core" coreCrypto "github.com/dexon-foundation/dexon-consensus/core/crypto" + coreUtils "github.com/dexon-foundation/dexon-consensus/core/utils" + "github.com/dexon-foundation/dexon-consensus/core/crypto/ecdsa" coreTypes "github.com/dexon-foundation/dexon-consensus/core/types" dkgTypes "github.com/dexon-foundation/dexon-consensus/core/types/dkg" @@ -2184,7 +2186,7 @@ func (g *GovernanceContract) addDKGComplaint(round *big.Int, comp []byte) ([]byt return g.penalize() } - verified, _ := core.VerifyDKGComplaintSignature(&dkgComplaint) + verified, _ := coreUtils.VerifyDKGComplaintSignature(&dkgComplaint) if !verified { return g.penalize() } @@ -2234,7 +2236,7 @@ func (g *GovernanceContract) addDKGMasterPublicKey(round *big.Int, mpk []byte) ( return g.penalize() } - verified, _ := core.VerifyDKGMasterPublicKeySignature(&dkgMasterPK) + verified, _ := coreUtils.VerifyDKGMasterPublicKeySignature(&dkgMasterPK) if !verified { return g.penalize() } @@ -2261,7 +2263,7 @@ func (g *GovernanceContract) addDKGMPKReady(round *big.Int, ready []byte) ([]byt return g.penalize() } - verified, _ := core.VerifyDKGMPKReadySignature(&dkgReady) + verified, _ := coreUtils.VerifyDKGMPKReadySignature(&dkgReady) if !verified { return g.penalize() } @@ -2290,7 +2292,7 @@ func (g *GovernanceContract) addDKGFinalize(round *big.Int, finalize []byte) ([] return g.penalize() } - verified, _ := core.VerifyDKGFinalizeSignature(&dkgFinalize) + verified, _ := coreUtils.VerifyDKGFinalizeSignature(&dkgFinalize) if !verified { return g.penalize() } 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 fb6536463..a9fa21df2 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 @@ -86,7 +86,7 @@ type agreementMgr struct { network Network logger common.Logger cache *utils.NodeSetCache - auth *Authenticator + signer *utils.Signer lattice *Lattice ctx context.Context lastEndTime time.Time @@ -119,7 +119,7 @@ func newAgreementMgr(con *Consensus, initRound uint64, network: con.network, logger: con.logger, cache: con.nodeSetCache, - auth: con.authModule, + signer: con.signer, lattice: con.lattice, ctx: con.ctx, initRound: initRound, @@ -181,7 +181,7 @@ func (mgr *agreementMgr) appendConfig( mgr.con.ID, recv, newLeaderSelector(genValidLeader(mgr), mgr.logger), - mgr.auth) + mgr.signer) // Hacky way to make agreement module self contained. recv.agreementModule = agrModule mgr.baModules = append(mgr.baModules, agrModule) 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 4fb0deaa8..eead4628a 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement.go @@ -26,6 +26,7 @@ import ( "github.com/dexon-foundation/dexon-consensus/common" "github.com/dexon-foundation/dexon-consensus/core/types" + "github.com/dexon-foundation/dexon-consensus/core/utils" ) // Errors for agreement module. @@ -112,7 +113,7 @@ type agreement struct { pendingVote []pendingVote candidateBlock map[common.Hash]*types.Block fastForward chan uint64 - authModule *Authenticator + signer *utils.Signer } // newAgreement creates a agreement instance. @@ -120,7 +121,7 @@ func newAgreement( ID types.NodeID, recv agreementReceiver, leader *leaderSelector, - authModule *Authenticator) *agreement { + signer *utils.Signer) *agreement { agreement := &agreement{ data: &agreementData{ recv: recv, @@ -130,7 +131,7 @@ func newAgreement( aID: &atomic.Value{}, candidateBlock: make(map[common.Hash]*types.Block), fastForward: make(chan uint64, 1), - authModule: authModule, + signer: signer, } agreement.stop() return agreement @@ -268,7 +269,7 @@ func (a *agreement) sanityCheck(vote *types.Vote) error { if _, exist := a.notarySet[vote.ProposerID]; !exist { return ErrNotInNotarySet } - ok, err := verifyVoteSignature(vote) + ok, err := utils.VerifyVoteSignature(vote) if err != nil { return err } @@ -299,7 +300,7 @@ func (a *agreement) checkForkVote(vote *types.Vote) error { // prepareVote prepares a vote. func (a *agreement) prepareVote(vote *types.Vote) (err error) { vote.Position = a.agreementID() - err = a.authModule.SignVote(vote) + err = a.signer.SignVote(vote) return } diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/authenticator.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/authenticator.go deleted file mode 100644 index 8e57f719f..000000000 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/authenticator.go +++ /dev/null @@ -1,156 +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 -// . - -package core - -import ( - "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" -) - -// Authenticator verify data owner. -type Authenticator struct { - prvKey crypto.PrivateKey - pubKey crypto.PublicKey - proposerID types.NodeID -} - -// NewAuthenticator constructs an Authenticator instance. -func NewAuthenticator(prvKey crypto.PrivateKey) (auth *Authenticator) { - auth = &Authenticator{ - prvKey: prvKey, - pubKey: prvKey.PublicKey(), - } - auth.proposerID = types.NewNodeID(auth.pubKey) - return -} - -// SignBlock signs a types.Block. -func (au *Authenticator) SignBlock(b *types.Block) (err error) { - b.ProposerID = au.proposerID - b.PayloadHash = crypto.Keccak256Hash(b.Payload) - if b.Hash, err = hashBlock(b); err != nil { - return - } - if b.Signature, err = au.prvKey.Sign(b.Hash); err != nil { - return - } - return -} - -// SignVote signs a types.Vote. -func (au *Authenticator) SignVote(v *types.Vote) (err error) { - v.ProposerID = au.proposerID - v.Signature, err = au.prvKey.Sign(hashVote(v)) - return -} - -// SignCRS signs CRS signature of types.Block. -func (au *Authenticator) SignCRS(b *types.Block, crs common.Hash) (err error) { - if b.ProposerID != au.proposerID { - err = ErrInvalidProposerID - return - } - b.CRSSignature, err = au.prvKey.Sign(hashCRS(b, crs)) - return -} - -// SignDKGComplaint signs a DKG complaint. -func (au *Authenticator) SignDKGComplaint( - complaint *typesDKG.Complaint) (err error) { - complaint.ProposerID = au.proposerID - complaint.Signature, err = au.prvKey.Sign(hashDKGComplaint(complaint)) - return -} - -// SignDKGMasterPublicKey signs a DKG master public key. -func (au *Authenticator) SignDKGMasterPublicKey( - mpk *typesDKG.MasterPublicKey) (err error) { - mpk.ProposerID = au.proposerID - mpk.Signature, err = au.prvKey.Sign(hashDKGMasterPublicKey(mpk)) - return -} - -// SignDKGPrivateShare signs a DKG private share. -func (au *Authenticator) SignDKGPrivateShare( - prvShare *typesDKG.PrivateShare) (err error) { - prvShare.ProposerID = au.proposerID - prvShare.Signature, err = au.prvKey.Sign(hashDKGPrivateShare(prvShare)) - return -} - -// SignDKGPartialSignature signs a DKG partial signature. -func (au *Authenticator) SignDKGPartialSignature( - pSig *typesDKG.PartialSignature) (err error) { - pSig.ProposerID = au.proposerID - pSig.Signature, err = au.prvKey.Sign(hashDKGPartialSignature(pSig)) - return -} - -// SignDKGMPKReady signs a DKG ready message. -func (au *Authenticator) SignDKGMPKReady( - ready *typesDKG.MPKReady) (err error) { - ready.ProposerID = au.proposerID - ready.Signature, err = au.prvKey.Sign(hashDKGMPKReady(ready)) - return -} - -// SignDKGFinalize signs a DKG finalize message. -func (au *Authenticator) SignDKGFinalize( - final *typesDKG.Finalize) (err error) { - final.ProposerID = au.proposerID - final.Signature, err = au.prvKey.Sign(hashDKGFinalize(final)) - return -} - -// VerifyBlock verifies the signature of types.Block. -func (au *Authenticator) VerifyBlock(b *types.Block) (err error) { - payloadHash := crypto.Keccak256Hash(b.Payload) - if payloadHash != b.PayloadHash { - err = ErrIncorrectHash - return - } - hash, err := hashBlock(b) - if err != nil { - return - } - if hash != b.Hash { - err = ErrIncorrectHash - return - } - pubKey, err := crypto.SigToPub(b.Hash, b.Signature) - if err != nil { - return - } - if !b.ProposerID.Equal(types.NewNodeID(pubKey)) { - err = ErrIncorrectSignature - return - } - return -} - -// VerifyVote verifies the signature of types.Vote. -func (au *Authenticator) VerifyVote(v *types.Vote) (bool, error) { - return verifyVoteSignature(v) -} - -// VerifyCRS verifies the CRS signature of types.Block. -func (au *Authenticator) VerifyCRS(b *types.Block, crs common.Hash) (bool, error) { - return verifyCRSSignature(b, crs) -} 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 d341cb524..ad24e446d 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 @@ -417,7 +417,7 @@ func (cc *configurationChain) processPrivateShare( } if !cc.mpkReady { // TODO(jimmy-dexon): remove duplicated signature check in dkg module. - ok, err := verifyDKGPrivateShareSignature(prvShare) + ok, err := utils.VerifyDKGPrivateShareSignature(prvShare) if err != nil { return err } @@ -435,7 +435,7 @@ func (cc *configurationChain) processPartialSignature( cc.tsigReady.L.Lock() defer cc.tsigReady.L.Unlock() if _, exist := cc.tsig[psig.Hash]; !exist { - ok, err := verifyDKGPartialSignatureSignature(psig) + ok, err := utils.VerifyDKGPartialSignatureSignature(psig) if err != nil { return err } 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 e45e4be5a..0d4a38a91 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/consensus.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/consensus.go @@ -260,7 +260,7 @@ func (recv *consensusBAReceiver) PullBlocks(hashes common.Hashes) { type consensusDKGReceiver struct { ID types.NodeID gov Governance - authModule *Authenticator + signer *utils.Signer nodeSetCache *utils.NodeSetCache cfgModule *configurationChain network Network @@ -270,7 +270,7 @@ type consensusDKGReceiver struct { // ProposeDKGComplaint proposes a DKGComplaint. func (recv *consensusDKGReceiver) ProposeDKGComplaint( complaint *typesDKG.Complaint) { - if err := recv.authModule.SignDKGComplaint(complaint); err != nil { + if err := recv.signer.SignDKGComplaint(complaint); err != nil { recv.logger.Error("Failed to sign DKG complaint", "error", err) return } @@ -282,7 +282,7 @@ func (recv *consensusDKGReceiver) ProposeDKGComplaint( // ProposeDKGMasterPublicKey propose a DKGMasterPublicKey. func (recv *consensusDKGReceiver) ProposeDKGMasterPublicKey( mpk *typesDKG.MasterPublicKey) { - if err := recv.authModule.SignDKGMasterPublicKey(mpk); err != nil { + if err := recv.signer.SignDKGMasterPublicKey(mpk); err != nil { recv.logger.Error("Failed to sign DKG master public key", "error", err) return } @@ -293,7 +293,7 @@ func (recv *consensusDKGReceiver) ProposeDKGMasterPublicKey( // ProposeDKGPrivateShare propose a DKGPrivateShare. func (recv *consensusDKGReceiver) ProposeDKGPrivateShare( prv *typesDKG.PrivateShare) { - if err := recv.authModule.SignDKGPrivateShare(prv); err != nil { + if err := recv.signer.SignDKGPrivateShare(prv); err != nil { recv.logger.Error("Failed to sign DKG private share", "error", err) return } @@ -320,7 +320,7 @@ func (recv *consensusDKGReceiver) ProposeDKGPrivateShare( func (recv *consensusDKGReceiver) ProposeDKGAntiNackComplaint( prv *typesDKG.PrivateShare) { if prv.ProposerID == recv.ID { - if err := recv.authModule.SignDKGPrivateShare(prv); err != nil { + if err := recv.signer.SignDKGPrivateShare(prv); err != nil { recv.logger.Error("Failed sign DKG private share", "error", err) return } @@ -331,7 +331,7 @@ func (recv *consensusDKGReceiver) ProposeDKGAntiNackComplaint( // ProposeDKGMPKReady propose a DKGMPKReady message. func (recv *consensusDKGReceiver) ProposeDKGMPKReady(ready *typesDKG.MPKReady) { - if err := recv.authModule.SignDKGMPKReady(ready); err != nil { + if err := recv.signer.SignDKGMPKReady(ready); err != nil { recv.logger.Error("Failed to sign DKG ready", "error", err) return } @@ -341,7 +341,7 @@ func (recv *consensusDKGReceiver) ProposeDKGMPKReady(ready *typesDKG.MPKReady) { // ProposeDKGFinalize propose a DKGFinalize message. func (recv *consensusDKGReceiver) ProposeDKGFinalize(final *typesDKG.Finalize) { - if err := recv.authModule.SignDKGFinalize(final); err != nil { + if err := recv.signer.SignDKGFinalize(final); err != nil { recv.logger.Error("Failed to sign DKG finalize", "error", err) return } @@ -352,8 +352,8 @@ func (recv *consensusDKGReceiver) ProposeDKGFinalize(final *typesDKG.Finalize) { // Consensus implements DEXON Consensus algorithm. type Consensus struct { // Node Info. - ID types.NodeID - authModule *Authenticator + ID types.NodeID + signer *utils.Signer // BA. baMgr *agreementMgr @@ -399,10 +399,38 @@ func NewConsensus( prv crypto.PrivateKey, logger common.Logger) *Consensus { + return newConsensus(dMoment, app, gov, db, network, prv, logger, true) +} + +// NewConsensusForSimulation creates an instance of Consensus for simulation, +// the only difference with NewConsensus is nonblocking of app. +func NewConsensusForSimulation( + dMoment time.Time, + app Application, + gov Governance, + db db.Database, + network Network, + prv crypto.PrivateKey, + logger common.Logger) *Consensus { + + return newConsensus(dMoment, app, gov, db, network, prv, logger, false) +} + +// newConsensus creates a Consensus instance. +func newConsensus( + dMoment time.Time, + app Application, + gov Governance, + db db.Database, + network Network, + prv crypto.PrivateKey, + logger common.Logger, + usingNonBlocking bool) *Consensus { + // TODO(w): load latest blockHeight from DB, and use config at that height. nodeSetCache := utils.NewNodeSetCache(gov) - // Setup auth module. - authModule := NewAuthenticator(prv) + // Setup signer module. + signer := utils.NewSigner(prv) // Check if the application implement Debug interface. var debugApp Debug if a, ok := app.(Debug); ok { @@ -413,13 +441,13 @@ func NewConsensus( config := utils.GetConfigWithPanic(gov, round, logger) // Init lattice. lattice := NewLattice( - dMoment, round, config, authModule, app, debugApp, db, logger) + dMoment, round, config, signer, app, debugApp, db, logger) // Init configuration chain. ID := types.NewNodeID(prv.PublicKey()) recv := &consensusDKGReceiver{ ID: ID, gov: gov, - authModule: authModule, + signer: signer, nodeSetCache: nodeSetCache, network: network, logger: logger, @@ -432,12 +460,16 @@ func NewConsensus( db, logger) recv.cfgModule = cfgModule + appModule := app + if usingNonBlocking { + appModule = newNonBlocking(app, debugApp) + } // Construct Consensus instance. con := &Consensus{ ID: ID, ccModule: newCompactionChain(gov), lattice: lattice, - app: newNonBlocking(app, debugApp), + app: appModule, debugApp: debugApp, gov: gov, db: db, @@ -447,7 +479,7 @@ func NewConsensus( cfgModule: cfgModule, dMoment: dMoment, nodeSetCache: nodeSetCache, - authModule: authModule, + signer: signer, event: common.NewEvent(), logger: logger, } @@ -479,14 +511,14 @@ func NewConsensusFromSyncer( logger common.Logger) (*Consensus, error) { // Setup the cache for node sets. nodeSetCache := utils.NewNodeSetCache(gov) - // Setup auth module. - authModule := NewAuthenticator(prv) + // Setup signer module. + signer := utils.NewSigner(prv) // Init configuration chain. ID := types.NewNodeID(prv.PublicKey()) recv := &consensusDKGReceiver{ ID: ID, gov: gov, - authModule: authModule, + signer: signer, nodeSetCache: nodeSetCache, network: networkModule, logger: logger, @@ -518,7 +550,7 @@ func NewConsensusFromSyncer( cfgModule: cfgModule, dMoment: initRoundBeginTime, nodeSetCache: nodeSetCache, - authModule: authModule, + signer: signer, event: common.NewEvent(), logger: logger, } @@ -569,7 +601,11 @@ func (con *Consensus) prepare(initBlock *types.Block) error { // Setup lattice module. initPlusOneCfg := utils.GetConfigWithPanic(con.gov, initRound+1, con.logger) if err := con.lattice.AppendConfig(initRound+1, initPlusOneCfg); err != nil { - return err + if err == ErrRoundNotIncreasing { + err = nil + } else { + return err + } } // Register events. dkgSet, err := con.nodeSetCache.GetDKGSet(initRound) @@ -655,7 +691,7 @@ func (con *Consensus) runCRS(round uint64) { round, utils.GetCRSWithPanic(con.gov, round, con.logger)) if err != nil { con.logger.Error("Failed to prepare partial signature", "error", err) - } else if err = con.authModule.SignDKGPartialSignature(psig); err != nil { + } else if err = con.signer.SignDKGPartialSignature(psig); err != nil { con.logger.Error("Failed to sign DKG partial signature", "error", err) } else if err = con.cfgModule.processPartialSignature(psig); err != nil { con.logger.Error("Failed to process partial signature", "error", err) @@ -700,23 +736,37 @@ func (con *Consensus) initialRound( }() }) } + // checkCRS is a generator of checker to check if CRS for that round is + // ready or not. + checkCRS := func(round uint64) func() bool { + return func() bool { + nextCRS := con.gov.CRS(round) + if (nextCRS != common.Hash{}) { + return true + } + con.logger.Info("CRS is not ready yet. Try again later...", + "nodeID", con.ID, + "round", round) + return false + } + } // Initiate BA modules. con.event.RegisterTime( startTime.Add(config.RoundInterval/2+config.LambdaDKG), func(time.Time) { go func(nextRound uint64) { - for (con.gov.CRS(nextRound) == common.Hash{}) { - con.logger.Info("CRS is not ready yet. Try again later...", - "nodeID", con.ID, + if !checkWithCancel( + con.ctx, 500*time.Millisecond, checkCRS(nextRound)) { + con.logger.Info("unable to prepare CRS for baMgr", "round", nextRound) - time.Sleep(500 * time.Millisecond) + return } // Notify BA for new round. nextConfig := utils.GetConfigWithPanic( con.gov, nextRound, con.logger) - con.logger.Debug("Calling Governance.CRS", - "round", nextRound) - nextCRS := utils.GetCRSWithPanic(con.gov, nextRound, con.logger) + nextCRS := utils.GetCRSWithPanic( + con.gov, nextRound, con.logger) + con.logger.Info("appendConfig for baMgr", "round", nextRound) if err := con.baMgr.appendConfig( nextRound, nextConfig, nextCRS); err != nil { panic(err) @@ -729,11 +779,11 @@ func (con *Consensus) initialRound( go func(nextRound uint64) { // Normally, gov.CRS would return non-nil. Use this for in case of // unexpected network fluctuation and ensure the robustness. - for (con.gov.CRS(nextRound) == common.Hash{}) { - con.logger.Info("CRS is not ready yet. Try again later...", - "nodeID", con.ID, + if !checkWithCancel( + con.ctx, 500*time.Millisecond, checkCRS(nextRound)) { + con.logger.Info("unable to prepare CRS for DKG set", "round", nextRound) - time.Sleep(500 * time.Millisecond) + return } nextDkgSet, err := con.nodeSetCache.GetDKGSet(nextRound) if err != nil { @@ -933,7 +983,7 @@ func (con *Consensus) ProcessAgreementResult( if err != nil { return err } - if err = con.authModule.SignDKGPartialSignature(psig); err != nil { + if err = con.signer.SignDKGPartialSignature(psig); err != nil { return err } if err = con.cfgModule.processPartialSignature(psig); err != nil { @@ -1123,7 +1173,7 @@ func (con *Consensus) prepareBlock(b *types.Block, err = ErrCRSNotReady return } - if err = con.authModule.SignCRS(b, crs); err != nil { + if err = con.signer.SignCRS(b, crs); err != nil { return } return diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/crypto.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/crypto.go deleted file mode 100644 index d4a7f0ead..000000000 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/crypto.go +++ /dev/null @@ -1,292 +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 -// . - -package core - -import ( - "encoding/binary" - - "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" -) - -func hashWitness(witness *types.Witness) (common.Hash, error) { - binaryHeight := make([]byte, 8) - binary.LittleEndian.PutUint64(binaryHeight, witness.Height) - return crypto.Keccak256Hash( - binaryHeight, - witness.Data), nil -} - -func hashBlock(block *types.Block) (common.Hash, error) { - hashPosition := hashPosition(block.Position) - // Handling Block.Acks. - binaryAcks := make([][]byte, len(block.Acks)) - for idx, ack := range block.Acks { - binaryAcks[idx] = ack[:] - } - hashAcks := crypto.Keccak256Hash(binaryAcks...) - binaryTimestamp, err := block.Timestamp.UTC().MarshalBinary() - if err != nil { - return common.Hash{}, err - } - binaryWitness, err := hashWitness(&block.Witness) - if err != nil { - return common.Hash{}, err - } - - hash := crypto.Keccak256Hash( - block.ProposerID.Hash[:], - block.ParentHash[:], - hashPosition[:], - hashAcks[:], - binaryTimestamp[:], - block.PayloadHash[:], - binaryWitness[:]) - return hash, nil -} - -func verifyBlockSignature(pubkey crypto.PublicKey, - block *types.Block, sig crypto.Signature) (bool, error) { - hash, err := hashBlock(block) - if err != nil { - return false, err - } - return pubkey.VerifySignature(hash, sig), nil -} - -func hashVote(vote *types.Vote) common.Hash { - binaryPeriod := make([]byte, 8) - binary.LittleEndian.PutUint64(binaryPeriod, vote.Period) - - hashPosition := hashPosition(vote.Position) - - hash := crypto.Keccak256Hash( - vote.ProposerID.Hash[:], - vote.BlockHash[:], - binaryPeriod, - hashPosition[:], - []byte{byte(vote.Type)}, - ) - return hash -} - -func verifyVoteSignature(vote *types.Vote) (bool, error) { - hash := hashVote(vote) - pubKey, err := crypto.SigToPub(hash, vote.Signature) - if err != nil { - return false, err - } - if vote.ProposerID != types.NewNodeID(pubKey) { - return false, nil - } - return true, nil -} - -func hashCRS(block *types.Block, crs common.Hash) common.Hash { - hashPos := hashPosition(block.Position) - return crypto.Keccak256Hash(crs[:], hashPos[:]) -} - -func verifyCRSSignature(block *types.Block, crs common.Hash) ( - bool, error) { - hash := hashCRS(block, crs) - pubKey, err := crypto.SigToPub(hash, block.CRSSignature) - if err != nil { - return false, err - } - if block.ProposerID != types.NewNodeID(pubKey) { - return false, nil - } - return true, nil -} - -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, - ) -} - -func hashDKGPrivateShare(prvShare *typesDKG.PrivateShare) common.Hash { - binaryRound := make([]byte, 8) - binary.LittleEndian.PutUint64(binaryRound, prvShare.Round) - - return crypto.Keccak256Hash( - prvShare.ProposerID.Hash[:], - prvShare.ReceiverID.Hash[:], - binaryRound, - prvShare.PrivateShare.Bytes(), - ) -} - -func verifyDKGPrivateShareSignature( - prvShare *typesDKG.PrivateShare) (bool, error) { - hash := hashDKGPrivateShare(prvShare) - pubKey, err := crypto.SigToPub(hash, prvShare.Signature) - if err != nil { - return false, err - } - if prvShare.ProposerID != types.NewNodeID(pubKey) { - return false, nil - } - return true, nil -} - -func hashDKGMasterPublicKey(mpk *typesDKG.MasterPublicKey) common.Hash { - binaryRound := make([]byte, 8) - binary.LittleEndian.PutUint64(binaryRound, mpk.Round) - - return crypto.Keccak256Hash( - mpk.ProposerID.Hash[:], - mpk.DKGID.GetLittleEndian(), - mpk.PublicKeyShares.MasterKeyBytes(), - binaryRound, - ) -} - -// VerifyDKGMasterPublicKeySignature verifies DKGMasterPublicKey signature. -func VerifyDKGMasterPublicKeySignature( - mpk *typesDKG.MasterPublicKey) (bool, error) { - hash := hashDKGMasterPublicKey(mpk) - pubKey, err := crypto.SigToPub(hash, mpk.Signature) - if err != nil { - return false, err - } - if mpk.ProposerID != types.NewNodeID(pubKey) { - return false, nil - } - return true, nil -} - -func hashDKGComplaint(complaint *typesDKG.Complaint) common.Hash { - binaryRound := make([]byte, 8) - binary.LittleEndian.PutUint64(binaryRound, complaint.Round) - - hashPrvShare := hashDKGPrivateShare(&complaint.PrivateShare) - - return crypto.Keccak256Hash( - complaint.ProposerID.Hash[:], - binaryRound, - hashPrvShare[:], - ) -} - -// VerifyDKGComplaintSignature verifies DKGCompliant signature. -func VerifyDKGComplaintSignature( - complaint *typesDKG.Complaint) (bool, error) { - if complaint.Round != complaint.PrivateShare.Round { - return false, nil - } - hash := hashDKGComplaint(complaint) - pubKey, err := crypto.SigToPub(hash, complaint.Signature) - if err != nil { - return false, err - } - if complaint.ProposerID != types.NewNodeID(pubKey) { - return false, nil - } - if !complaint.IsNack() { - return verifyDKGPrivateShareSignature(&complaint.PrivateShare) - } - return true, nil -} - -func hashDKGPartialSignature(psig *typesDKG.PartialSignature) common.Hash { - binaryRound := make([]byte, 8) - binary.LittleEndian.PutUint64(binaryRound, psig.Round) - - return crypto.Keccak256Hash( - psig.ProposerID.Hash[:], - binaryRound, - psig.Hash[:], - psig.PartialSignature.Signature[:], - ) -} - -func verifyDKGPartialSignatureSignature( - psig *typesDKG.PartialSignature) (bool, error) { - hash := hashDKGPartialSignature(psig) - pubKey, err := crypto.SigToPub(hash, psig.Signature) - if err != nil { - return false, err - } - if psig.ProposerID != types.NewNodeID(pubKey) { - return false, nil - } - return true, nil -} - -func hashDKGMPKReady(ready *typesDKG.MPKReady) common.Hash { - binaryRound := make([]byte, 8) - binary.LittleEndian.PutUint64(binaryRound, ready.Round) - - return crypto.Keccak256Hash( - ready.ProposerID.Hash[:], - binaryRound, - ) -} - -// VerifyDKGMPKReadySignature verifies DKGMPKReady signature. -func VerifyDKGMPKReadySignature( - ready *typesDKG.MPKReady) (bool, error) { - hash := hashDKGMPKReady(ready) - pubKey, err := crypto.SigToPub(hash, ready.Signature) - if err != nil { - return false, err - } - if ready.ProposerID != types.NewNodeID(pubKey) { - return false, nil - } - return true, nil -} - -func hashDKGFinalize(final *typesDKG.Finalize) common.Hash { - binaryRound := make([]byte, 8) - binary.LittleEndian.PutUint64(binaryRound, final.Round) - - return crypto.Keccak256Hash( - final.ProposerID.Hash[:], - binaryRound, - ) -} - -// VerifyDKGFinalizeSignature verifies DKGFinalize signature. -func VerifyDKGFinalizeSignature( - final *typesDKG.Finalize) (bool, error) { - hash := hashDKGFinalize(final) - pubKey, err := crypto.SigToPub(hash, final.Signature) - if err != nil { - return false, err - } - if final.ProposerID != types.NewNodeID(pubKey) { - return false, nil - } - return true, nil -} 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 ef12cf992..492271e98 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 @@ -155,7 +155,6 @@ func newDKGProtocol( prvShare, pubShare := dkg.NewPrivateKeyShares(threshold) recv.ProposeDKGMasterPublicKey(&typesDKG.MasterPublicKey{ - ProposerID: ID, Round: round, DKGID: newDKGID(ID), PublicKeyShares: *pubShare, @@ -195,7 +194,6 @@ func (d *dkgProtocol) processMasterPublicKeys( return ErrIDShareNotFound } d.recv.ProposeDKGPrivateShare(&typesDKG.PrivateShare{ - ProposerID: d.ID, ReceiverID: mpk.ProposerID, Round: d.round, PrivateShare: *share, @@ -210,8 +208,7 @@ func (d *dkgProtocol) proposeNackComplaints() { continue } d.recv.ProposeDKGComplaint(&typesDKG.Complaint{ - ProposerID: d.ID, - Round: d.round, + Round: d.round, PrivateShare: typesDKG.PrivateShare{ ProposerID: nID, Round: d.round, @@ -240,7 +237,6 @@ func (d *dkgProtocol) processNackComplaints(complaints []*typesDKG.Complaint) ( continue } d.recv.ProposeDKGAntiNackComplaint(&typesDKG.PrivateShare{ - ProposerID: d.ID, ReceiverID: complaint.ProposerID, Round: d.round, PrivateShare: *share, @@ -267,8 +263,7 @@ func (d *dkgProtocol) enforceNackComplaints(complaints []*typesDKG.Complaint) { if _, exist := d.antiComplaintReceived[from][to]; !exist { d.recv.ProposeDKGComplaint(&typesDKG.Complaint{ - ProposerID: d.ID, - Round: d.round, + Round: d.round, PrivateShare: typesDKG.PrivateShare{ ProposerID: to, Round: d.round, @@ -282,7 +277,7 @@ func (d *dkgProtocol) sanityCheck(prvShare *typesDKG.PrivateShare) error { if _, exist := d.idMap[prvShare.ProposerID]; !exist { return ErrNotDKGParticipant } - ok, err := verifyDKGPrivateShareSignature(prvShare) + ok, err := utils.VerifyDKGPrivateShareSignature(prvShare) if err != nil { return err } @@ -318,7 +313,6 @@ func (d *dkgProtocol) processPrivateShare( return nil } complaint := &typesDKG.Complaint{ - ProposerID: d.ID, Round: d.round, PrivateShare: *prvShare, } @@ -546,7 +540,7 @@ func (tsig *tsigProtocol) sanityCheck(psig *typesDKG.PartialSignature) error { if !exist { return ErrNotQualifyDKGParticipant } - ok, err := verifyDKGPartialSignatureSignature(psig) + ok, err := utils.VerifyDKGPartialSignatureSignature(psig) if err != nil { return err } diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/lattice.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/lattice.go index 8780bbaec..db19cf910 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/lattice.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/lattice.go @@ -25,6 +25,7 @@ import ( "github.com/dexon-foundation/dexon-consensus/common" "github.com/dexon-foundation/dexon-consensus/core/db" "github.com/dexon-foundation/dexon-consensus/core/types" + "github.com/dexon-foundation/dexon-consensus/core/utils" ) // Errors for sanity check error. @@ -34,15 +35,15 @@ var ( // Lattice represents a unit to produce a global ordering from multiple chains. type Lattice struct { - lock sync.RWMutex - authModule *Authenticator - app Application - debug Debug - pool blockPool - data *latticeData - toModule *totalOrdering - ctModule *consensusTimestamp - logger common.Logger + lock sync.RWMutex + signer *utils.Signer + app Application + debug Debug + pool blockPool + data *latticeData + toModule *totalOrdering + ctModule *consensusTimestamp + logger common.Logger } // NewLattice constructs an Lattice instance. @@ -50,7 +51,7 @@ func NewLattice( dMoment time.Time, round uint64, cfg *types.Config, - authModule *Authenticator, + signer *utils.Signer, app Application, debug Debug, db db.Database, @@ -58,14 +59,14 @@ func NewLattice( // Create genesis latticeDataConfig. return &Lattice{ - authModule: authModule, - app: app, - debug: debug, - pool: newBlockPool(cfg.NumChains), - data: newLatticeData(db, dMoment, round, cfg), - toModule: newTotalOrdering(dMoment, round, cfg), - ctModule: newConsensusTimestamp(dMoment, round, cfg.NumChains), - logger: logger, + signer: signer, + app: app, + debug: debug, + pool: newBlockPool(cfg.NumChains), + data: newLatticeData(db, dMoment, round, cfg), + toModule: newTotalOrdering(dMoment, round, cfg), + ctModule: newConsensusTimestamp(dMoment, round, cfg.NumChains), + logger: logger, } } @@ -89,7 +90,7 @@ func (l *Lattice) PrepareBlock( if b.Witness, err = l.app.PrepareWitness(b.Witness.Height); err != nil { return } - if err = l.authModule.SignBlock(b); err != nil { + if err = l.signer.SignBlock(b); err != nil { return } return @@ -102,7 +103,7 @@ func (l *Lattice) PrepareEmptyBlock(b *types.Block) (err error) { if err = l.data.prepareEmptyBlock(b); err != nil { return } - if b.Hash, err = hashBlock(b); err != nil { + if b.Hash, err = utils.HashBlock(b); err != nil { return } return @@ -116,7 +117,7 @@ func (l *Lattice) SanityCheck(b *types.Block) (err error) { if b.IsEmpty() { // Only need to verify block's hash. var hash common.Hash - if hash, err = hashBlock(b); err != nil { + if hash, err = utils.HashBlock(b); err != nil { return } if b.Hash != hash { @@ -124,7 +125,7 @@ func (l *Lattice) SanityCheck(b *types.Block) (err error) { } } else { // Verify block's signature. - if err = l.authModule.VerifyBlock(b); err != nil { + if err = utils.VerifyBlockSignature(b); err != nil { return } } diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/leader-selector.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/leader-selector.go index a68f8ab66..94d28faeb 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/leader-selector.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/leader-selector.go @@ -25,6 +25,7 @@ import ( "github.com/dexon-foundation/dexon-consensus/common" "github.com/dexon-foundation/dexon-consensus/core/crypto" "github.com/dexon-foundation/dexon-consensus/core/types" + "github.com/dexon-foundation/dexon-consensus/core/utils" ) // Errors for leader module. @@ -121,7 +122,7 @@ func (l *leaderSelector) leaderBlockHash() common.Hash { } func (l *leaderSelector) processBlock(block *types.Block) error { - ok, err := verifyCRSSignature(block, l.hashCRS) + ok, err := utils.VerifyCRSSignature(block, l.hashCRS) if err != nil { return err } 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 da9d352f4..32bbab3b2 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 @@ -127,7 +127,7 @@ func (con *Consensus) initConsensusObj(initBlock *types.Block) { con.roundBeginTimes[con.latticeLastRound], con.latticeLastRound, cfg, - core.NewAuthenticator(con.prv), + utils.NewSigner(con.prv), con.app, debugApp, con.db, @@ -446,9 +446,10 @@ func (con *Consensus) SyncBlocks( return false, err } if syncBlock != nil { - con.logger.Info("deliver set found", syncBlock) + con.logger.Info("deliver set found", "block", syncBlock) // New lattice with the round of syncBlock. con.initConsensusObj(syncBlock) + con.setupConfigs(blocks) // Process blocks from syncBlock to blocks' last block. b := blocks[len(blocks)-1] blocksCount := b.Finalization.Height - syncBlock.Finalization.Height + 1 @@ -586,7 +587,7 @@ func (con *Consensus) setupConfigs(blocks []*types.Block) { con.resizeByNumChains(curMaxNumChains) // Notify core.Lattice for new configs. if con.lattice != nil { - for con.latticeLastRound+1 <= maxRound { + for con.latticeLastRound+1 <= untilRound { con.latticeLastRound++ if err := con.lattice.AppendConfig( con.latticeLastRound, @@ -714,14 +715,12 @@ func (con *Consensus) startCRSMonitor() { select { case <-con.ctx.Done(): return - case <-time.After(1 * time.Second): - // Notify agreement modules for the latest round that CRS is - // available if the round is not notified yet. - var crsRound = lastNotifiedRound - for (con.gov.CRS(crsRound+1) != common.Hash{}) { - crsRound++ - } - notifyNewCRS(crsRound) + case <-time.After(500 * time.Millisecond): + } + // Notify agreement modules for the latest round that CRS is + // available if the round is not notified yet. + if (con.gov.CRS(lastNotifiedRound+1) != common.Hash{}) { + notifyNewCRS(lastNotifiedRound + 1) } } }() @@ -732,7 +731,10 @@ func (con *Consensus) stopAgreement() { con.lock.Lock() defer con.lock.Unlock() for _, a := range con.agreements { - close(a.inputChan) + if a.inputChan != nil { + close(a.inputChan) + a.inputChan = nil + } } }() con.agreementWaitGroup.Wait() diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/total-ordering.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/total-ordering.go index 3bf6946ae..744471a84 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/total-ordering.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/total-ordering.go @@ -19,6 +19,7 @@ package core import ( "errors" + "fmt" "math" "sort" "sync" @@ -1017,7 +1018,7 @@ func (to *totalOrdering) generateDeliverSet() ( chainID, otherChainID uint32 info, otherInfo *totalOrderingCandidateInfo precedings = make(map[uint32]struct{}) - cfg = to.configs[to.curRound-to.configs[0].roundID] + cfg = to.getCurrentConfig() ) mode = TotalOrderingModeNormal to.globalVector.updateCandidateInfo(to.dirtyChainIDs, to.objCache) @@ -1162,7 +1163,7 @@ func (to *totalOrdering) flushBlocks( b *types.Block) (flushed []*types.Block, mode uint32, err error) { mode = TotalOrderingModeFlush - cfg := to.configs[to.curRound-to.configs[0].roundID] + cfg := to.getCurrentConfig() if cfg.isLastBlock(b) { to.flushReadyChains[b.Position.ChainID] = struct{}{} } @@ -1216,7 +1217,7 @@ func (to *totalOrdering) flushBlocks( to.globalVector.cachedCandidateInfo = nil to.switchRound() // Force picking new candidates. - numChains := to.configs[to.curRound-to.configs[0].roundID].numChains + numChains := to.getCurrentConfig().numChains to.output(map[common.Hash]struct{}{}, numChains) return } @@ -1226,7 +1227,7 @@ func (to *totalOrdering) deliverBlocks() ( delivered []*types.Block, mode uint32, err error) { hashes, mode := to.generateDeliverSet() - cfg := to.configs[to.curRound-to.configs[0].roundID] + cfg := to.getCurrentConfig() // Output precedings. delivered = to.output(hashes, cfg.numChains) // Check if any block in delivered set is the last block in this round, if @@ -1271,12 +1272,21 @@ func (to *totalOrdering) deliverBlocks() ( return } +func (to *totalOrdering) getCurrentConfig() *totalOrderingConfig { + cfgIdx := to.curRound - to.configs[0].roundID + if cfgIdx >= uint64(len(to.configs)) { + panic(fmt.Errorf("total ordering config is not ready: %v, %v, %v", + to.curRound, to.configs[0].roundID, len(to.configs))) + } + return to.configs[cfgIdx] +} + // processBlock is the entry point of totalOrdering. func (to *totalOrdering) processBlock( b *types.Block) ([]*types.Block, uint32, error) { // NOTE: Block b is assumed to be in topologically sorted, i.e., all its // acking blocks are during or after total ordering stage. - cfg := to.configs[to.curRound-to.configs[0].roundID] + cfg := to.getCurrentConfig() to.pendings[b.Hash] = b to.buildBlockRelation(b) isOldest, err := to.updateVectors(b) 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 671d68018..0c2d15588 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/utils.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils.go @@ -18,6 +18,7 @@ package core import ( + "context" "errors" "fmt" "math/rand" @@ -146,27 +147,6 @@ func HashConfigurationBlock( ) } -// VerifyBlock verifies the signature of types.Block. -func VerifyBlock(b *types.Block) (err error) { - hash, err := hashBlock(b) - if err != nil { - return - } - if hash != b.Hash { - err = ErrIncorrectHash - return - } - pubKey, err := crypto.SigToPub(b.Hash, b.Signature) - if err != nil { - return - } - if !b.ProposerID.Equal(types.NewNodeID(pubKey)) { - err = ErrIncorrectSignature - return - } - return -} - // VerifyAgreementResult perform sanity check against a types.AgreementResult // instance. func VerifyAgreementResult( @@ -201,7 +181,7 @@ func VerifyAgreementResult( if _, exist := notarySet[vote.ProposerID]; !exist { return ErrIncorrectVoteProposer } - ok, err := verifyVoteSignature(&vote) + ok, err := utils.VerifyVoteSignature(&vote) if err != nil { return err } @@ -235,3 +215,22 @@ func isTravisCI() bool { 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) { + ctx, cancel := context.WithCancel(parentCtx) + defer cancel() +Loop: + for { + select { + case <-ctx.Done(): + break Loop + case <-time.After(interval): + } + if ret = checker(); ret { + return + } + } + return +} diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/crypto.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/crypto.go new file mode 100644 index 000000000..60424115e --- /dev/null +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/crypto.go @@ -0,0 +1,317 @@ +// 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 utils + +import ( + "encoding/binary" + + "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" +) + +func hashWitness(witness *types.Witness) (common.Hash, error) { + binaryHeight := make([]byte, 8) + binary.LittleEndian.PutUint64(binaryHeight, witness.Height) + return crypto.Keccak256Hash( + binaryHeight, + witness.Data), nil +} + +// HashBlock generates hash of a types.Block. +func HashBlock(block *types.Block) (common.Hash, error) { + hashPosition := hashPosition(block.Position) + // Handling Block.Acks. + binaryAcks := make([][]byte, len(block.Acks)) + for idx, ack := range block.Acks { + binaryAcks[idx] = ack[:] + } + hashAcks := crypto.Keccak256Hash(binaryAcks...) + binaryTimestamp, err := block.Timestamp.UTC().MarshalBinary() + if err != nil { + return common.Hash{}, err + } + binaryWitness, err := hashWitness(&block.Witness) + if err != nil { + return common.Hash{}, err + } + + hash := crypto.Keccak256Hash( + block.ProposerID.Hash[:], + block.ParentHash[:], + hashPosition[:], + hashAcks[:], + binaryTimestamp[:], + block.PayloadHash[:], + binaryWitness[:]) + return hash, nil +} + +// VerifyBlockSignature verifies the signature of types.Block. +func VerifyBlockSignature(b *types.Block) (err error) { + payloadHash := crypto.Keccak256Hash(b.Payload) + if payloadHash != b.PayloadHash { + err = ErrIncorrectHash + return + } + hash, err := HashBlock(b) + if err != nil { + return + } + if hash != b.Hash { + err = ErrIncorrectHash + return + } + pubKey, err := crypto.SigToPub(b.Hash, b.Signature) + if err != nil { + return + } + if !b.ProposerID.Equal(types.NewNodeID(pubKey)) { + err = ErrIncorrectSignature + return + } + return + +} + +func hashVote(vote *types.Vote) common.Hash { + binaryPeriod := make([]byte, 8) + binary.LittleEndian.PutUint64(binaryPeriod, vote.Period) + + hashPosition := hashPosition(vote.Position) + + hash := crypto.Keccak256Hash( + vote.ProposerID.Hash[:], + vote.BlockHash[:], + binaryPeriod, + hashPosition[:], + []byte{byte(vote.Type)}, + ) + return hash +} + +// VerifyVoteSignature verifies the signature of types.Vote. +func VerifyVoteSignature(vote *types.Vote) (bool, error) { + hash := hashVote(vote) + pubKey, err := crypto.SigToPub(hash, vote.Signature) + if err != nil { + return false, err + } + if vote.ProposerID != types.NewNodeID(pubKey) { + return false, nil + } + return true, nil +} + +func hashCRS(block *types.Block, crs common.Hash) common.Hash { + hashPos := hashPosition(block.Position) + return crypto.Keccak256Hash(crs[:], hashPos[:]) +} + +// VerifyCRSSignature verifies the CRS signature of types.Block. +func VerifyCRSSignature(block *types.Block, crs common.Hash) ( + bool, error) { + hash := hashCRS(block, crs) + pubKey, err := crypto.SigToPub(hash, block.CRSSignature) + if err != nil { + return false, err + } + if block.ProposerID != types.NewNodeID(pubKey) { + return false, nil + } + return true, nil +} + +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, + ) +} + +func hashDKGPrivateShare(prvShare *typesDKG.PrivateShare) common.Hash { + binaryRound := make([]byte, 8) + binary.LittleEndian.PutUint64(binaryRound, prvShare.Round) + + return crypto.Keccak256Hash( + prvShare.ProposerID.Hash[:], + prvShare.ReceiverID.Hash[:], + binaryRound, + prvShare.PrivateShare.Bytes(), + ) +} + +// VerifyDKGPrivateShareSignature verifies the signature of +// typesDKG.PrivateShare. +func VerifyDKGPrivateShareSignature( + prvShare *typesDKG.PrivateShare) (bool, error) { + hash := hashDKGPrivateShare(prvShare) + pubKey, err := crypto.SigToPub(hash, prvShare.Signature) + if err != nil { + return false, err + } + if prvShare.ProposerID != types.NewNodeID(pubKey) { + return false, nil + } + return true, nil +} + +func hashDKGMasterPublicKey(mpk *typesDKG.MasterPublicKey) common.Hash { + binaryRound := make([]byte, 8) + binary.LittleEndian.PutUint64(binaryRound, mpk.Round) + + return crypto.Keccak256Hash( + mpk.ProposerID.Hash[:], + mpk.DKGID.GetLittleEndian(), + mpk.PublicKeyShares.MasterKeyBytes(), + binaryRound, + ) +} + +// VerifyDKGMasterPublicKeySignature verifies DKGMasterPublicKey signature. +func VerifyDKGMasterPublicKeySignature( + mpk *typesDKG.MasterPublicKey) (bool, error) { + hash := hashDKGMasterPublicKey(mpk) + pubKey, err := crypto.SigToPub(hash, mpk.Signature) + if err != nil { + return false, err + } + if mpk.ProposerID != types.NewNodeID(pubKey) { + return false, nil + } + return true, nil +} + +func hashDKGComplaint(complaint *typesDKG.Complaint) common.Hash { + binaryRound := make([]byte, 8) + binary.LittleEndian.PutUint64(binaryRound, complaint.Round) + + hashPrvShare := hashDKGPrivateShare(&complaint.PrivateShare) + + return crypto.Keccak256Hash( + complaint.ProposerID.Hash[:], + binaryRound, + hashPrvShare[:], + ) +} + +// VerifyDKGComplaintSignature verifies DKGCompliant signature. +func VerifyDKGComplaintSignature( + complaint *typesDKG.Complaint) (bool, error) { + if complaint.Round != complaint.PrivateShare.Round { + return false, nil + } + hash := hashDKGComplaint(complaint) + pubKey, err := crypto.SigToPub(hash, complaint.Signature) + if err != nil { + return false, err + } + if complaint.ProposerID != types.NewNodeID(pubKey) { + return false, nil + } + if !complaint.IsNack() { + return VerifyDKGPrivateShareSignature(&complaint.PrivateShare) + } + return true, nil +} + +func hashDKGPartialSignature(psig *typesDKG.PartialSignature) common.Hash { + binaryRound := make([]byte, 8) + binary.LittleEndian.PutUint64(binaryRound, psig.Round) + + return crypto.Keccak256Hash( + psig.ProposerID.Hash[:], + binaryRound, + psig.Hash[:], + psig.PartialSignature.Signature[:], + ) +} + +// VerifyDKGPartialSignatureSignature verifies the signature of +// typesDKG.PartialSignature. +func VerifyDKGPartialSignatureSignature( + psig *typesDKG.PartialSignature) (bool, error) { + hash := hashDKGPartialSignature(psig) + pubKey, err := crypto.SigToPub(hash, psig.Signature) + if err != nil { + return false, err + } + if psig.ProposerID != types.NewNodeID(pubKey) { + return false, nil + } + return true, nil +} + +func hashDKGMPKReady(ready *typesDKG.MPKReady) common.Hash { + binaryRound := make([]byte, 8) + binary.LittleEndian.PutUint64(binaryRound, ready.Round) + + return crypto.Keccak256Hash( + ready.ProposerID.Hash[:], + binaryRound, + ) +} + +// VerifyDKGMPKReadySignature verifies DKGMPKReady signature. +func VerifyDKGMPKReadySignature( + ready *typesDKG.MPKReady) (bool, error) { + hash := hashDKGMPKReady(ready) + pubKey, err := crypto.SigToPub(hash, ready.Signature) + if err != nil { + return false, err + } + if ready.ProposerID != types.NewNodeID(pubKey) { + return false, nil + } + return true, nil +} + +func hashDKGFinalize(final *typesDKG.Finalize) common.Hash { + binaryRound := make([]byte, 8) + binary.LittleEndian.PutUint64(binaryRound, final.Round) + + return crypto.Keccak256Hash( + final.ProposerID.Hash[:], + binaryRound, + ) +} + +// VerifyDKGFinalizeSignature verifies DKGFinalize signature. +func VerifyDKGFinalizeSignature( + final *typesDKG.Finalize) (bool, error) { + hash := hashDKGFinalize(final) + pubKey, err := crypto.SigToPub(hash, final.Signature) + if err != nil { + return false, err + } + if final.ProposerID != types.NewNodeID(pubKey) { + return false, nil + } + return true, nil +} diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/signer.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/signer.go new file mode 100644 index 000000000..47bea3f3d --- /dev/null +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/signer.go @@ -0,0 +1,126 @@ +// 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 utils + +import ( + "errors" + + "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 signer. +var ( + ErrInvalidProposerID = errors.New("invalid proposer id") + ErrIncorrectHash = errors.New("hash of block is incorrect") + ErrIncorrectSignature = errors.New("signature of block is incorrect") +) + +// Signer signs a segment of data. +type Signer struct { + prvKey crypto.PrivateKey + pubKey crypto.PublicKey + proposerID types.NodeID +} + +// NewSigner constructs an Signer instance. +func NewSigner(prvKey crypto.PrivateKey) (s *Signer) { + s = &Signer{ + prvKey: prvKey, + pubKey: prvKey.PublicKey(), + } + s.proposerID = types.NewNodeID(s.pubKey) + return +} + +// SignBlock signs a types.Block. +func (s *Signer) SignBlock(b *types.Block) (err error) { + b.ProposerID = s.proposerID + b.PayloadHash = crypto.Keccak256Hash(b.Payload) + if b.Hash, err = HashBlock(b); err != nil { + return + } + if b.Signature, err = s.prvKey.Sign(b.Hash); err != nil { + return + } + return +} + +// SignVote signs a types.Vote. +func (s *Signer) SignVote(v *types.Vote) (err error) { + v.ProposerID = s.proposerID + v.Signature, err = s.prvKey.Sign(hashVote(v)) + return +} + +// SignCRS signs CRS signature of types.Block. +func (s *Signer) SignCRS(b *types.Block, crs common.Hash) (err error) { + if b.ProposerID != s.proposerID { + err = ErrInvalidProposerID + return + } + b.CRSSignature, err = s.prvKey.Sign(hashCRS(b, crs)) + return +} + +// SignDKGComplaint signs a DKG complaint. +func (s *Signer) SignDKGComplaint(complaint *typesDKG.Complaint) (err error) { + complaint.ProposerID = s.proposerID + complaint.Signature, err = s.prvKey.Sign(hashDKGComplaint(complaint)) + return +} + +// SignDKGMasterPublicKey signs a DKG master public key. +func (s *Signer) SignDKGMasterPublicKey( + mpk *typesDKG.MasterPublicKey) (err error) { + mpk.ProposerID = s.proposerID + mpk.Signature, err = s.prvKey.Sign(hashDKGMasterPublicKey(mpk)) + return +} + +// SignDKGPrivateShare signs a DKG private share. +func (s *Signer) SignDKGPrivateShare( + prvShare *typesDKG.PrivateShare) (err error) { + prvShare.ProposerID = s.proposerID + prvShare.Signature, err = s.prvKey.Sign(hashDKGPrivateShare(prvShare)) + return +} + +// SignDKGPartialSignature signs a DKG partial signature. +func (s *Signer) SignDKGPartialSignature( + pSig *typesDKG.PartialSignature) (err error) { + pSig.ProposerID = s.proposerID + pSig.Signature, err = s.prvKey.Sign(hashDKGPartialSignature(pSig)) + return +} + +// SignDKGMPKReady signs a DKG ready message. +func (s *Signer) SignDKGMPKReady(ready *typesDKG.MPKReady) (err error) { + ready.ProposerID = s.proposerID + ready.Signature, err = s.prvKey.Sign(hashDKGMPKReady(ready)) + return +} + +// SignDKGFinalize signs a DKG finalize message. +func (s *Signer) SignDKGFinalize(final *typesDKG.Finalize) (err error) { + final.ProposerID = s.proposerID + final.Signature, err = s.prvKey.Sign(hashDKGFinalize(final)) + return +} diff --git a/vendor/vendor.json b/vendor/vendor.json index 56b294989..a1c2eb19f 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -105,14 +105,14 @@ { "checksumSHA1": "65L1yf+f0OCiLFniljqfRxVdsQA=", "path": "github.com/dexon-foundation/dexon-consensus/common", - "revision": "146ed32cf841151b826eafd7d6ade188c56865bf", - "revisionTime": "2018-12-20T09:26:30Z" + "revision": "dce509a13ef5873b9cae3c1cabdb97e219b6fb7d", + "revisionTime": "2018-12-24T02:29:31Z" }, { - "checksumSHA1": "DxtHhW/eYFodiPxgwu7opvIhJu0=", + "checksumSHA1": "GuNkyaDFHBDzOV5un2efH5CBG7k=", "path": "github.com/dexon-foundation/dexon-consensus/core", - "revision": "146ed32cf841151b826eafd7d6ade188c56865bf", - "revisionTime": "2018-12-20T09:26:30Z" + "revision": "dce509a13ef5873b9cae3c1cabdb97e219b6fb7d", + "revisionTime": "2018-12-24T02:29:31Z" }, { "checksumSHA1": "v4fKR7uhoyufi6hAVO44cFEb+tY=", @@ -123,50 +123,50 @@ { "checksumSHA1": "tQSbYCu5P00lUhKsx3IbBZCuSLY=", "path": "github.com/dexon-foundation/dexon-consensus/core/crypto", - "revision": "146ed32cf841151b826eafd7d6ade188c56865bf", - "revisionTime": "2018-12-20T09:26:30Z" + "revision": "dce509a13ef5873b9cae3c1cabdb97e219b6fb7d", + "revisionTime": "2018-12-24T02:29:31Z" }, { "checksumSHA1": "W2P7pkuJ+26BpJg03K4Y0nB5obI=", "path": "github.com/dexon-foundation/dexon-consensus/core/crypto/dkg", - "revision": "146ed32cf841151b826eafd7d6ade188c56865bf", - "revisionTime": "2018-12-20T09:26:30Z" + "revision": "dce509a13ef5873b9cae3c1cabdb97e219b6fb7d", + "revisionTime": "2018-12-24T02:29:31Z" }, { "checksumSHA1": "6Pf6caC8LTNCI7IflFmglKYnxYo=", "path": "github.com/dexon-foundation/dexon-consensus/core/crypto/ecdsa", - "revision": "146ed32cf841151b826eafd7d6ade188c56865bf", - "revisionTime": "2018-12-20T09:26:30Z" + "revision": "dce509a13ef5873b9cae3c1cabdb97e219b6fb7d", + "revisionTime": "2018-12-24T02:29:31Z" }, { "checksumSHA1": "PJXR1OuWwVVYrdJMK3skPr1/8ls=", "path": "github.com/dexon-foundation/dexon-consensus/core/db", - "revision": "146ed32cf841151b826eafd7d6ade188c56865bf", - "revisionTime": "2018-12-20T09:26:30Z" + "revision": "dce509a13ef5873b9cae3c1cabdb97e219b6fb7d", + "revisionTime": "2018-12-24T02:29:31Z" }, { - "checksumSHA1": "VRDwO2+FQkeZFeuLfRFS9FUpdCc=", + "checksumSHA1": "ZQnoWpMJTicqu9UMKi+CPd5r3so=", "path": "github.com/dexon-foundation/dexon-consensus/core/syncer", - "revision": "146ed32cf841151b826eafd7d6ade188c56865bf", - "revisionTime": "2018-12-20T09:26:30Z" + "revision": "dce509a13ef5873b9cae3c1cabdb97e219b6fb7d", + "revisionTime": "2018-12-24T02:29:31Z" }, { "checksumSHA1": "Z079qQV+aQV9A3kSJ0LbFjx5VO4=", "path": "github.com/dexon-foundation/dexon-consensus/core/types", - "revision": "146ed32cf841151b826eafd7d6ade188c56865bf", - "revisionTime": "2018-12-20T09:26:30Z" + "revision": "dce509a13ef5873b9cae3c1cabdb97e219b6fb7d", + "revisionTime": "2018-12-24T02:29:31Z" }, { "checksumSHA1": "sY+2eiOoWvsNMvuPl9qQ+rlT9sA=", "path": "github.com/dexon-foundation/dexon-consensus/core/types/dkg", - "revision": "146ed32cf841151b826eafd7d6ade188c56865bf", - "revisionTime": "2018-12-20T09:26:30Z" + "revision": "dce509a13ef5873b9cae3c1cabdb97e219b6fb7d", + "revisionTime": "2018-12-24T02:29:31Z" }, { - "checksumSHA1": "WEtKiyBYr0oPUSF+smv1A2LPBuI=", + "checksumSHA1": "0JFlVFny0IyANnlelQDl8ot16wU=", "path": "github.com/dexon-foundation/dexon-consensus/core/utils", - "revision": "146ed32cf841151b826eafd7d6ade188c56865bf", - "revisionTime": "2018-12-20T09:26:30Z" + "revision": "dce509a13ef5873b9cae3c1cabdb97e219b6fb7d", + "revisionTime": "2018-12-24T02:29:31Z" }, { "checksumSHA1": "TAkwduKZqLyimyTPPWIllZWYFuE=", -- cgit v1.2.3