From 70ab62c1b72c6fef8dd2c8e405d7f9823f70f475 Mon Sep 17 00:00:00 2001 From: Mission Liao Date: Tue, 18 Dec 2018 10:02:30 +0800 Subject: vendor: sync to latest core (#91) - Implement new methods in db to cache DKG private key. - Implement new methods in db to cache compaction chain tip. --- .../dexon-consensus/core/db/level-db.go | 176 ++++++++++++++++++--- 1 file changed, 156 insertions(+), 20 deletions(-) (limited to 'vendor/github.com/dexon-foundation/dexon-consensus/core/db/level-db.go') 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 +} -- cgit