aboutsummaryrefslogtreecommitdiffstats
path: root/core/db
diff options
context:
space:
mode:
Diffstat (limited to 'core/db')
-rw-r--r--core/db/interfaces.go12
-rw-r--r--core/db/level-db.go60
-rw-r--r--core/db/level-db_test.go31
-rw-r--r--core/db/memory.go35
-rw-r--r--core/db/memory_test.go25
5 files changed, 163 insertions, 0 deletions
diff --git a/core/db/interfaces.go b/core/db/interfaces.go
index 3ffba4a..ebbbbd4 100644
--- a/core/db/interfaces.go
+++ b/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"
)
@@ -43,6 +44,12 @@ var (
// 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.
@@ -65,6 +72,10 @@ type Reader interface {
// 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.
@@ -72,6 +83,7 @@ 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/core/db/level-db.go b/core/db/level-db.go
index 238c38e..3b5994b 100644
--- a/core/db/level-db.go
+++ b/core/db/level-db.go
@@ -18,9 +18,12 @@
package db
import (
+ "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"
)
@@ -28,6 +31,7 @@ import (
var (
blockKeyPrefix = []byte("b-")
compactionChainTipInfoKey = []byte("cc-tip")
+ dkgPrivateKeyKeyPrefix = []byte("dkg-prvs")
)
type compactionChainTipInfo struct {
@@ -195,9 +199,65 @@ func (lvl *LevelDBBackedDB) GetCompactionChainTipInfo() (
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/core/db/level-db_test.go b/core/db/level-db_test.go
index 69c8f07..cf56b87 100644
--- a/core/db/level-db_test.go
+++ b/core/db/level-db_test.go
@@ -18,6 +18,7 @@
package db
import (
+ "bytes"
"fmt"
"testing"
"time"
@@ -27,6 +28,7 @@ import (
"github.com/stretchr/testify/suite"
"github.com/dexon-foundation/dexon-consensus/common"
+ "github.com/dexon-foundation/dexon-consensus/core/crypto/dkg"
"github.com/dexon-foundation/dexon-consensus/core/types"
)
@@ -149,6 +151,35 @@ func (s *LevelDBTestSuite) TestCompactionChainTipInfo() {
s.Require().IsType(err, ErrInvalidCompactionChainTipHeight)
}
+func (s *LevelDBTestSuite) TestDKGPrivateKey() {
+ dbName := fmt.Sprintf("test-db-%v-dkg-prv.db", time.Now().UTC())
+ dbInst, err := NewLevelDBBackedDB(dbName)
+ s.Require().NoError(err)
+ defer func(dbName string) {
+ err = dbInst.Close()
+ s.NoError(err)
+ err = os.RemoveAll(dbName)
+ s.NoError(err)
+ }(dbName)
+ p := dkg.NewPrivateKey()
+ // Check existence.
+ exists, err := dbInst.HasDKGPrivateKey(1)
+ s.Require().NoError(err)
+ s.Require().False(exists)
+ // We should be unable to get it, too.
+ _, err = dbInst.GetDKGPrivateKey(1)
+ s.Require().IsType(err, ErrDKGPrivateKeyDoesNotExist)
+ // Put it.
+ s.Require().NoError(dbInst.PutDKGPrivateKey(1, *p))
+ // Put it again, should not success.
+ err = dbInst.PutDKGPrivateKey(1, *p)
+ s.Require().IsType(err, ErrDKGPrivateKeyExists)
+ // Get it back.
+ tmpPrv, err := dbInst.GetDKGPrivateKey(1)
+ s.Require().NoError(err)
+ s.Require().Equal(bytes.Compare(p.Bytes(), tmpPrv.Bytes()), 0)
+}
+
func TestLevelDB(t *testing.T) {
suite.Run(t, new(LevelDBTestSuite))
}
diff --git a/core/db/memory.go b/core/db/memory.go
index 568c64b..7393de9 100644
--- a/core/db/memory.go
+++ b/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"
)
@@ -47,6 +48,8 @@ type MemBackedDB struct {
compactionChainTipLock sync.RWMutex
compactionChainTipHash common.Hash
compactionChainTipHeight uint64
+ dkgPrivateKeysLock sync.RWMutex
+ dkgPrivateKeys map[uint64]*dkg.PrivateKey
persistantFilePath string
}
@@ -56,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
@@ -162,6 +166,37 @@ func (m *MemBackedDB) GetCompactionChainTipInfo() (
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
diff --git a/core/db/memory_test.go b/core/db/memory_test.go
index 7d18c3a..09f74bb 100644
--- a/core/db/memory_test.go
+++ b/core/db/memory_test.go
@@ -18,10 +18,12 @@
package db
import (
+ "bytes"
"os"
"testing"
"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/stretchr/testify/suite"
)
@@ -145,6 +147,29 @@ func (s *MemBackedDBTestSuite) TestCompactionChainTipInfo() {
s.Require().IsType(err, ErrInvalidCompactionChainTipHeight)
}
+func (s *MemBackedDBTestSuite) TestDKGPrivateKey() {
+ dbInst, err := NewMemBackedDB()
+ s.Require().NoError(err)
+ s.Require().NotNil(dbInst)
+ p := dkg.NewPrivateKey()
+ // Check existence.
+ exists, err := dbInst.HasDKGPrivateKey(1)
+ s.Require().NoError(err)
+ s.Require().False(exists)
+ // We should be unable to get it, too.
+ _, err = dbInst.GetDKGPrivateKey(1)
+ s.Require().IsType(err, ErrDKGPrivateKeyDoesNotExist)
+ // Put it.
+ s.Require().NoError(dbInst.PutDKGPrivateKey(1, *p))
+ // Put it again, should not success.
+ err = dbInst.PutDKGPrivateKey(1, *p)
+ s.Require().IsType(err, ErrDKGPrivateKeyExists)
+ // Get it back.
+ tmpPrv, err := dbInst.GetDKGPrivateKey(1)
+ s.Require().NoError(err)
+ s.Require().Equal(bytes.Compare(p.Bytes(), tmpPrv.Bytes()), 0)
+}
+
func TestMemBackedDB(t *testing.T) {
suite.Run(t, new(MemBackedDBTestSuite))
}