diff options
Diffstat (limited to 'core/db')
-rw-r--r-- | core/db/interfaces.go | 12 | ||||
-rw-r--r-- | core/db/level-db.go | 60 | ||||
-rw-r--r-- | core/db/level-db_test.go | 31 | ||||
-rw-r--r-- | core/db/memory.go | 35 | ||||
-rw-r--r-- | core/db/memory_test.go | 25 |
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)) } |