From c972cddcfb5d5b16efdf08135b4f7782d796764c Mon Sep 17 00:00:00 2001
From: Jimmy Hu <jimmy.hu@dexon.org>
Date: Thu, 13 Dec 2018 11:12:59 +0800
Subject: vendor: sync to latest core and fix conflict

---
 .../dexon-consensus/core/agreement-mgr.go          |  56 ++++--
 .../dexon-consensus/core/blockdb/interfaces.go     |  70 --------
 .../dexon-consensus/core/blockdb/level-db.go       | 127 -------------
 .../dexon-consensus/core/blockdb/memory.go         | 183 -------------------
 .../dexon-consensus/core/configuration-chain.go    |  25 ++-
 .../dexon-consensus/core/consensus.go              | 199 +++++++++++++--------
 .../dexon-consensus/core/db/interfaces.go          |  70 ++++++++
 .../dexon-consensus/core/db/level-db.go            | 127 +++++++++++++
 .../dexon-consensus/core/db/memory.go              | 185 +++++++++++++++++++
 .../dexon-consensus/core/interfaces.go             |   6 +-
 .../dexon-consensus/core/lattice-data.go           |  18 +-
 .../dexon-consensus/core/lattice.go                |  16 +-
 .../dexon-consensus/core/nonblocking.go            |   4 +-
 .../dexon-consensus/core/total-ordering.go         |  13 +-
 .../dexon-foundation/dexon-consensus/core/utils.go |  12 ++
 .../dexon-consensus/core/utils/nodeset-cache.go    |  19 +-
 vendor/vendor.json                                 |  42 +++--
 17 files changed, 640 insertions(+), 532 deletions(-)
 delete mode 100644 vendor/github.com/dexon-foundation/dexon-consensus/core/blockdb/interfaces.go
 delete mode 100644 vendor/github.com/dexon-foundation/dexon-consensus/core/blockdb/level-db.go
 delete mode 100644 vendor/github.com/dexon-foundation/dexon-consensus/core/blockdb/memory.go
 create mode 100644 vendor/github.com/dexon-foundation/dexon-consensus/core/db/interfaces.go
 create mode 100644 vendor/github.com/dexon-foundation/dexon-consensus/core/db/level-db.go
 create mode 100644 vendor/github.com/dexon-foundation/dexon-consensus/core/db/memory.go

(limited to 'vendor')

diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement-mgr.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement-mgr.go
index 57fb5c549..4cb47b105 100644
--- a/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement-mgr.go
+++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement-mgr.go
@@ -20,6 +20,7 @@ package core
 import (
 	"context"
 	"errors"
+	"math"
 	"sync"
 	"time"
 
@@ -174,7 +175,7 @@ func (mgr *agreementMgr) appendConfig(
 		recv := &consensusBAReceiver{
 			consensus:     mgr.con,
 			chainID:       i,
-			restartNotary: make(chan bool, 1),
+			restartNotary: make(chan types.Position, 1),
 		}
 		agrModule := newAgreement(
 			mgr.con.ID,
@@ -252,7 +253,9 @@ func (mgr *agreementMgr) processAgreementResult(
 			int(mgr.gov.Configuration(result.Position.Round).NotarySetSize),
 			types.NewNotarySetTarget(crs, result.Position.ChainID))
 		for key := range result.Votes {
-			agreement.processVote(&result.Votes[key])
+			if err := agreement.processVote(&result.Votes[key]); err != nil {
+				return err
+			}
 		}
 		agreement.restart(nIDs, result.Position, crs)
 	}
@@ -298,7 +301,7 @@ func (mgr *agreementMgr) runBA(initRound uint64, chainID uint32) {
 
 	// Check if this routine needs to awake in this round and prepare essential
 	// variables when yes.
-	checkRound := func() (awake bool) {
+	checkRound := func() (isNotary, isDisabled bool) {
 		defer func() {
 			currentRound = nextRound
 			nextRound++
@@ -318,7 +321,8 @@ func (mgr *agreementMgr) runBA(initRound uint64, chainID uint32) {
 		roundEndTime = config.beginTime.Add(config.roundInterval)
 		// Check if this chain handled by this routine included in this round.
 		if chainID >= config.numChains {
-			return false
+			isDisabled = true
+			return
 		}
 		// Check if this node in notary set of this chain in this round.
 		nodeSet, err := mgr.cache.GetNodeSet(nextRound)
@@ -329,7 +333,18 @@ func (mgr *agreementMgr) runBA(initRound uint64, chainID uint32) {
 		setting.notarySet = nodeSet.GetSubSet(
 			int(config.notarySetSize),
 			types.NewNotarySetTarget(config.crs, chainID))
-		_, awake = setting.notarySet[mgr.ID]
+		_, isNotary = setting.notarySet[mgr.ID]
+		if isNotary {
+			mgr.logger.Info("selected as notary set",
+				"ID", mgr.ID,
+				"round", nextRound,
+				"chainID", chainID)
+		} else {
+			mgr.logger.Info("not selected as notary set",
+				"ID", mgr.ID,
+				"round", nextRound,
+				"chainID", chainID)
+		}
 		// Setup ticker
 		if tickDuration != config.lambdaBA {
 			if setting.ticker != nil {
@@ -348,12 +363,9 @@ Loop:
 		default:
 		}
 		now := time.Now().UTC()
-		if !checkRound() {
-			if now.After(roundEndTime) {
-				// That round is passed.
-				continue Loop
-			}
-			// Sleep until next checkpoint.
+		var isDisabled bool
+		setting.recv.isNotary, isDisabled = checkRound()
+		if isDisabled {
 			select {
 			case <-mgr.ctx.Done():
 				break Loop
@@ -379,7 +391,7 @@ Loop:
 		// Run BA for this round.
 		recv.round = currentRound
 		recv.changeNotaryTime = roundEndTime
-		recv.restartNotary <- false
+		recv.restartNotary <- types.Position{ChainID: math.MaxUint32}
 		if err := mgr.baRoutineForOneRound(&setting); err != nil {
 			mgr.logger.Error("BA routine failed",
 				"error", err,
@@ -394,6 +406,7 @@ func (mgr *agreementMgr) baRoutineForOneRound(
 	setting *baRoundSetting) (err error) {
 	agr := setting.agr
 	recv := setting.recv
+	oldPos := agr.agreementID()
 Loop:
 	for {
 		select {
@@ -402,12 +415,18 @@ Loop:
 		default:
 		}
 		select {
-		case newNotary := <-recv.restartNotary:
-			if newNotary {
-				// This round is finished.
-				break Loop
+		case restartPos := <-recv.restartNotary:
+			if !isStop(restartPos) {
+				if restartPos.Round > oldPos.Round {
+					// This round is finished.
+					break Loop
+				}
+				if restartPos.Older(&oldPos) {
+					// The restartNotary event is triggered by 'BlockConfirmed'
+					// of some older block.
+					break
+				}
 			}
-			oldPos := agr.agreementID()
 			var nextHeight uint64
 			for {
 				nextHeight, err = mgr.lattice.NextHeight(recv.round, setting.chainID)
@@ -425,15 +444,16 @@ Loop:
 				if nextHeight > oldPos.Height {
 					break
 				}
-				time.Sleep(100 * time.Millisecond)
 				mgr.logger.Debug("Lattice not ready!!!",
 					"old", &oldPos, "next", nextHeight)
+				time.Sleep(100 * time.Millisecond)
 			}
 			nextPos := types.Position{
 				Round:   recv.round,
 				ChainID: setting.chainID,
 				Height:  nextHeight,
 			}
+			oldPos = nextPos
 			agr.restart(setting.notarySet, nextPos, setting.crs)
 		default:
 		}
diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/blockdb/interfaces.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/blockdb/interfaces.go
deleted file mode 100644
index c85630775..000000000
--- a/vendor/github.com/dexon-foundation/dexon-consensus/core/blockdb/interfaces.go
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2018 The dexon-consensus Authors
-// This file is part of the dexon-consensus library.
-//
-// The dexon-consensus library is free software: you can redistribute it
-// and/or modify it under the terms of the GNU Lesser General Public License as
-// published by the Free Software Foundation, either version 3 of the License,
-// or (at your option) any later version.
-//
-// The dexon-consensus library is distributed in the hope that it will be
-// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
-// General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the dexon-consensus library. If not, see
-// <http://www.gnu.org/licenses/>.
-
-package blockdb
-
-import (
-	"errors"
-	"fmt"
-
-	"github.com/dexon-foundation/dexon-consensus/common"
-	"github.com/dexon-foundation/dexon-consensus/core/types"
-)
-
-var (
-	// ErrBlockExists is the error when block eixsts.
-	ErrBlockExists = errors.New("block exists")
-	// ErrBlockDoesNotExist is the error when block does not eixst.
-	ErrBlockDoesNotExist = errors.New("block does not exist")
-	// ErrIterationFinished is the error to check if the iteration is finished.
-	ErrIterationFinished = errors.New("iteration finished")
-	// ErrEmptyPath is the error when the required path is empty.
-	ErrEmptyPath = fmt.Errorf("empty path")
-	// ErrClosed is the error when using DB after it's closed.
-	ErrClosed = fmt.Errorf("db closed")
-	// ErrNotImplemented is the error that some interface is not implemented.
-	ErrNotImplemented = fmt.Errorf("not implemented")
-)
-
-// BlockDatabase is the interface for a BlockDatabase.
-type BlockDatabase interface {
-	Reader
-	Writer
-
-	// Close allows database implementation able to
-	// release resource when finishing.
-	Close() error
-}
-
-// Reader defines the interface for reading blocks into DB.
-type Reader interface {
-	Has(hash common.Hash) bool
-	Get(hash common.Hash) (types.Block, error)
-	GetAll() (BlockIterator, error)
-}
-
-// Writer defines the interface for writing blocks into DB.
-type Writer interface {
-	Update(block types.Block) error
-	Put(block types.Block) error
-}
-
-// BlockIterator defines an iterator on blocks hold
-// in a DB.
-type BlockIterator interface {
-	Next() (types.Block, error)
-}
diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/blockdb/level-db.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/blockdb/level-db.go
deleted file mode 100644
index 76730fc9c..000000000
--- a/vendor/github.com/dexon-foundation/dexon-consensus/core/blockdb/level-db.go
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright 2018 The dexon-consensus Authors
-// This file is part of the dexon-consensus library.
-//
-// The dexon-consensus library is free software: you can redistribute it
-// and/or modify it under the terms of the GNU Lesser General Public License as
-// published by the Free Software Foundation, either version 3 of the License,
-// or (at your option) any later version.
-//
-// The dexon-consensus library is distributed in the hope that it will be
-// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
-// General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the dexon-consensus library. If not, see
-// <http://www.gnu.org/licenses/>.
-
-package blockdb
-
-import (
-	"encoding/json"
-
-	"github.com/syndtr/goleveldb/leveldb"
-
-	"github.com/dexon-foundation/dexon-consensus/common"
-	"github.com/dexon-foundation/dexon-consensus/core/types"
-)
-
-// LevelDBBackedBlockDB is a leveldb backed BlockDB implementation.
-type LevelDBBackedBlockDB struct {
-	db *leveldb.DB
-}
-
-// NewLevelDBBackedBlockDB initialize a leveldb-backed block database.
-func NewLevelDBBackedBlockDB(
-	path string) (lvl *LevelDBBackedBlockDB, err error) {
-
-	db, err := leveldb.OpenFile(path, nil)
-	if err != nil {
-		return
-	}
-	lvl = &LevelDBBackedBlockDB{db: db}
-	return
-}
-
-// Close implement Closer interface, which would release allocated resource.
-func (lvl *LevelDBBackedBlockDB) Close() error {
-	return lvl.db.Close()
-}
-
-// Has implements the Reader.Has method.
-func (lvl *LevelDBBackedBlockDB) Has(hash common.Hash) bool {
-	exists, err := lvl.db.Has([]byte(hash[:]), nil)
-	if err != nil {
-		// TODO(missionliao): Modify the interface to return error.
-		panic(err)
-	}
-	return exists
-}
-
-// Get implements the Reader.Get method.
-func (lvl *LevelDBBackedBlockDB) Get(
-	hash common.Hash) (block types.Block, err error) {
-
-	queried, err := lvl.db.Get([]byte(hash[:]), nil)
-	if err != nil {
-		if err == leveldb.ErrNotFound {
-			err = ErrBlockDoesNotExist
-		}
-		return
-	}
-	err = json.Unmarshal(queried, &block)
-	if err != nil {
-		return
-	}
-	return
-}
-
-// Update implements the Writer.Update method.
-func (lvl *LevelDBBackedBlockDB) Update(block types.Block) (err error) {
-	// NOTE: we didn't handle changes of block hash (and it
-	//       should not happen).
-	marshaled, err := json.Marshal(&block)
-	if err != nil {
-		return
-	}
-
-	if !lvl.Has(block.Hash) {
-		err = ErrBlockDoesNotExist
-		return
-	}
-	err = lvl.db.Put(
-		[]byte(block.Hash[:]),
-		marshaled,
-		nil)
-	if err != nil {
-		return
-	}
-	return
-}
-
-// Put implements the Writer.Put method.
-func (lvl *LevelDBBackedBlockDB) Put(block types.Block) (err error) {
-	marshaled, err := json.Marshal(&block)
-	if err != nil {
-		return
-	}
-	if lvl.Has(block.Hash) {
-		err = ErrBlockExists
-		return
-	}
-	err = lvl.db.Put(
-		[]byte(block.Hash[:]),
-		marshaled,
-		nil)
-	if err != nil {
-		return
-	}
-	return
-}
-
-// GetAll implements Reader.GetAll method, which allows callers
-// to retrieve all blocks in DB.
-func (lvl *LevelDBBackedBlockDB) GetAll() (BlockIterator, error) {
-	// TODO (mission): Implement this part via goleveldb's iterator.
-	return nil, ErrNotImplemented
-}
diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/blockdb/memory.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/blockdb/memory.go
deleted file mode 100644
index b45af229b..000000000
--- a/vendor/github.com/dexon-foundation/dexon-consensus/core/blockdb/memory.go
+++ /dev/null
@@ -1,183 +0,0 @@
-// Copyright 2018 The dexon-consensus Authors
-// This file is part of the dexon-consensus library.
-//
-// The dexon-consensus library is free software: you can redistribute it
-// and/or modify it under the terms of the GNU Lesser General Public License as
-// published by the Free Software Foundation, either version 3 of the License,
-// or (at your option) any later version.
-//
-// The dexon-consensus library is distributed in the hope that it will be
-// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
-// General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the dexon-consensus library. If not, see
-// <http://www.gnu.org/licenses/>.
-
-package blockdb
-
-import (
-	"encoding/json"
-	"io/ioutil"
-	"os"
-	"sync"
-
-	"github.com/dexon-foundation/dexon-consensus/common"
-	"github.com/dexon-foundation/dexon-consensus/core/types"
-)
-
-type seqIterator struct {
-	idx int
-	db  *MemBackedBlockDB
-}
-
-func (seq *seqIterator) Next() (types.Block, error) {
-	curIdx := seq.idx
-	seq.idx++
-	return seq.db.getByIndex(curIdx)
-}
-
-// MemBackedBlockDB is a memory backed BlockDB implementation.
-type MemBackedBlockDB struct {
-	blocksMutex        sync.RWMutex
-	blockHashSequence  common.Hashes
-	blocksByHash       map[common.Hash]*types.Block
-	persistantFilePath string
-}
-
-// NewMemBackedBlockDB initialize a memory-backed block database.
-func NewMemBackedBlockDB(persistantFilePath ...string) (db *MemBackedBlockDB, err error) {
-	db = &MemBackedBlockDB{
-		blockHashSequence: common.Hashes{},
-		blocksByHash:      make(map[common.Hash]*types.Block),
-	}
-	if len(persistantFilePath) == 0 || len(persistantFilePath[0]) == 0 {
-		return
-	}
-	db.persistantFilePath = persistantFilePath[0]
-	buf, err := ioutil.ReadFile(db.persistantFilePath)
-	if err != nil {
-		if !os.IsNotExist(err) {
-			// Something unexpected happened.
-			return
-		}
-		// It's expected behavior that file doesn't exists, we should not
-		// report error on it.
-		err = nil
-		return
-	}
-
-	// Init this instance by file content, it's a temporary way
-	// to export those private field for JSON encoding.
-	toLoad := struct {
-		Sequence common.Hashes
-		ByHash   map[common.Hash]*types.Block
-	}{}
-	err = json.Unmarshal(buf, &toLoad)
-	if err != nil {
-		return
-	}
-	db.blockHashSequence = toLoad.Sequence
-	db.blocksByHash = toLoad.ByHash
-	return
-}
-
-// Has returns wheter or not the DB has a block identified with the hash.
-func (m *MemBackedBlockDB) Has(hash common.Hash) bool {
-	m.blocksMutex.RLock()
-	defer m.blocksMutex.RUnlock()
-
-	_, ok := m.blocksByHash[hash]
-	return ok
-}
-
-// Get returns a block given a hash.
-func (m *MemBackedBlockDB) Get(hash common.Hash) (types.Block, error) {
-	m.blocksMutex.RLock()
-	defer m.blocksMutex.RUnlock()
-
-	return m.internalGet(hash)
-}
-
-func (m *MemBackedBlockDB) internalGet(hash common.Hash) (types.Block, error) {
-	b, ok := m.blocksByHash[hash]
-	if !ok {
-		return types.Block{}, ErrBlockDoesNotExist
-	}
-	return *b, nil
-}
-
-// Put inserts a new block into the database.
-func (m *MemBackedBlockDB) Put(block types.Block) error {
-	if m.Has(block.Hash) {
-		return ErrBlockExists
-	}
-
-	m.blocksMutex.Lock()
-	defer m.blocksMutex.Unlock()
-
-	m.blockHashSequence = append(m.blockHashSequence, block.Hash)
-	m.blocksByHash[block.Hash] = &block
-	return nil
-}
-
-// Update updates a block in the database.
-func (m *MemBackedBlockDB) Update(block types.Block) error {
-	if !m.Has(block.Hash) {
-		return ErrBlockDoesNotExist
-	}
-
-	m.blocksMutex.Lock()
-	defer m.blocksMutex.Unlock()
-
-	m.blocksByHash[block.Hash] = &block
-	return nil
-}
-
-// Close implement Closer interface, which would release allocated resource.
-func (m *MemBackedBlockDB) Close() (err error) {
-	// Save internal state to a pretty-print json file. It's a temporary way
-	// to dump private file via JSON encoding.
-	if len(m.persistantFilePath) == 0 {
-		return
-	}
-
-	m.blocksMutex.RLock()
-	defer m.blocksMutex.RUnlock()
-
-	toDump := struct {
-		Sequence common.Hashes
-		ByHash   map[common.Hash]*types.Block
-	}{
-		Sequence: m.blockHashSequence,
-		ByHash:   m.blocksByHash,
-	}
-
-	// Dump to JSON with 2-space indent.
-	buf, err := json.Marshal(&toDump)
-	if err != nil {
-		return
-	}
-
-	err = ioutil.WriteFile(m.persistantFilePath, buf, 0644)
-	return
-}
-
-func (m *MemBackedBlockDB) getByIndex(idx int) (types.Block, error) {
-	m.blocksMutex.RLock()
-	defer m.blocksMutex.RUnlock()
-
-	if idx >= len(m.blockHashSequence) {
-		return types.Block{}, ErrIterationFinished
-	}
-
-	hash := m.blockHashSequence[idx]
-	return m.internalGet(hash)
-}
-
-// GetAll implement Reader.GetAll method, which allows caller
-// to retrieve all blocks in DB.
-func (m *MemBackedBlockDB) GetAll() (BlockIterator, error) {
-	return &seqIterator{db: m}, nil
-}
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 fdfcd13d0..364f2c75c 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
@@ -216,6 +216,18 @@ func (cc *configurationChain) runDKG(round uint64) error {
 	return nil
 }
 
+func (cc *configurationChain) isDKGReady(round uint64) bool {
+	if !cc.gov.IsDKGFinal(round) {
+		return false
+	}
+	return func() bool {
+		cc.dkgResult.RLock()
+		defer cc.dkgResult.RUnlock()
+		_, exist := cc.gpk[round]
+		return exist
+	}()
+}
+
 func (cc *configurationChain) preparePartialSignature(
 	round uint64, hash common.Hash) (*typesDKG.PartialSignature, error) {
 	signer, exist := func() (*dkgShareSecret, bool) {
@@ -305,19 +317,6 @@ func (cc *configurationChain) runTSig(
 	return signature, nil
 }
 
-func (cc *configurationChain) runBlockTSig(
-	round uint64, hash common.Hash) (crypto.Signature, error) {
-	sig, err := cc.runTSig(round, hash)
-	if err != nil {
-		return crypto.Signature{}, err
-	}
-	cc.logger.Info("Block TSIG",
-		"nodeID", cc.ID,
-		"round", round,
-		"signature", sig)
-	return sig, nil
-}
-
 func (cc *configurationChain) runCRSTSig(
 	round uint64, crs common.Hash) ([]byte, error) {
 	sig, err := cc.runTSig(round, crs)
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 bfe893cd5..a6d80371d 100644
--- a/vendor/github.com/dexon-foundation/dexon-consensus/core/consensus.go
+++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/consensus.go
@@ -25,8 +25,8 @@ import (
 	"time"
 
 	"github.com/dexon-foundation/dexon-consensus/common"
-	"github.com/dexon-foundation/dexon-consensus/core/blockdb"
 	"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"
@@ -70,17 +70,23 @@ type consensusBAReceiver struct {
 	chainID          uint32
 	changeNotaryTime time.Time
 	round            uint64
-	restartNotary    chan bool
+	isNotary         bool
+	restartNotary    chan types.Position
 }
 
 func (recv *consensusBAReceiver) ProposeVote(vote *types.Vote) {
+	if !recv.isNotary {
+		return
+	}
 	if err := recv.agreementModule.prepareVote(vote); err != nil {
 		recv.consensus.logger.Error("Failed to prepare vote", "error", err)
 		return
 	}
 	go func() {
 		if err := recv.agreementModule.processVote(vote); err != nil {
-			recv.consensus.logger.Error("Failed to process vote", "error", err)
+			recv.consensus.logger.Error("Failed to process self vote",
+				"error", err,
+				"vote", vote)
 			return
 		}
 		recv.consensus.logger.Debug("Calling Network.BroadcastVote",
@@ -90,6 +96,9 @@ func (recv *consensusBAReceiver) ProposeVote(vote *types.Vote) {
 }
 
 func (recv *consensusBAReceiver) ProposeBlock() common.Hash {
+	if !recv.isNotary {
+		return common.Hash{}
+	}
 	block := recv.consensus.proposeBlock(recv.chainID, recv.round)
 	if block == nil {
 		recv.consensus.logger.Error("unable to propose block")
@@ -123,7 +132,7 @@ func (recv *consensusBAReceiver) ConfirmBlock(
 		block, exist = recv.agreementModule.findCandidateBlockNoLock(hash)
 		if !exist {
 			recv.consensus.logger.Error("Unknown block confirmed",
-				"hash", hash,
+				"hash", hash.String()[:6],
 				"chainID", recv.chainID)
 			ch := make(chan *types.Block)
 			func() {
@@ -135,7 +144,8 @@ func (recv *consensusBAReceiver) ConfirmBlock(
 			go func() {
 				block = <-ch
 				recv.consensus.logger.Info("Receive unknown block",
-					"hash", hash,
+					"hash", hash.String()[:6],
+					"position", &block.Position,
 					"chainID", recv.chainID)
 				recv.agreementModule.addCandidateBlock(block)
 				recv.agreementModule.lock.Lock()
@@ -152,8 +162,8 @@ func (recv *consensusBAReceiver) ConfirmBlock(
 			parentHash := hash
 			for {
 				recv.consensus.logger.Warn("Parent block not confirmed",
-					"hash", parentHash,
-					"chainID", recv.chainID)
+					"parent-hash", parentHash.String()[:6],
+					"cur-position", &block.Position)
 				ch := make(chan *types.Block)
 				if !func() bool {
 					recv.consensus.lock.Lock()
@@ -179,11 +189,14 @@ func (recv *consensusBAReceiver) ConfirmBlock(
 					}
 				}
 				recv.consensus.logger.Info("Receive parent block",
-					"hash", block.ParentHash,
+					"parent-hash", block.ParentHash.String()[:6],
+					"cur-position", &block.Position,
 					"chainID", recv.chainID)
 				recv.consensus.ccModule.registerBlock(block)
 				if err := recv.consensus.processBlock(block); err != nil {
-					recv.consensus.logger.Error("Failed to process block", "error", err)
+					recv.consensus.logger.Error("Failed to process block",
+						"block", block,
+						"error", err)
 					return
 				}
 				parentHash = block.ParentHash
@@ -194,24 +207,28 @@ func (recv *consensusBAReceiver) ConfirmBlock(
 			}
 		}(block.ParentHash)
 	}
-	voteList := make([]types.Vote, 0, len(votes))
-	for _, vote := range votes {
-		if vote.BlockHash != hash {
-			continue
+	if recv.isNotary {
+		voteList := make([]types.Vote, 0, len(votes))
+		for _, vote := range votes {
+			if vote.BlockHash != hash {
+				continue
+			}
+			voteList = append(voteList, *vote)
 		}
-		voteList = append(voteList, *vote)
-	}
-	result := &types.AgreementResult{
-		BlockHash:    block.Hash,
-		Position:     block.Position,
-		Votes:        voteList,
-		IsEmptyBlock: isEmptyBlockConfirmed,
+		result := &types.AgreementResult{
+			BlockHash:    block.Hash,
+			Position:     block.Position,
+			Votes:        voteList,
+			IsEmptyBlock: isEmptyBlockConfirmed,
+		}
+		recv.consensus.logger.Debug("Propose AgreementResult",
+			"result", result)
+		recv.consensus.network.BroadcastAgreementResult(result)
 	}
-	recv.consensus.logger.Debug("Propose AgreementResult",
-		"result", result)
-	recv.consensus.network.BroadcastAgreementResult(result)
 	if err := recv.consensus.processBlock(block); err != nil {
-		recv.consensus.logger.Error("Failed to process block", "error", err)
+		recv.consensus.logger.Error("Failed to process block",
+			"block", block,
+			"error", err)
 		return
 	}
 	// Clean the restartNotary channel so BA will not stuck by deadlock.
@@ -223,15 +240,18 @@ CleanChannelLoop:
 			break CleanChannelLoop
 		}
 	}
+	newPos := block.Position
 	if block.Timestamp.After(recv.changeNotaryTime) {
 		recv.round++
-		recv.restartNotary <- true
-	} else {
-		recv.restartNotary <- false
+		newPos.Round++
 	}
+	recv.restartNotary <- newPos
 }
 
 func (recv *consensusBAReceiver) PullBlocks(hashes common.Hashes) {
+	if !recv.isNotary {
+		return
+	}
 	recv.consensus.logger.Debug("Calling Network.PullBlocks", "hashes", hashes)
 	recv.consensus.network.PullBlocks(hashes)
 }
@@ -312,7 +332,7 @@ func (recv *consensusDKGReceiver) ProposeDKGAntiNackComplaint(
 // ProposeDKGFinalize propose a DKGFinalize message.
 func (recv *consensusDKGReceiver) ProposeDKGFinalize(final *typesDKG.Finalize) {
 	if err := recv.authModule.SignDKGFinalize(final); err != nil {
-		recv.logger.Error("Faield to sign DKG finalize", "error", err)
+		recv.logger.Error("Failed to sign DKG finalize", "error", err)
 		return
 	}
 	recv.logger.Debug("Calling Governance.AddDKGFinalize", "final", final)
@@ -340,21 +360,23 @@ type Consensus struct {
 	toSyncer *totalOrderingSyncer
 
 	// Interfaces.
-	db      blockdb.BlockDatabase
-	app     Application
-	gov     Governance
-	network Network
+	db       db.Database
+	app      Application
+	debugApp Debug
+	gov      Governance
+	network  Network
 
 	// Misc.
-	dMoment       time.Time
-	nodeSetCache  *utils.NodeSetCache
-	round         uint64
-	roundToNotify uint64
-	lock          sync.RWMutex
-	ctx           context.Context
-	ctxCancel     context.CancelFunc
-	event         *common.Event
-	logger        common.Logger
+	dMoment                    time.Time
+	nodeSetCache               *utils.NodeSetCache
+	round                      uint64
+	roundToNotify              uint64
+	lock                       sync.RWMutex
+	ctx                        context.Context
+	ctxCancel                  context.CancelFunc
+	event                      *common.Event
+	logger                     common.Logger
+	nonFinalizedBlockDelivered bool
 }
 
 // NewConsensus construct an Consensus instance.
@@ -362,7 +384,7 @@ func NewConsensus(
 	dMoment time.Time,
 	app Application,
 	gov Governance,
-	db blockdb.BlockDatabase,
+	db db.Database,
 	network Network,
 	prv crypto.PrivateKey,
 	logger common.Logger) *Consensus {
@@ -372,7 +394,10 @@ func NewConsensus(
 	// Setup auth module.
 	authModule := NewAuthenticator(prv)
 	// Check if the application implement Debug interface.
-	debugApp, _ := app.(Debug)
+	var debugApp Debug
+	if a, ok := app.(Debug); ok {
+		debugApp = a
+	}
 	// Get configuration for genesis round.
 	var round uint64
 	logger.Debug("Calling Governance.Configuration", "round", round)
@@ -407,6 +432,7 @@ func NewConsensus(
 		ccModule:         newCompactionChain(gov),
 		lattice:          lattice,
 		app:              newNonBlocking(app, debugApp),
+		debugApp:         debugApp,
 		gov:              gov,
 		db:               db,
 		network:          network,
@@ -438,7 +464,7 @@ func NewConsensusFromSyncer(
 	initRoundBeginTime time.Time,
 	app Application,
 	gov Governance,
-	db blockdb.BlockDatabase,
+	db db.Database,
 	networkModule Network,
 	prv crypto.PrivateKey,
 	latticeModule *Lattice,
@@ -492,7 +518,6 @@ func NewConsensusFromSyncer(
 	}
 	// Dump all BA-confirmed blocks to the consensus instance.
 	for _, b := range blocks {
-		con.app.BlockConfirmed(*b)
 		con.ccModule.registerBlock(b)
 		if err := con.processBlock(b); err != nil {
 			return nil, err
@@ -500,7 +525,7 @@ func NewConsensusFromSyncer(
 	}
 	// Dump all randomness result to the consensus instance.
 	for _, r := range randomnessResults {
-		if err := con.ProcessBlockRandomnessResult(r); err != nil {
+		if err := con.ProcessBlockRandomnessResult(r, false); err != nil {
 			con.logger.Error("failed to process randomness result when syncing",
 				"result", r)
 			continue
@@ -605,21 +630,22 @@ func (con *Consensus) runDKG(round uint64, config *types.Config) {
 }
 
 func (con *Consensus) runCRS(round uint64) {
-	con.logger.Debug("Calling Governance.CRS to check if already proposed",
-		"round", round+1)
-	if (con.gov.CRS(round+1) != common.Hash{}) {
-		con.logger.Info("CRS already proposed", "round", round+1)
-		return
-	}
-	con.logger.Debug("Calling Governance.IsDKGFinal to check if ready to run CRS",
-		"round", round)
-	for !con.gov.IsDKGFinal(round) {
+	for {
+		con.logger.Debug("Calling Governance.CRS to check if already proposed",
+			"round", round+1)
+		if (con.gov.CRS(round+1) != common.Hash{}) {
+			con.logger.Info("CRS already proposed", "round", round+1)
+			return
+		}
+		con.logger.Debug("Calling Governance.IsDKGFinal to check if ready to run CRS",
+			"round", round)
+		if con.cfgModule.isDKGReady(round) {
+			break
+		}
 		con.logger.Debug("DKG is not ready for running CRS. Retry later...",
 			"round", round)
 		time.Sleep(500 * time.Millisecond)
 	}
-	// Wait some time for DKG to recover private share.
-	time.Sleep(100 * time.Millisecond)
 	// Start running next round CRS.
 	con.logger.Debug("Calling Governance.CRS", "round", round)
 	psig, err := con.cfgModule.preparePartialSignature(round, con.gov.CRS(round))
@@ -794,26 +820,30 @@ MessageLoop:
 				// For sync mode.
 				if err := con.processFinalizedBlock(val); err != nil {
 					con.logger.Error("Failed to process finalized block",
+						"block", val,
 						"error", err)
 				}
 			} else {
 				if err := con.preProcessBlock(val); err != nil {
 					con.logger.Error("Failed to pre process block",
+						"block", val,
 						"error", err)
 				}
 			}
 		case *types.Vote:
 			if err := con.ProcessVote(val); err != nil {
 				con.logger.Error("Failed to process vote",
+					"vote", val,
 					"error", err)
 			}
 		case *types.AgreementResult:
 			if err := con.ProcessAgreementResult(val); err != nil {
 				con.logger.Error("Failed to process agreement result",
+					"result", val,
 					"error", err)
 			}
 		case *types.BlockRandomnessResult:
-			if err := con.ProcessBlockRandomnessResult(val); err != nil {
+			if err := con.ProcessBlockRandomnessResult(val, true); err != nil {
 				con.logger.Error("Failed to process block randomness result",
 					"hash", val.BlockHash.String()[:6],
 					"position", &val.Position,
@@ -884,9 +914,7 @@ func (con *Consensus) ProcessAgreementResult(
 	if rand.Position.Round == 0 {
 		return nil
 	}
-	if !con.ccModule.blockRegistered(rand.BlockHash) {
-		return nil
-	}
+	// TODO(mission): find a way to avoid spamming by older agreement results.
 	// Sanity check done.
 	if !con.cfgModule.touchTSigHash(rand.BlockHash) {
 		return nil
@@ -914,13 +942,16 @@ func (con *Consensus) ProcessAgreementResult(
 	con.logger.Debug("Calling Network.BroadcastDKGPartialSignature",
 		"proposer", psig.ProposerID,
 		"round", psig.Round,
-		"hash", psig.Hash)
+		"hash", psig.Hash.String()[:6])
 	con.network.BroadcastDKGPartialSignature(psig)
 	go func() {
 		tsig, err := con.cfgModule.runTSig(rand.Position.Round, rand.BlockHash)
 		if err != nil {
 			if err != ErrTSigAlreadyRunning {
-				con.logger.Error("Faield to run TSIG", "error", err)
+				con.logger.Error("Failed to run TSIG",
+					"position", &rand.Position,
+					"hash", rand.BlockHash.String()[:6],
+					"error", err)
 			}
 			return
 		}
@@ -929,7 +960,7 @@ func (con *Consensus) ProcessAgreementResult(
 			Position:   rand.Position,
 			Randomness: tsig.Signature,
 		}
-		if err := con.ProcessBlockRandomnessResult(result); err != nil {
+		if err := con.ProcessBlockRandomnessResult(result, true); err != nil {
 			con.logger.Error("Failed to process randomness result",
 				"error", err)
 			return
@@ -940,27 +971,33 @@ func (con *Consensus) ProcessAgreementResult(
 
 // ProcessBlockRandomnessResult processes the randomness result.
 func (con *Consensus) ProcessBlockRandomnessResult(
-	rand *types.BlockRandomnessResult) error {
+	rand *types.BlockRandomnessResult, needBroadcast bool) error {
 	if rand.Position.Round == 0 {
 		return nil
 	}
 	if err := con.ccModule.processBlockRandomnessResult(rand); err != nil {
 		if err == ErrBlockNotRegistered {
 			err = nil
+		} else {
+			return err
 		}
-		return err
 	}
-	con.logger.Debug("Calling Network.BroadcastRandomnessResult",
-		"hash", rand.BlockHash,
-		"position", &rand.Position,
-		"randomness", hex.EncodeToString(rand.Randomness))
-	con.network.BroadcastRandomnessResult(rand)
+	if needBroadcast {
+		con.logger.Debug("Calling Network.BroadcastRandomnessResult",
+			"hash", rand.BlockHash.String()[:6],
+			"position", &rand.Position,
+			"randomness", hex.EncodeToString(rand.Randomness))
+		con.network.BroadcastRandomnessResult(rand)
+	}
 	return nil
 }
 
 // preProcessBlock performs Byzantine Agreement on the block.
 func (con *Consensus) preProcessBlock(b *types.Block) (err error) {
 	err = con.baMgr.processBlock(b)
+	if err == nil && con.debugApp != nil {
+		con.debugApp.BlockReceived(b.Hash)
+	}
 	return
 }
 
@@ -999,7 +1036,7 @@ func (con *Consensus) deliverBlock(b *types.Block) {
 
 // processBlock is the entry point to submit one block to a Consensus instance.
 func (con *Consensus) processBlock(block *types.Block) (err error) {
-	if err = con.db.Put(*block); err != nil && err != blockdb.ErrBlockExists {
+	if err = con.db.PutBlock(*block); err != nil && err != db.ErrBlockExists {
 		return
 	}
 	con.lock.Lock()
@@ -1012,6 +1049,19 @@ func (con *Consensus) processBlock(block *types.Block) (err error) {
 	}
 	// Pass delivered blocks to compaction chain.
 	for _, b := range deliveredBlocks {
+		if b.IsFinalized() {
+			if con.nonFinalizedBlockDelivered {
+				panic(fmt.Errorf("attempting to skip finalized block: %s", b))
+			}
+			con.logger.Info("skip delivery of finalized block",
+				"block", b,
+				"finalization-height", b.Finalization.Height)
+			continue
+		} else {
+			// Mark that some non-finalized block delivered. After this flag
+			// turned on, it's not allowed to deliver finalized blocks anymore.
+			con.nonFinalizedBlockDelivered = true
+		}
 		if err = con.ccModule.processBlock(b); err != nil {
 			return
 		}
@@ -1022,11 +1072,14 @@ 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.Update(*b); err != nil {
+		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/db/interfaces.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/db/interfaces.go
new file mode 100644
index 000000000..5e13dc604
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/db/interfaces.go
@@ -0,0 +1,70 @@
+// Copyright 2018 The dexon-consensus Authors
+// This file is part of the dexon-consensus library.
+//
+// The dexon-consensus library is free software: you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation, either version 3 of the License,
+// or (at your option) any later version.
+//
+// The dexon-consensus library is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+// General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the dexon-consensus library. If not, see
+// <http://www.gnu.org/licenses/>.
+
+package db
+
+import (
+	"errors"
+	"fmt"
+
+	"github.com/dexon-foundation/dexon-consensus/common"
+	"github.com/dexon-foundation/dexon-consensus/core/types"
+)
+
+var (
+	// ErrBlockExists is the error when block eixsts.
+	ErrBlockExists = errors.New("block exists")
+	// ErrBlockDoesNotExist is the error when block does not eixst.
+	ErrBlockDoesNotExist = errors.New("block does not exist")
+	// ErrIterationFinished is the error to check if the iteration is finished.
+	ErrIterationFinished = errors.New("iteration finished")
+	// ErrEmptyPath is the error when the required path is empty.
+	ErrEmptyPath = fmt.Errorf("empty path")
+	// ErrClosed is the error when using DB after it's closed.
+	ErrClosed = fmt.Errorf("db closed")
+	// ErrNotImplemented is the error that some interface is not implemented.
+	ErrNotImplemented = fmt.Errorf("not implemented")
+)
+
+// Database is the interface for a Database.
+type Database interface {
+	Reader
+	Writer
+
+	// Close allows database implementation able to
+	// release resource when finishing.
+	Close() error
+}
+
+// Reader defines the interface for reading blocks into DB.
+type Reader interface {
+	HasBlock(hash common.Hash) bool
+	GetBlock(hash common.Hash) (types.Block, error)
+	GetAllBlocks() (BlockIterator, error)
+}
+
+// Writer defines the interface for writing blocks into DB.
+type Writer interface {
+	UpdateBlock(block types.Block) error
+	PutBlock(block types.Block) error
+}
+
+// BlockIterator defines an iterator on blocks hold
+// in a DB.
+type BlockIterator interface {
+	NextBlock() (types.Block, error)
+}
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
new file mode 100644
index 000000000..6983d3a5e
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/db/level-db.go
@@ -0,0 +1,127 @@
+// Copyright 2018 The dexon-consensus Authors
+// This file is part of the dexon-consensus library.
+//
+// The dexon-consensus library is free software: you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation, either version 3 of the License,
+// or (at your option) any later version.
+//
+// The dexon-consensus library is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+// General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the dexon-consensus library. If not, see
+// <http://www.gnu.org/licenses/>.
+
+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"
+)
+
+// LevelDBBackedDB is a leveldb backed DB implementation.
+type LevelDBBackedDB struct {
+	db *leveldb.DB
+}
+
+// NewLevelDBBackedDB initialize a leveldb-backed database.
+func NewLevelDBBackedDB(
+	path string) (lvl *LevelDBBackedDB, err error) {
+
+	dbInst, err := leveldb.OpenFile(path, nil)
+	if err != nil {
+		return
+	}
+	lvl = &LevelDBBackedDB{db: dbInst}
+	return
+}
+
+// Close implement Closer interface, which would release allocated resource.
+func (lvl *LevelDBBackedDB) Close() error {
+	return lvl.db.Close()
+}
+
+// HasBlock implements the Reader.Has method.
+func (lvl *LevelDBBackedDB) HasBlock(hash common.Hash) bool {
+	exists, err := lvl.db.Has([]byte(hash[:]), nil)
+	if err != nil {
+		// TODO(missionliao): Modify the interface to return error.
+		panic(err)
+	}
+	return exists
+}
+
+// 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)
+	if err != nil {
+		if err == leveldb.ErrNotFound {
+			err = ErrBlockDoesNotExist
+		}
+		return
+	}
+	err = json.Unmarshal(queried, &block)
+	if err != nil {
+		return
+	}
+	return
+}
+
+// UpdateBlock implements the Writer.UpdateBlock method.
+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)
+	if err != nil {
+		return
+	}
+
+	if !lvl.HasBlock(block.Hash) {
+		err = ErrBlockDoesNotExist
+		return
+	}
+	err = lvl.db.Put(
+		[]byte(block.Hash[:]),
+		marshaled,
+		nil)
+	if err != nil {
+		return
+	}
+	return
+}
+
+// PutBlock implements the Writer.PutBlock method.
+func (lvl *LevelDBBackedDB) PutBlock(block types.Block) (err error) {
+	marshaled, err := json.Marshal(&block)
+	if err != nil {
+		return
+	}
+	if lvl.HasBlock(block.Hash) {
+		err = ErrBlockExists
+		return
+	}
+	err = lvl.db.Put(
+		[]byte(block.Hash[:]),
+		marshaled,
+		nil)
+	if err != nil {
+		return
+	}
+	return
+}
+
+// GetAllBlocks implements Reader.GetAllBlocks method, which allows callers
+// to retrieve all blocks in DB.
+func (lvl *LevelDBBackedDB) GetAllBlocks() (BlockIterator, error) {
+	// TODO (mission): Implement this part via goleveldb's iterator.
+	return nil, ErrNotImplemented
+}
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
new file mode 100644
index 000000000..4246e4fe1
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/db/memory.go
@@ -0,0 +1,185 @@
+// Copyright 2018 The dexon-consensus Authors
+// This file is part of the dexon-consensus library.
+//
+// The dexon-consensus library is free software: you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation, either version 3 of the License,
+// or (at your option) any later version.
+//
+// The dexon-consensus library is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+// General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the dexon-consensus library. If not, see
+// <http://www.gnu.org/licenses/>.
+
+package db
+
+import (
+	"encoding/json"
+	"io/ioutil"
+	"os"
+	"sync"
+
+	"github.com/dexon-foundation/dexon-consensus/common"
+	"github.com/dexon-foundation/dexon-consensus/core/types"
+)
+
+type blockSeqIterator struct {
+	idx int
+	db  *MemBackedDB
+}
+
+// NextBlock implemenets BlockIterator.NextBlock method.
+func (seq *blockSeqIterator) NextBlock() (types.Block, error) {
+	curIdx := seq.idx
+	seq.idx++
+	return seq.db.getBlockByIndex(curIdx)
+}
+
+// MemBackedDB is a memory backed DB implementation.
+type MemBackedDB struct {
+	blocksMutex        sync.RWMutex
+	blockHashSequence  common.Hashes
+	blocksByHash       map[common.Hash]*types.Block
+	persistantFilePath string
+}
+
+// NewMemBackedDB initialize a memory-backed database.
+func NewMemBackedDB(persistantFilePath ...string) (
+	dbInst *MemBackedDB, err error) {
+	dbInst = &MemBackedDB{
+		blockHashSequence: common.Hashes{},
+		blocksByHash:      make(map[common.Hash]*types.Block),
+	}
+	if len(persistantFilePath) == 0 || len(persistantFilePath[0]) == 0 {
+		return
+	}
+	dbInst.persistantFilePath = persistantFilePath[0]
+	buf, err := ioutil.ReadFile(dbInst.persistantFilePath)
+	if err != nil {
+		if !os.IsNotExist(err) {
+			// Something unexpected happened.
+			return
+		}
+		// It's expected behavior that file doesn't exists, we should not
+		// report error on it.
+		err = nil
+		return
+	}
+
+	// Init this instance by file content, it's a temporary way
+	// to export those private field for JSON encoding.
+	toLoad := struct {
+		Sequence common.Hashes
+		ByHash   map[common.Hash]*types.Block
+	}{}
+	err = json.Unmarshal(buf, &toLoad)
+	if err != nil {
+		return
+	}
+	dbInst.blockHashSequence = toLoad.Sequence
+	dbInst.blocksByHash = toLoad.ByHash
+	return
+}
+
+// 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()
+
+	_, ok := m.blocksByHash[hash]
+	return ok
+}
+
+// GetBlock returns a block given a hash.
+func (m *MemBackedDB) GetBlock(hash common.Hash) (types.Block, error) {
+	m.blocksMutex.RLock()
+	defer m.blocksMutex.RUnlock()
+
+	return m.internalGetBlock(hash)
+}
+
+func (m *MemBackedDB) internalGetBlock(hash common.Hash) (types.Block, error) {
+	b, ok := m.blocksByHash[hash]
+	if !ok {
+		return types.Block{}, ErrBlockDoesNotExist
+	}
+	return *b, nil
+}
+
+// PutBlock inserts a new block into the database.
+func (m *MemBackedDB) PutBlock(block types.Block) error {
+	if m.HasBlock(block.Hash) {
+		return ErrBlockExists
+	}
+
+	m.blocksMutex.Lock()
+	defer m.blocksMutex.Unlock()
+
+	m.blockHashSequence = append(m.blockHashSequence, block.Hash)
+	m.blocksByHash[block.Hash] = &block
+	return nil
+}
+
+// UpdateBlock updates a block in the database.
+func (m *MemBackedDB) UpdateBlock(block types.Block) error {
+	if !m.HasBlock(block.Hash) {
+		return ErrBlockDoesNotExist
+	}
+
+	m.blocksMutex.Lock()
+	defer m.blocksMutex.Unlock()
+
+	m.blocksByHash[block.Hash] = &block
+	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
+	// to dump private file via JSON encoding.
+	if len(m.persistantFilePath) == 0 {
+		return
+	}
+
+	m.blocksMutex.RLock()
+	defer m.blocksMutex.RUnlock()
+
+	toDump := struct {
+		Sequence common.Hashes
+		ByHash   map[common.Hash]*types.Block
+	}{
+		Sequence: m.blockHashSequence,
+		ByHash:   m.blocksByHash,
+	}
+
+	// Dump to JSON with 2-space indent.
+	buf, err := json.Marshal(&toDump)
+	if err != nil {
+		return
+	}
+
+	err = ioutil.WriteFile(m.persistantFilePath, buf, 0644)
+	return
+}
+
+func (m *MemBackedDB) getBlockByIndex(idx int) (types.Block, error) {
+	m.blocksMutex.RLock()
+	defer m.blocksMutex.RUnlock()
+
+	if idx >= len(m.blockHashSequence) {
+		return types.Block{}, ErrIterationFinished
+	}
+
+	hash := m.blockHashSequence[idx]
+	return m.internalGetBlock(hash)
+}
+
+// GetAllBlocks implement Reader.GetAllBlocks method, which allows caller
+// to retrieve all blocks in DB.
+func (m *MemBackedDB) GetAllBlocks() (BlockIterator, error) {
+	return &blockSeqIterator{db: m}, nil
+}
diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/interfaces.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/interfaces.go
index 69798540f..2ebfe8621 100644
--- a/vendor/github.com/dexon-foundation/dexon-consensus/core/interfaces.go
+++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/interfaces.go
@@ -41,7 +41,7 @@ type Application interface {
 	// BlockConfirmed is called when a block is confirmed and added to lattice.
 	BlockConfirmed(block types.Block)
 
-	// BlockDelivered is called when a block is add to the compaction chain.
+	// BlockDelivered is called when a block is added to the compaction chain.
 	BlockDelivered(blockHash common.Hash,
 		blockPosition types.Position, result types.FinalizationResult)
 }
@@ -49,9 +49,13 @@ type Application interface {
 // Debug describes the application interface that requires
 // more detailed consensus execution.
 type Debug interface {
+	// BlockReceived is called when the block received in agreement.
+	BlockReceived(common.Hash)
 	// TotalOrderingDelivered is called when the total ordering algorithm deliver
 	// a set of block.
 	TotalOrderingDelivered(common.Hashes, uint32)
+	// BlockReady is called when the block's randomness is ready.
+	BlockReady(common.Hash)
 }
 
 // Network describs the network interface that interacts with DEXON consensus
diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/lattice-data.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/lattice-data.go
index f1ab2de6a..e55c0dbfc 100644
--- a/vendor/github.com/dexon-foundation/dexon-consensus/core/lattice-data.go
+++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/lattice-data.go
@@ -24,7 +24,7 @@ import (
 	"time"
 
 	"github.com/dexon-foundation/dexon-consensus/common"
-	"github.com/dexon-foundation/dexon-consensus/core/blockdb"
+	"github.com/dexon-foundation/dexon-consensus/core/db"
 	"github.com/dexon-foundation/dexon-consensus/core/types"
 	"github.com/dexon-foundation/dexon-consensus/core/utils"
 )
@@ -105,8 +105,8 @@ func newLatticeDataConfig(
 
 // latticeData is a module for storing lattice.
 type latticeData struct {
-	// BlockDB for getting blocks purged in memory.
-	db blockdb.Reader
+	// DB for getting blocks purged in memory.
+	db db.Reader
 	// chains stores chains' blocks and other info.
 	chains []*chainStatus
 	// blockByHash stores blocks, indexed by block hash.
@@ -117,7 +117,7 @@ type latticeData struct {
 
 // newLatticeData creates a new latticeData instance.
 func newLatticeData(
-	db blockdb.Reader,
+	db db.Reader,
 	dMoment time.Time,
 	round uint64,
 	config *types.Config) (data *latticeData) {
@@ -146,7 +146,7 @@ func (data *latticeData) checkAckingRelations(b *types.Block) error {
 	for _, hash := range b.Acks {
 		bAck, err := data.findBlock(hash)
 		if err != nil {
-			if err == blockdb.ErrBlockDoesNotExist {
+			if err == db.ErrBlockDoesNotExist {
 				return &ErrAckingBlockNotExists{hash}
 			}
 			return err
@@ -276,7 +276,7 @@ func (data *latticeData) addBlock(
 	// Update lastAckPos.
 	for _, ack := range block.Acks {
 		if bAck, err = data.findBlock(ack); err != nil {
-			if err == blockdb.ErrBlockDoesNotExist {
+			if err == db.ErrBlockDoesNotExist {
 				err = nil
 				continue
 			}
@@ -298,7 +298,7 @@ func (data *latticeData) addBlock(
 			allAckingBlockDelivered := true
 			for _, ack := range tip.Acks {
 				if bAck, err = data.findBlock(ack); err != nil {
-					if err == blockdb.ErrBlockDoesNotExist {
+					if err == db.ErrBlockDoesNotExist {
 						err = nil
 						allAckingBlockDelivered = false
 						break
@@ -525,7 +525,7 @@ func (data *latticeData) findBlock(h common.Hash) (b *types.Block, err error) {
 		return
 	}
 	var tmpB types.Block
-	if tmpB, err = data.db.Get(h); err != nil {
+	if tmpB, err = data.db.GetBlock(h); err != nil {
 		return
 	}
 	b = &tmpB
@@ -632,7 +632,7 @@ func (s *chainStatus) addBlock(b *types.Block) {
 }
 
 // purgeBlock purges a block from cache, make sure this block is already saved
-// in blockdb.
+// in db.
 func (s *chainStatus) purgeBlock(b *types.Block) error {
 	if b.Hash != s.blocks[0].Hash || s.nextOutputIndex <= 0 {
 		return ErrPurgeNotDeliveredBlock
diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/lattice.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/lattice.go
index e578e3f4f..8780bbaec 100644
--- a/vendor/github.com/dexon-foundation/dexon-consensus/core/lattice.go
+++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/lattice.go
@@ -23,7 +23,7 @@ import (
 	"time"
 
 	"github.com/dexon-foundation/dexon-consensus/common"
-	"github.com/dexon-foundation/dexon-consensus/core/blockdb"
+	"github.com/dexon-foundation/dexon-consensus/core/db"
 	"github.com/dexon-foundation/dexon-consensus/core/types"
 )
 
@@ -53,7 +53,7 @@ func NewLattice(
 	authModule *Authenticator,
 	app Application,
 	debug Debug,
-	db blockdb.BlockDatabase,
+	db db.Database,
 	logger common.Logger) *Lattice {
 
 	// Create genesis latticeDataConfig.
@@ -304,21 +304,21 @@ func (l *Lattice) AppendConfig(round uint64, config *types.Config) (err error) {
 }
 
 // ProcessFinalizedBlock is used for syncing lattice data.
-func (l *Lattice) ProcessFinalizedBlock(b *types.Block) {
+func (l *Lattice) ProcessFinalizedBlock(b *types.Block) ([]*types.Block, error) {
 	l.lock.Lock()
 	defer l.lock.Unlock()
 	// Syncing state for core.latticeData module.
 	if err := l.data.addFinalizedBlock(b); err != nil {
-		panic(err)
+		return nil, err
 	}
 	l.pool.purgeBlocks(b.Position.ChainID, b.Position.Height)
 	// Syncing state for core.totalOrdering module.
 	toDelivered, deliveredMode, err := l.toModule.processBlock(b)
 	if err != nil {
-		panic(err)
+		return nil, err
 	}
 	if len(toDelivered) == 0 {
-		return
+		return nil, nil
 	}
 	hashes := make(common.Hashes, len(toDelivered))
 	for idx := range toDelivered {
@@ -329,7 +329,7 @@ func (l *Lattice) ProcessFinalizedBlock(b *types.Block) {
 	}
 	// Sync core.consensusTimestamp module.
 	if err = l.ctModule.processBlocks(toDelivered); err != nil {
-		panic(err)
+		return nil, err
 	}
-	return
+	return toDelivered, nil
 }
diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/nonblocking.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/nonblocking.go
index f94d3c631..56c42fec6 100644
--- a/vendor/github.com/dexon-foundation/dexon-consensus/core/nonblocking.go
+++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/nonblocking.go
@@ -44,7 +44,7 @@ type blockDeliveredEvent struct {
 // them that makes the methods to be non-blocking.
 //  - Application
 //  - Debug
-//  - It also provides nonblockig for blockdb update.
+//  - It also provides nonblockig for db update.
 type nonBlocking struct {
 	app          Application
 	debug        Debug
@@ -75,7 +75,7 @@ func (nb *nonBlocking) addEvent(event interface{}) {
 
 func (nb *nonBlocking) run() {
 	// This go routine consume the first event from events and call the
-	// corresponding methods of Application/Debug/blockdb.
+	// corresponding methods of Application/Debug/db.
 	for {
 		var event interface{}
 		func() {
diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/total-ordering.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/total-ordering.go
index 52f927005..3bf6946ae 100644
--- a/vendor/github.com/dexon-foundation/dexon-consensus/core/total-ordering.go
+++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/total-ordering.go
@@ -535,11 +535,13 @@ type totalOrderingGlobalVector struct {
 	cachedCandidateInfo *totalOrderingCandidateInfo
 }
 
-func newTotalOrderingGlobalVector(numChains uint32) *totalOrderingGlobalVector {
+func newTotalOrderingGlobalVector(
+	initRound uint64, numChains uint32) *totalOrderingGlobalVector {
 	return &totalOrderingGlobalVector{
 		blocks:      make([][]*types.Block, numChains),
 		tips:        make([]*types.Block, numChains),
 		breakpoints: make([][]*totalOrderingBreakpoint, numChains),
+		curRound:    initRound,
 	}
 }
 
@@ -792,14 +794,14 @@ type totalOrdering struct {
 }
 
 // newTotalOrdering constructs an totalOrdering instance.
-func newTotalOrdering(dMoment time.Time, round uint64, cfg *types.Config) *totalOrdering {
+func newTotalOrdering(
+	dMoment time.Time, round uint64, cfg *types.Config) *totalOrdering {
 	config := &totalOrderingConfig{}
 	config.fromConfig(round, cfg)
 	config.setRoundBeginTime(dMoment)
 	candidates := make([]*totalOrderingCandidateInfo, config.numChains)
 	to := &totalOrdering{
 		pendings:              make(map[common.Hash]*types.Block),
-		globalVector:          newTotalOrderingGlobalVector(config.numChains),
 		dirtyChainIDs:         make([]int, 0, config.numChains),
 		acked:                 make(map[common.Hash]map[common.Hash]struct{}),
 		objCache:              newTotalOrderingObjectCache(config.numChains),
@@ -807,6 +809,8 @@ func newTotalOrdering(dMoment time.Time, round uint64, cfg *types.Config) *total
 		candidates:            candidates,
 		candidateChainIDs:     make([]uint32, 0, config.numChains),
 		curRound:              config.roundID,
+		globalVector: newTotalOrderingGlobalVector(
+			config.roundID, config.numChains),
 	}
 	to.configs = []*totalOrderingConfig{config}
 	return to
@@ -898,7 +902,8 @@ func (to *totalOrdering) clean(b *types.Block) {
 }
 
 // updateVectors is a helper function to update all cached vectors.
-func (to *totalOrdering) updateVectors(b *types.Block) (isOldest bool, err error) {
+func (to *totalOrdering) updateVectors(
+	b *types.Block) (isOldest bool, err error) {
 	var (
 		candidateHash common.Hash
 		chainID       uint32
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 bc5e33636..2ef243757 100644
--- a/vendor/github.com/dexon-foundation/dexon-consensus/core/utils.go
+++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils.go
@@ -219,3 +219,15 @@ func DiffUint64(a, b uint64) uint64 {
 	}
 	return b - a
 }
+
+func isCI() bool {
+	return os.Getenv("CI") != ""
+}
+
+func isCircleCI() bool {
+	return isCI() && os.Getenv("CIRCLECI") == "true"
+}
+
+func isTravisCI() bool {
+	return isCI() && os.Getenv("TRAVIS") == "true"
+}
diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/nodeset-cache.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/nodeset-cache.go
index a8f8fe58f..6d4f7b0ba 100644
--- a/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/nodeset-cache.go
+++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/nodeset-cache.go
@@ -27,8 +27,12 @@ import (
 )
 
 var (
-	// ErrRoundNotReady means we got nil config.
-	ErrRoundNotReady = errors.New("round is not ready")
+	// ErrNodeSetNotReady means we got nil empty node set.
+	ErrNodeSetNotReady = errors.New("node set is not ready")
+	// ErrCRSNotReady means we got empty CRS.
+	ErrCRSNotReady = errors.New("crs is not ready")
+	// ErrConfigurationNotReady means we go nil configuration.
+	ErrConfigurationNotReady = errors.New("configuration is not ready")
 	// ErrInvalidChainID means the chain ID is unexpected.
 	ErrInvalidChainID = errors.New("invalid chain id")
 )
@@ -172,16 +176,15 @@ func (cache *NodeSetCache) update(
 	cache.lock.Lock()
 	defer cache.lock.Unlock()
 
-	// Get the requested round.
+	// Get information for the requested round.
 	keySet := cache.nsIntf.NodeSet(round)
 	if keySet == nil {
-		// That round is not ready yet.
-		err = ErrRoundNotReady
+		err = ErrNodeSetNotReady
 		return
 	}
 	crs := cache.nsIntf.CRS(round)
 	if (crs == common.Hash{}) {
-		err = ErrRoundNotReady
+		err = ErrCRSNotReady
 		return
 	}
 	// Cache new round.
@@ -199,6 +202,10 @@ func (cache *NodeSetCache) update(
 		}
 	}
 	cfg := cache.nsIntf.Configuration(round)
+	if cfg == nil {
+		err = ErrConfigurationNotReady
+		return
+	}
 	nIDs = &sets{
 		nodeSet:   nodeSet,
 		notarySet: make([]map[types.NodeID]struct{}, cfg.NumChains),
diff --git a/vendor/vendor.json b/vendor/vendor.json
index 0eab5926c..81119dc09 100644
--- a/vendor/vendor.json
+++ b/vendor/vendor.json
@@ -105,14 +105,14 @@
 		{
 			"checksumSHA1": "65L1yf+f0OCiLFniljqfRxVdsQA=",
 			"path": "github.com/dexon-foundation/dexon-consensus/common",
-			"revision": "56e872f84131348adbc0861afb3554bba4a8e5db",
-			"revisionTime": "2018-12-05T06:29:54Z"
+			"revision": "0ead4a7c012af9ddaa4a934729e216539d2caeb1",
+			"revisionTime": "2018-12-13T03:01:43Z"
 		},
 		{
-			"checksumSHA1": "YWywKLu6YqxtRpXbCls4lRxjgPo=",
+			"checksumSHA1": "7Oa+i0v4Xtpk+mA1ANSwPzOZrZo=",
 			"path": "github.com/dexon-foundation/dexon-consensus/core",
-			"revision": "56e872f84131348adbc0861afb3554bba4a8e5db",
-			"revisionTime": "2018-12-05T06:29:54Z"
+			"revision": "0ead4a7c012af9ddaa4a934729e216539d2caeb1",
+			"revisionTime": "2018-12-13T03:01:43Z"
 		},
 		{
 			"checksumSHA1": "v4fKR7uhoyufi6hAVO44cFEb+tY=",
@@ -123,38 +123,44 @@
 		{
 			"checksumSHA1": "tQSbYCu5P00lUhKsx3IbBZCuSLY=",
 			"path": "github.com/dexon-foundation/dexon-consensus/core/crypto",
-			"revision": "56e872f84131348adbc0861afb3554bba4a8e5db",
-			"revisionTime": "2018-12-05T06:29:54Z"
+			"revision": "0ead4a7c012af9ddaa4a934729e216539d2caeb1",
+			"revisionTime": "2018-12-13T03:01:43Z"
 		},
 		{
 			"checksumSHA1": "p2jOAulavUU2xyj018pYPHlj8XA=",
 			"path": "github.com/dexon-foundation/dexon-consensus/core/crypto/dkg",
-			"revision": "56e872f84131348adbc0861afb3554bba4a8e5db",
-			"revisionTime": "2018-12-05T06:29:54Z"
+			"revision": "0ead4a7c012af9ddaa4a934729e216539d2caeb1",
+			"revisionTime": "2018-12-13T03:01:43Z"
 		},
 		{
 			"checksumSHA1": "6Pf6caC8LTNCI7IflFmglKYnxYo=",
 			"path": "github.com/dexon-foundation/dexon-consensus/core/crypto/ecdsa",
-			"revision": "56e872f84131348adbc0861afb3554bba4a8e5db",
-			"revisionTime": "2018-12-05T06:29:54Z"
+			"revision": "0ead4a7c012af9ddaa4a934729e216539d2caeb1",
+			"revisionTime": "2018-12-13T03:01:43Z"
+		},
+		{
+			"checksumSHA1": "oE4WEMp92OrJrujzd3XdQEkPiDI=",
+			"path": "github.com/dexon-foundation/dexon-consensus/core/db",
+			"revision": "0ead4a7c012af9ddaa4a934729e216539d2caeb1",
+			"revisionTime": "2018-12-13T03:01:43Z"
 		},
 		{
 			"checksumSHA1": "Z079qQV+aQV9A3kSJ0LbFjx5VO4=",
 			"path": "github.com/dexon-foundation/dexon-consensus/core/types",
-			"revision": "56e872f84131348adbc0861afb3554bba4a8e5db",
-			"revisionTime": "2018-12-05T06:29:54Z"
+			"revision": "0ead4a7c012af9ddaa4a934729e216539d2caeb1",
+			"revisionTime": "2018-12-13T03:01:43Z"
 		},
 		{
 			"checksumSHA1": "Sn3PAYsblIXmr7gVKDzxnoBPku4=",
 			"path": "github.com/dexon-foundation/dexon-consensus/core/types/dkg",
-			"revision": "56e872f84131348adbc0861afb3554bba4a8e5db",
-			"revisionTime": "2018-12-05T06:29:54Z"
+			"revision": "0ead4a7c012af9ddaa4a934729e216539d2caeb1",
+			"revisionTime": "2018-12-13T03:01:43Z"
 		},
 		{
-			"checksumSHA1": "pE0L1qyJ7Jyir1SQ6jEsj8U+83U=",
+			"checksumSHA1": "A7UQ+7rv9FuElmFBEn/ZdhBqFKI=",
 			"path": "github.com/dexon-foundation/dexon-consensus/core/utils",
-			"revision": "56e872f84131348adbc0861afb3554bba4a8e5db",
-			"revisionTime": "2018-12-05T06:29:54Z"
+			"revision": "0ead4a7c012af9ddaa4a934729e216539d2caeb1",
+			"revisionTime": "2018-12-13T03:01:43Z"
 		},
 		{
 			"checksumSHA1": "TAkwduKZqLyimyTPPWIllZWYFuE=",
-- 
cgit v1.2.3