aboutsummaryrefslogtreecommitdiffstats
path: root/core/db/level-db.go
diff options
context:
space:
mode:
Diffstat (limited to 'core/db/level-db.go')
-rw-r--r--core/db/level-db.go118
1 files changed, 97 insertions, 21 deletions
diff --git a/core/db/level-db.go b/core/db/level-db.go
index 6983d3a..238c38e 100644
--- a/core/db/level-db.go
+++ b/core/db/level-db.go
@@ -18,14 +18,23 @@
package db
import (
- "encoding/json"
-
"github.com/syndtr/goleveldb/leveldb"
"github.com/dexon-foundation/dexon-consensus/common"
"github.com/dexon-foundation/dexon-consensus/core/types"
+ "github.com/dexon-foundation/dexon/rlp"
+)
+
+var (
+ blockKeyPrefix = []byte("b-")
+ compactionChainTipInfoKey = []byte("cc-tip")
)
+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 +59,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 +67,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 +96,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 +117,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
+ }
+ blockKey := lvl.getBlockKey(block.Hash)
+ exists, err := lvl.internalHasBlock(blockKey)
if err != nil {
return
}
- if lvl.HasBlock(block.Hash) {
+ 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 +142,62 @@ 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
+}
+
+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
+}