aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/dexon-foundation/dexon-consensus
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/dexon-foundation/dexon-consensus')
-rw-r--r--vendor/github.com/dexon-foundation/dexon-consensus/core/configuration-chain.go109
-rw-r--r--vendor/github.com/dexon-foundation/dexon-consensus/core/consensus.go25
-rw-r--r--vendor/github.com/dexon-foundation/dexon-consensus/core/crypto/dkg/utils.go21
-rw-r--r--vendor/github.com/dexon-foundation/dexon-consensus/core/db/interfaces.go23
-rw-r--r--vendor/github.com/dexon-foundation/dexon-consensus/core/db/level-db.go176
-rw-r--r--vendor/github.com/dexon-foundation/dexon-consensus/core/db/memory.go92
-rw-r--r--vendor/github.com/dexon-foundation/dexon-consensus/core/dkg-tsig-protocol.go13
-rw-r--r--vendor/github.com/dexon-foundation/dexon-consensus/core/utils.go4
8 files changed, 383 insertions, 80 deletions
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 364f2c75c..2b3a859ed 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
@@ -24,6 +24,7 @@ import (
"github.com/dexon-foundation/dexon-consensus/common"
"github.com/dexon-foundation/dexon-consensus/core/crypto"
+ "github.com/dexon-foundation/dexon-consensus/core/db"
"github.com/dexon-foundation/dexon-consensus/core/types"
typesDKG "github.com/dexon-foundation/dexon-consensus/core/types/dkg"
"github.com/dexon-foundation/dexon-consensus/core/utils"
@@ -53,6 +54,7 @@ type configurationChain struct {
tsigTouched map[common.Hash]struct{}
tsigReady *sync.Cond
cache *utils.NodeSetCache
+ db db.Database
dkgSet map[types.NodeID]struct{}
mpkReady bool
pendingPrvShare map[types.NodeID]*typesDKG.PrivateShare
@@ -66,6 +68,7 @@ func newConfigurationChain(
recv dkgReceiver,
gov Governance,
cache *utils.NodeSetCache,
+ dbInst db.Database,
logger common.Logger) *configurationChain {
return &configurationChain{
ID: ID,
@@ -78,6 +81,7 @@ func newConfigurationChain(
tsigTouched: make(map[common.Hash]struct{}),
tsigReady: sync.NewCond(&sync.Mutex{}),
cache: cache,
+ db: dbInst,
pendingPsig: make(map[common.Hash][]*typesDKG.PartialSignature),
}
}
@@ -104,6 +108,10 @@ func (cc *configurationChain) registerDKG(round uint64, threshold int) {
}
func (cc *configurationChain) runDKG(round uint64) error {
+ // Check if corresponding DKG signer is ready.
+ if _, _, err := cc.getDKGInfo(round); err == nil {
+ return nil
+ }
cc.dkgLock.Lock()
defer cc.dkgLock.Unlock()
if cc.dkg == nil || cc.dkg.round != round {
@@ -113,20 +121,11 @@ func (cc *configurationChain) runDKG(round uint64) error {
}
return ErrDKGNotRegistered
}
- if func() bool {
- cc.dkgResult.RLock()
- defer cc.dkgResult.RUnlock()
- _, exist := cc.gpk[round]
- return exist
- }() {
- return nil
- }
cc.logger.Debug("Calling Governance.IsDKGFinal", "round", round)
if cc.gov.IsDKGFinal(round) {
cc.logger.Warn("DKG already final", "round", round)
return nil
}
-
ticker := newTicker(cc.gov, round, TickerDKG)
cc.dkgLock.Unlock()
<-ticker.Tick()
@@ -153,7 +152,8 @@ func (cc *configurationChain) runDKG(round uint64) error {
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))
+ complaints := cc.gov.DKGComplaints(round)
+ cc.dkg.processNackComplaints(complaints)
cc.dkgLock.Unlock()
<-ticker.Tick()
cc.dkgLock.Lock()
@@ -163,8 +163,7 @@ func (cc *configurationChain) runDKG(round uint64) error {
<-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))
+ cc.dkg.enforceNackComplaints(complaints)
// Enforce complaint is done in `processPrivateShare`.
// Phase 8(T = 5λ): DKG finalize.
cc.dkgLock.Unlock()
@@ -209,6 +208,10 @@ func (cc *configurationChain) runDKG(round uint64) error {
if err != nil {
return err
}
+ // Save private shares to DB.
+ if err = cc.db.PutDKGPrivateKey(round, *signer.privateKey); err != nil {
+ return err
+ }
cc.dkgResult.Lock()
defer cc.dkgResult.Unlock()
cc.dkgSigner[round] = signer
@@ -220,23 +223,74 @@ func (cc *configurationChain) isDKGReady(round uint64) bool {
if !cc.gov.IsDKGFinal(round) {
return false
}
- return func() bool {
+ _, _, err := cc.getDKGInfo(round)
+ return err == nil
+}
+
+func (cc *configurationChain) getDKGInfo(
+ round uint64) (*DKGGroupPublicKey, *dkgShareSecret, error) {
+ getFromCache := func() (*DKGGroupPublicKey, *dkgShareSecret) {
cc.dkgResult.RLock()
defer cc.dkgResult.RUnlock()
- _, exist := cc.gpk[round]
- return exist
- }()
+ gpk := cc.gpk[round]
+ signer := cc.dkgSigner[round]
+ return gpk, signer
+ }
+ gpk, signer := getFromCache()
+ if gpk == nil || signer == nil {
+ if err := cc.recoverDKGInfo(round); err != nil {
+ return nil, nil, err
+ }
+ gpk, signer = getFromCache()
+ }
+ if gpk == nil || signer == nil {
+ return nil, nil, ErrDKGNotReady
+ }
+ return gpk, 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 {
+ return nil
+ }
+ if !cc.gov.IsDKGFinal(round) {
+ return ErrDKGNotReady
+ }
+
+ threshold := getDKGThreshold(cc.gov.Configuration(round))
+ // Restore group public key.
+ gpk, err := NewDKGGroupPublicKey(round,
+ cc.gov.DKGMasterPublicKeys(round),
+ cc.gov.DKGComplaints(round),
+ threshold)
+ if err != nil {
+ return err
+ }
+ // Restore DKG share secret, this segment of code is copied from
+ // dkgProtocol.recoverShareSecret.
+ if len(gpk.qualifyIDs) < threshold {
+ return ErrNotReachThreshold
+ }
+ // Check if we have private shares in DB.
+ prvKey, err := cc.db.GetDKGPrivateKey(round)
+ if err != nil {
+ return err
+ }
+ cc.gpk[round] = gpk
+ cc.dkgSigner[round] = &dkgShareSecret{
+ privateKey: &prvKey,
+ }
+ 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 {
+ _, signer, _ := cc.getDKGInfo(round)
+ if signer == nil {
return nil, ErrDKGNotReady
}
return &typesDKG.PartialSignature{
@@ -264,13 +318,8 @@ func (cc *configurationChain) untouchTSigHash(hash common.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 {
+ gpk, _, _ := cc.getDKGInfo(round)
+ if gpk == nil {
return crypto.Signature{}, ErrDKGNotReady
}
cc.tsigReady.L.Lock()
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 a6d80371d..5beaf546a 100644
--- a/vendor/github.com/dexon-foundation/dexon-consensus/core/consensus.go
+++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/consensus.go
@@ -424,6 +424,7 @@ func NewConsensus(
recv,
gov,
nodeSetCache,
+ db,
logger)
recv.cfgModule = cfgModule
// Construct Consensus instance.
@@ -490,6 +491,7 @@ func NewConsensusFromSyncer(
recv,
gov,
nodeSetCache,
+ db,
logger)
recv.cfgModule = cfgModule
// Setup Consensus instance.
@@ -576,7 +578,7 @@ func (con *Consensus) prepare(initBlock *types.Block) error {
}
if _, exist := dkgSet[con.ID]; exist {
con.logger.Info("Selected as DKG set", "round", initRound)
- con.cfgModule.registerDKG(initRound, int(initConfig.DKGSetSize)/3+1)
+ con.cfgModule.registerDKG(initRound, getDKGThreshold(initConfig))
con.event.RegisterTime(con.dMoment.Add(initConfig.RoundInterval/4),
func(time.Time) {
con.runDKG(initRound, initConfig)
@@ -742,8 +744,7 @@ func (con *Consensus) initialRound(
return
}
con.logger.Info("Selected as DKG set", "round", nextRound)
- con.cfgModule.registerDKG(
- nextRound, int(config.DKGSetSize/3)+1)
+ con.cfgModule.registerDKG(nextRound, getDKGThreshold(config))
con.event.RegisterTime(
startTime.Add(config.RoundInterval*2/3),
func(time.Time) {
@@ -1003,6 +1004,14 @@ func (con *Consensus) preProcessBlock(b *types.Block) (err error) {
// deliverBlock deliver a block to application layer.
func (con *Consensus) deliverBlock(b *types.Block) {
+ if err := con.db.UpdateBlock(*b); err != nil {
+ panic(err)
+ }
+ if err := con.db.PutCompactionChainTipInfo(
+ b.Hash, b.Finalization.Height); err != nil {
+ panic(err)
+ }
+ con.cfgModule.untouchTSigHash(b.Hash)
con.logger.Debug("Calling Application.BlockDelivered", "block", b)
con.app.BlockDelivered(b.Hash, b.Position, b.Finalization.Clone())
if b.Position.Round == con.roundToNotify {
@@ -1032,6 +1041,9 @@ func (con *Consensus) deliverBlock(b *types.Block) {
con.roundToNotify, b.Finalization.Height)
con.roundToNotify++
}
+ if con.debugApp != nil {
+ con.debugApp.BlockReady(b.Hash)
+ }
}
// processBlock is the entry point to submit one block to a Consensus instance.
@@ -1072,14 +1084,7 @@ func (con *Consensus) processBlock(block *types.Block) (err error) {
"delivered", con.ccModule.lastDeliveredBlock(),
"pending", con.ccModule.lastPendingBlock())
for _, b := range deliveredBlocks {
- if err = con.db.UpdateBlock(*b); err != nil {
- panic(err)
- }
- con.cfgModule.untouchTSigHash(b.Hash)
con.deliverBlock(b)
- if con.debugApp != nil {
- con.debugApp.BlockReady(b.Hash)
- }
}
if err = con.lattice.PurgeBlocks(deliveredBlocks); err != nil {
return
diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/crypto/dkg/utils.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/crypto/dkg/utils.go
index fa4ad9f05..9e470f0cf 100644
--- a/vendor/github.com/dexon-foundation/dexon-consensus/core/crypto/dkg/utils.go
+++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/crypto/dkg/utils.go
@@ -18,7 +18,9 @@
package dkg
import (
+ "encoding/binary"
"fmt"
+ "math/rand"
"github.com/dexon-foundation/bls/ffi/go/bls"
@@ -69,3 +71,22 @@ func RecoverGroupPublicKey(pubShares []*PublicKeyShares) *PublicKey {
}
return pub
}
+
+// NewRandomPrivateKeyShares constructs a private key shares randomly.
+func NewRandomPrivateKeyShares() *PrivateKeyShares {
+ // Generate IDs.
+ rndIDs := make(IDs, 0, 10)
+ for i := range rndIDs {
+ id := make([]byte, 8)
+ binary.LittleEndian.PutUint64(id, rand.Uint64())
+ rndIDs[i] = NewID(id)
+ }
+ prvShares := NewEmptyPrivateKeyShares()
+ prvShares.SetParticipants(rndIDs)
+ for _, id := range rndIDs {
+ if err := prvShares.AddShare(id, NewPrivateKey()); err != nil {
+ panic(err)
+ }
+ }
+ return prvShares
+}
diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/db/interfaces.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/db/interfaces.go
index 5e13dc604..ebbbbd475 100644
--- a/vendor/github.com/dexon-foundation/dexon-consensus/core/db/interfaces.go
+++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/db/interfaces.go
@@ -22,6 +22,7 @@ import (
"fmt"
"github.com/dexon-foundation/dexon-consensus/common"
+ "github.com/dexon-foundation/dexon-consensus/core/crypto/dkg"
"github.com/dexon-foundation/dexon-consensus/core/types"
)
@@ -38,6 +39,17 @@ var (
ErrClosed = fmt.Errorf("db closed")
// ErrNotImplemented is the error that some interface is not implemented.
ErrNotImplemented = fmt.Errorf("not implemented")
+ // ErrInvalidCompactionChainTipHeight means the newly updated height of
+ // the tip of compaction chain is invalid, usually means it's smaller than
+ // current cached one.
+ ErrInvalidCompactionChainTipHeight = fmt.Errorf(
+ "invalid compaction chain tip height")
+ // ErrDKGPrivateKeyExists raised when attempting to save DKG private key
+ // that already saved.
+ ErrDKGPrivateKeyExists = errors.New("dkg private key exists")
+ // ErrDKGPrivateKeyDoesNotExist raised when the DKG private key of the
+ // requested round does not exists.
+ ErrDKGPrivateKeyDoesNotExist = errors.New("dkg private key does not exists")
)
// Database is the interface for a Database.
@@ -55,12 +67,23 @@ type Reader interface {
HasBlock(hash common.Hash) bool
GetBlock(hash common.Hash) (types.Block, error)
GetAllBlocks() (BlockIterator, error)
+
+ // GetCompactionChainTipInfo returns the block hash and finalization height
+ // of the tip block of compaction chain. Empty hash and zero height means
+ // the compaction chain is empty.
+ GetCompactionChainTipInfo() (common.Hash, uint64)
+
+ // DKG Private Key related methods.
+ HasDKGPrivateKey(round uint64) (bool, error)
+ GetDKGPrivateKey(round uint64) (dkg.PrivateKey, error)
}
// Writer defines the interface for writing blocks into DB.
type Writer interface {
UpdateBlock(block types.Block) error
PutBlock(block types.Block) error
+ PutCompactionChainTipInfo(common.Hash, uint64) error
+ PutDKGPrivateKey(uint64, dkg.PrivateKey) error
}
// BlockIterator defines an iterator on blocks hold
diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/db/level-db.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/db/level-db.go
index 6983d3a5e..3b5994b26 100644
--- a/vendor/github.com/dexon-foundation/dexon-consensus/core/db/level-db.go
+++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/db/level-db.go
@@ -18,14 +18,27 @@
package db
import (
- "encoding/json"
+ "encoding/binary"
"github.com/syndtr/goleveldb/leveldb"
"github.com/dexon-foundation/dexon-consensus/common"
+ "github.com/dexon-foundation/dexon-consensus/core/crypto/dkg"
"github.com/dexon-foundation/dexon-consensus/core/types"
+ "github.com/dexon-foundation/dexon/rlp"
)
+var (
+ blockKeyPrefix = []byte("b-")
+ compactionChainTipInfoKey = []byte("cc-tip")
+ dkgPrivateKeyKeyPrefix = []byte("dkg-prvs")
+)
+
+type compactionChainTipInfo struct {
+ Height uint64 `json:"height"`
+ Hash common.Hash `json:"hash"`
+}
+
// LevelDBBackedDB is a leveldb backed DB implementation.
type LevelDBBackedDB struct {
db *leveldb.DB
@@ -50,7 +63,7 @@ func (lvl *LevelDBBackedDB) Close() error {
// HasBlock implements the Reader.Has method.
func (lvl *LevelDBBackedDB) HasBlock(hash common.Hash) bool {
- exists, err := lvl.db.Has([]byte(hash[:]), nil)
+ exists, err := lvl.internalHasBlock(lvl.getBlockKey(hash))
if err != nil {
// TODO(missionliao): Modify the interface to return error.
panic(err)
@@ -58,18 +71,25 @@ func (lvl *LevelDBBackedDB) HasBlock(hash common.Hash) bool {
return exists
}
+func (lvl *LevelDBBackedDB) internalHasBlock(key []byte) (bool, error) {
+ exists, err := lvl.db.Has(key, nil)
+ if err != nil {
+ return false, err
+ }
+ return exists, nil
+}
+
// GetBlock implements the Reader.GetBlock method.
func (lvl *LevelDBBackedDB) GetBlock(
hash common.Hash) (block types.Block, err error) {
-
- queried, err := lvl.db.Get([]byte(hash[:]), nil)
+ queried, err := lvl.db.Get(lvl.getBlockKey(hash), nil)
if err != nil {
if err == leveldb.ErrNotFound {
err = ErrBlockDoesNotExist
}
return
}
- err = json.Unmarshal(queried, &block)
+ err = rlp.DecodeBytes(queried, &block)
if err != nil {
return
}
@@ -80,20 +100,20 @@ func (lvl *LevelDBBackedDB) GetBlock(
func (lvl *LevelDBBackedDB) UpdateBlock(block types.Block) (err error) {
// NOTE: we didn't handle changes of block hash (and it
// should not happen).
- marshaled, err := json.Marshal(&block)
+ marshaled, err := rlp.EncodeToBytes(&block)
if err != nil {
return
}
-
- if !lvl.HasBlock(block.Hash) {
+ blockKey := lvl.getBlockKey(block.Hash)
+ exists, err := lvl.internalHasBlock(blockKey)
+ if err != nil {
+ return
+ }
+ if !exists {
err = ErrBlockDoesNotExist
return
}
- err = lvl.db.Put(
- []byte(block.Hash[:]),
- marshaled,
- nil)
- if err != nil {
+ if err = lvl.db.Put(blockKey, marshaled, nil); err != nil {
return
}
return
@@ -101,19 +121,20 @@ func (lvl *LevelDBBackedDB) UpdateBlock(block types.Block) (err error) {
// PutBlock implements the Writer.PutBlock method.
func (lvl *LevelDBBackedDB) PutBlock(block types.Block) (err error) {
- marshaled, err := json.Marshal(&block)
+ marshaled, err := rlp.EncodeToBytes(&block)
if err != nil {
return
}
- if lvl.HasBlock(block.Hash) {
+ blockKey := lvl.getBlockKey(block.Hash)
+ exists, err := lvl.internalHasBlock(blockKey)
+ if err != nil {
+ return
+ }
+ if exists {
err = ErrBlockExists
return
}
- err = lvl.db.Put(
- []byte(block.Hash[:]),
- marshaled,
- nil)
- if err != nil {
+ if err = lvl.db.Put(blockKey, marshaled, nil); err != nil {
return
}
return
@@ -125,3 +146,118 @@ func (lvl *LevelDBBackedDB) GetAllBlocks() (BlockIterator, error) {
// TODO (mission): Implement this part via goleveldb's iterator.
return nil, ErrNotImplemented
}
+
+// PutCompactionChainTipInfo saves tip of compaction chain into the database.
+func (lvl *LevelDBBackedDB) PutCompactionChainTipInfo(
+ blockHash common.Hash, height uint64) error {
+ marshaled, err := rlp.EncodeToBytes(&compactionChainTipInfo{
+ Hash: blockHash,
+ Height: height,
+ })
+ if err != nil {
+ return err
+ }
+ // Check current cached tip info to make sure the one to be updated is
+ // valid.
+ info, err := lvl.internalGetCompactionChainTipInfo()
+ if err != nil {
+ return err
+ }
+ if info.Height >= height {
+ return ErrInvalidCompactionChainTipHeight
+ }
+ if err = lvl.db.Put(compactionChainTipInfoKey, marshaled, nil); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (lvl *LevelDBBackedDB) internalGetCompactionChainTipInfo() (
+ info compactionChainTipInfo, err error) {
+ queried, err := lvl.db.Get(compactionChainTipInfoKey, nil)
+ if err != nil {
+ if err == leveldb.ErrNotFound {
+ err = nil
+ }
+ return
+ }
+ if err = rlp.DecodeBytes(queried, &info); err != nil {
+ return
+ }
+ return
+}
+
+// GetCompactionChainTipInfo get the tip info of compaction chain into the
+// database.
+func (lvl *LevelDBBackedDB) GetCompactionChainTipInfo() (
+ hash common.Hash, height uint64) {
+ info, err := lvl.internalGetCompactionChainTipInfo()
+ if err != nil {
+ panic(err)
+ }
+ hash, height = info.Hash, info.Height
+ return
+}
+
+// HasDKGPrivateKey check existence of DKG private key of one round.
+func (lvl *LevelDBBackedDB) HasDKGPrivateKey(round uint64) (bool, error) {
+ exists, err := lvl.db.Has(lvl.getDKGPrivateKeyKey(round), nil)
+ if err != nil {
+ return false, err
+ }
+ return exists, nil
+}
+
+// GetDKGPrivateKey get DKG private key of one round.
+func (lvl *LevelDBBackedDB) GetDKGPrivateKey(round uint64) (
+ prv dkg.PrivateKey, err error) {
+ queried, err := lvl.db.Get(lvl.getDKGPrivateKeyKey(round), nil)
+ if err != nil {
+ if err == leveldb.ErrNotFound {
+ err = ErrDKGPrivateKeyDoesNotExist
+ }
+ return
+ }
+ if err = rlp.DecodeBytes(queried, &prv); err != nil {
+ return
+ }
+ return
+}
+
+// PutDKGPrivateKey save DKG private key of one round.
+func (lvl *LevelDBBackedDB) PutDKGPrivateKey(
+ round uint64, prv dkg.PrivateKey) error {
+ // Check existence.
+ exists, err := lvl.HasDKGPrivateKey(round)
+ if err != nil {
+ return err
+ }
+ if exists {
+ return ErrDKGPrivateKeyExists
+ }
+ marshaled, err := rlp.EncodeToBytes(&prv)
+ if err != nil {
+ return err
+ }
+ if err := lvl.db.Put(
+ lvl.getDKGPrivateKeyKey(round), marshaled, nil); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (lvl *LevelDBBackedDB) getBlockKey(hash common.Hash) (ret []byte) {
+ ret = make([]byte, len(blockKeyPrefix)+len(hash[:]))
+ copy(ret, blockKeyPrefix)
+ copy(ret[len(blockKeyPrefix):], hash[:])
+ return
+}
+
+func (lvl *LevelDBBackedDB) getDKGPrivateKeyKey(
+ round uint64) (ret []byte) {
+ ret = make([]byte, len(dkgPrivateKeyKeyPrefix)+8)
+ copy(ret, dkgPrivateKeyKeyPrefix)
+ binary.LittleEndian.PutUint64(
+ ret[len(dkgPrivateKeyKeyPrefix):], round)
+ return
+}
diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/db/memory.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/db/memory.go
index 4246e4fe1..7393de9db 100644
--- a/vendor/github.com/dexon-foundation/dexon-consensus/core/db/memory.go
+++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/db/memory.go
@@ -24,6 +24,7 @@ import (
"sync"
"github.com/dexon-foundation/dexon-consensus/common"
+ "github.com/dexon-foundation/dexon-consensus/core/crypto/dkg"
"github.com/dexon-foundation/dexon-consensus/core/types"
)
@@ -41,10 +42,15 @@ func (seq *blockSeqIterator) NextBlock() (types.Block, error) {
// MemBackedDB is a memory backed DB implementation.
type MemBackedDB struct {
- blocksMutex sync.RWMutex
- blockHashSequence common.Hashes
- blocksByHash map[common.Hash]*types.Block
- persistantFilePath string
+ blocksLock sync.RWMutex
+ blockHashSequence common.Hashes
+ blocksByHash map[common.Hash]*types.Block
+ compactionChainTipLock sync.RWMutex
+ compactionChainTipHash common.Hash
+ compactionChainTipHeight uint64
+ dkgPrivateKeysLock sync.RWMutex
+ dkgPrivateKeys map[uint64]*dkg.PrivateKey
+ persistantFilePath string
}
// NewMemBackedDB initialize a memory-backed database.
@@ -53,6 +59,7 @@ func NewMemBackedDB(persistantFilePath ...string) (
dbInst = &MemBackedDB{
blockHashSequence: common.Hashes{},
blocksByHash: make(map[common.Hash]*types.Block),
+ dkgPrivateKeys: make(map[uint64]*dkg.PrivateKey),
}
if len(persistantFilePath) == 0 || len(persistantFilePath[0]) == 0 {
return
@@ -87,8 +94,8 @@ func NewMemBackedDB(persistantFilePath ...string) (
// HasBlock returns wheter or not the DB has a block identified with the hash.
func (m *MemBackedDB) HasBlock(hash common.Hash) bool {
- m.blocksMutex.RLock()
- defer m.blocksMutex.RUnlock()
+ m.blocksLock.RLock()
+ defer m.blocksLock.RUnlock()
_, ok := m.blocksByHash[hash]
return ok
@@ -96,8 +103,8 @@ func (m *MemBackedDB) HasBlock(hash common.Hash) bool {
// GetBlock returns a block given a hash.
func (m *MemBackedDB) GetBlock(hash common.Hash) (types.Block, error) {
- m.blocksMutex.RLock()
- defer m.blocksMutex.RUnlock()
+ m.blocksLock.RLock()
+ defer m.blocksLock.RUnlock()
return m.internalGetBlock(hash)
}
@@ -116,8 +123,8 @@ func (m *MemBackedDB) PutBlock(block types.Block) error {
return ErrBlockExists
}
- m.blocksMutex.Lock()
- defer m.blocksMutex.Unlock()
+ m.blocksLock.Lock()
+ defer m.blocksLock.Unlock()
m.blockHashSequence = append(m.blockHashSequence, block.Hash)
m.blocksByHash[block.Hash] = &block
@@ -130,13 +137,66 @@ func (m *MemBackedDB) UpdateBlock(block types.Block) error {
return ErrBlockDoesNotExist
}
- m.blocksMutex.Lock()
- defer m.blocksMutex.Unlock()
+ m.blocksLock.Lock()
+ defer m.blocksLock.Unlock()
m.blocksByHash[block.Hash] = &block
return nil
}
+// PutCompactionChainTipInfo saves tip of compaction chain into the database.
+func (m *MemBackedDB) PutCompactionChainTipInfo(
+ blockHash common.Hash, height uint64) error {
+ m.compactionChainTipLock.Lock()
+ defer m.compactionChainTipLock.Unlock()
+ if m.compactionChainTipHeight >= height {
+ return ErrInvalidCompactionChainTipHeight
+ }
+ m.compactionChainTipHeight = height
+ m.compactionChainTipHash = blockHash
+ return nil
+}
+
+// GetCompactionChainTipInfo get the tip info of compaction chain into the
+// database.
+func (m *MemBackedDB) GetCompactionChainTipInfo() (
+ hash common.Hash, height uint64) {
+ m.compactionChainTipLock.RLock()
+ defer m.compactionChainTipLock.RUnlock()
+ return m.compactionChainTipHash, m.compactionChainTipHeight
+}
+
+// HasDKGPrivateKey check existence of DKG private key of one round.
+func (m *MemBackedDB) HasDKGPrivateKey(round uint64) (bool, error) {
+ m.dkgPrivateKeysLock.RLock()
+ defer m.dkgPrivateKeysLock.RUnlock()
+ _, exists := m.dkgPrivateKeys[round]
+ return exists, nil
+}
+
+// GetDKGPrivateKey get DKG private key of one round.
+func (m *MemBackedDB) GetDKGPrivateKey(round uint64) (
+ dkg.PrivateKey, error) {
+ m.dkgPrivateKeysLock.RLock()
+ defer m.dkgPrivateKeysLock.RUnlock()
+ if prv, exists := m.dkgPrivateKeys[round]; exists {
+ return *prv, nil
+ }
+ return dkg.PrivateKey{}, ErrDKGPrivateKeyDoesNotExist
+}
+
+// PutDKGPrivateKey save DKG private key of one round.
+func (m *MemBackedDB) PutDKGPrivateKey(
+ round uint64, prv dkg.PrivateKey) error {
+ m.dkgPrivateKeysLock.Lock()
+ defer m.dkgPrivateKeysLock.Unlock()
+ if _, exists := m.dkgPrivateKeys[round]; exists {
+ return ErrDKGPrivateKeyExists
+ }
+ m.dkgPrivateKeys[round] = &prv
+ return nil
+}
+
// Close implement Closer interface, which would release allocated resource.
func (m *MemBackedDB) Close() (err error) {
// Save internal state to a pretty-print json file. It's a temporary way
@@ -145,8 +205,8 @@ func (m *MemBackedDB) Close() (err error) {
return
}
- m.blocksMutex.RLock()
- defer m.blocksMutex.RUnlock()
+ m.blocksLock.RLock()
+ defer m.blocksLock.RUnlock()
toDump := struct {
Sequence common.Hashes
@@ -167,8 +227,8 @@ func (m *MemBackedDB) Close() (err error) {
}
func (m *MemBackedDB) getBlockByIndex(idx int) (types.Block, error) {
- m.blocksMutex.RLock()
- defer m.blocksMutex.RUnlock()
+ m.blocksLock.RLock()
+ defer m.blocksLock.RUnlock()
if idx >= len(m.blockHashSequence) {
return types.Block{}, ErrIterationFinished
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 6645ecbae..8e03cbbda 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
@@ -378,16 +378,21 @@ func NewDKGGroupPublicKey(
// Calculate qualify members.
disqualifyIDs := map[types.NodeID]struct{}{}
- complaintsByID := map[types.NodeID]int{}
+ complaintsByID := map[types.NodeID]map[types.NodeID]struct{}{}
for _, complaint := range complaints {
if complaint.IsNack() {
- complaintsByID[complaint.PrivateShare.ProposerID]++
+ 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, num := range complaintsByID {
- if num > threshold {
+ for nID, complaints := range complaintsByID {
+ if len(complaints) > threshold {
disqualifyIDs[nID] = struct{}{}
}
}
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 2ef243757..671d68018 100644
--- a/vendor/github.com/dexon-foundation/dexon-consensus/core/utils.go
+++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils.go
@@ -231,3 +231,7 @@ func isCircleCI() bool {
func isTravisCI() bool {
return isCI() && os.Getenv("TRAVIS") == "true"
}
+
+func getDKGThreshold(config *types.Config) int {
+ return int(config.DKGSetSize/3) + 1
+}