aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJimmy Hu <jimmy.hu@dexon.org>2019-04-01 18:01:26 +0800
committerWei-Ning Huang <w@dexon.org>2019-04-09 21:32:59 +0800
commita2436b50ae570eb92afd836ca93005b60f6e0e21 (patch)
treee2d393eff22c7e32ea118d6f798ff14266664d28
parentf30474a07847c4406601bf045250ac18630dc484 (diff)
downloaddexon-a2436b50ae570eb92afd836ca93005b60f6e0e21.tar.gz
dexon-a2436b50ae570eb92afd836ca93005b60f6e0e21.tar.zst
dexon-a2436b50ae570eb92afd836ca93005b60f6e0e21.zip
vendor: sync to latest core (#320)
* vendor: sync to latest core * dex, core: fix conflict x
-rw-r--r--consensus/dexcon/fake_dexcon.go10
-rw-r--r--core/headerchain.go8
-rw-r--r--dex/app.go26
-rw-r--r--dex/app_test.go18
-rw-r--r--dex/blockproposer.go12
-rw-r--r--dex/cache.go1
-rw-r--r--dex/cache_test.go42
-rw-r--r--dex/handler.go5
-rw-r--r--dex/protocol_test.go12
-rw-r--r--vendor/github.com/dexon-foundation/dexon-consensus/common/utils.go10
-rw-r--r--vendor/github.com/dexon-foundation/dexon-consensus/core/agreement-mgr.go9
-rw-r--r--vendor/github.com/dexon-foundation/dexon-consensus/core/agreement.go4
-rw-r--r--vendor/github.com/dexon-foundation/dexon-consensus/core/blockchain.go84
-rw-r--r--vendor/github.com/dexon-foundation/dexon-consensus/core/consensus.go83
-rw-r--r--vendor/github.com/dexon-foundation/dexon-consensus/core/constant.go4
-rw-r--r--vendor/github.com/dexon-foundation/dexon-consensus/core/db/level-db.go2
-rw-r--r--vendor/github.com/dexon-foundation/dexon-consensus/core/interfaces.go3
-rw-r--r--vendor/github.com/dexon-foundation/dexon-consensus/core/nonblocking.go8
-rw-r--r--vendor/github.com/dexon-foundation/dexon-consensus/core/syncer/agreement.go34
-rw-r--r--vendor/github.com/dexon-foundation/dexon-consensus/core/syncer/consensus.go30
-rw-r--r--vendor/github.com/dexon-foundation/dexon-consensus/core/types/block-randomness.go11
-rw-r--r--vendor/github.com/dexon-foundation/dexon-consensus/core/types/block.go144
-rw-r--r--vendor/github.com/dexon-foundation/dexon-consensus/core/utils/round-event.go43
-rw-r--r--vendor/github.com/dexon-foundation/dexon-consensus/core/utils/utils.go13
-rw-r--r--vendor/vendor.json52
25 files changed, 275 insertions, 393 deletions
diff --git a/consensus/dexcon/fake_dexcon.go b/consensus/dexcon/fake_dexcon.go
index ae7bed90e..430d9bc6b 100644
--- a/consensus/dexcon/fake_dexcon.go
+++ b/consensus/dexcon/fake_dexcon.go
@@ -3,7 +3,6 @@ package dexcon
import (
"crypto/ecdsa"
"math/big"
- "time"
coreCommon "github.com/dexon-foundation/dexon-consensus/common"
dexCore "github.com/dexon-foundation/dexon-consensus/core"
@@ -54,15 +53,8 @@ func (f *FakeDexcon) Prepare(chain consensus.ChainReader, header *types.Header)
}
}
- parentCoreBlockHash, err := coreUtils.HashBlock(&parentCoreBlock)
- if err != nil {
- return err
- }
randomness := f.nodes.Randomness(header.Round, common.Hash(blockHash))
- coreBlock.Finalization.ParentHash = parentCoreBlockHash
- coreBlock.Finalization.Randomness = randomness
- coreBlock.Finalization.Timestamp = time.Now().UTC()
- coreBlock.Finalization.Height = parentHeader.Number.Uint64()
+ coreBlock.Randomness = randomness
dexconMeta, err := rlp.EncodeToBytes(&coreBlock)
if err != nil {
diff --git a/core/headerchain.go b/core/headerchain.go
index 0c2000064..b6aa66b60 100644
--- a/core/headerchain.go
+++ b/core/headerchain.go
@@ -535,15 +535,15 @@ func (hc *HeaderChain) verifyDexonHeader(header *types.Header,
}
}
- if header.Time != uint64(coreBlock.Finalization.Timestamp.UnixNano()/1000000) {
+ if header.Time != uint64(coreBlock.Timestamp.UnixNano()/1000000) {
return fmt.Errorf("timestamp mismatch")
}
- if header.Number.Uint64() != coreBlock.Finalization.Height {
+ if header.Number.Uint64() != coreBlock.Position.Height {
return fmt.Errorf("height mismatch")
}
- if !reflect.DeepEqual(header.Randomness, coreBlock.Finalization.Randomness) {
+ if !reflect.DeepEqual(header.Randomness, coreBlock.Randomness) {
return fmt.Errorf("randomness mismatch")
}
@@ -562,7 +562,7 @@ func (hc *HeaderChain) verifyTSig(coreBlock *coreTypes.Block,
verifierCache *dexCore.TSigVerifierCache) error {
round := coreBlock.Position.Round
- randomness := coreBlock.Finalization.Randomness
+ randomness := coreBlock.Randomness
if round == 0 {
return nil
diff --git a/dex/app.go b/dex/app.go
index 9a72d7795..5a268a09d 100644
--- a/dex/app.go
+++ b/dex/app.go
@@ -162,9 +162,9 @@ func (d *DexconApp) preparePayload(ctx context.Context, position coreTypes.Posit
default:
}
- // deliver height = position height + 1
- if d.deliveredHeight+d.undeliveredNum != position.Height {
- return nil, fmt.Errorf("expected height %d but get %d", d.deliveredHeight+d.undeliveredNum, position.Height)
+ // deliver height + 1 = position height
+ if d.deliveredHeight+d.undeliveredNum+1 != position.Height {
+ return nil, fmt.Errorf("expected height %d but get %d", d.deliveredHeight+d.undeliveredNum+1, position.Height)
}
deliveredBlock := d.blockchain.GetBlockByNumber(d.deliveredHeight)
@@ -308,8 +308,8 @@ func (d *DexconApp) VerifyBlock(block *coreTypes.Block) coreTypes.BlockVerifySta
d.appMu.RLock()
defer d.appMu.RUnlock()
- // deliver height = position height + 1
- if d.deliveredHeight+d.undeliveredNum != block.Position.Height {
+ // deliver height + 1 = position height
+ if d.deliveredHeight+d.undeliveredNum+1 != block.Position.Height {
return coreTypes.VerifyRetryLater
}
@@ -414,10 +414,10 @@ func (d *DexconApp) VerifyBlock(block *coreTypes.Block) coreTypes.BlockVerifySta
func (d *DexconApp) BlockDelivered(
blockHash coreCommon.Hash,
blockPosition coreTypes.Position,
- result coreTypes.FinalizationResult) {
+ rand []byte) {
- log.Debug("DexconApp block deliver", "height", result.Height, "hash", blockHash, "position", blockPosition.String())
- defer log.Debug("DexconApp block delivered", "height", result.Height, "hash", blockHash, "position", blockPosition.String())
+ log.Debug("DexconApp block deliver", "hash", blockHash, "position", blockPosition.String())
+ defer log.Debug("DexconApp block delivered", "hash", blockHash, "position", blockPosition.String())
d.appMu.Lock()
defer d.appMu.Unlock()
@@ -428,7 +428,7 @@ func (d *DexconApp) BlockDelivered(
}
block.Payload = nil
- block.Finalization = result
+ block.Randomness = rand
dexconMeta, err := rlp.EncodeToBytes(block)
if err != nil {
panic(err)
@@ -445,14 +445,14 @@ func (d *DexconApp) BlockDelivered(
}
newBlock := types.NewBlock(&types.Header{
- Number: new(big.Int).SetUint64(result.Height),
- Time: big.NewInt(result.Timestamp.UnixNano() / 1000000),
+ Number: new(big.Int).SetUint64(block.Position.Height),
+ Time: uint64(block.Timestamp.UnixNano() / 1000000),
Coinbase: owner,
GasLimit: d.gov.DexconConfiguration(block.Position.Round).BlockGasLimit,
Difficulty: big.NewInt(1),
Round: block.Position.Round,
DexconMeta: dexconMeta,
- Randomness: result.Randomness,
+ Randomness: block.Randomness,
}, txs, nil, nil)
if block.IsEmpty() {
@@ -470,7 +470,7 @@ func (d *DexconApp) BlockDelivered(
}
d.removeConfirmedBlock(blockHash)
- d.deliveredHeight = result.Height
+ d.deliveredHeight = block.Position.Height
// New blocks are finalized, notify other components.
go d.finalizedBlockFeed.Send(core.NewFinalizedBlockEvent{Block: d.blockchain.CurrentBlock()})
diff --git a/dex/app_test.go b/dex/app_test.go
index e648abdbd..652aaa0b2 100644
--- a/dex/app_test.go
+++ b/dex/app_test.go
@@ -39,7 +39,7 @@ type App interface {
PrepareWitness(height uint64) (witness coreTypes.Witness, err error)
VerifyBlock(block *coreTypes.Block) coreTypes.BlockVerifyStatus
BlockConfirmed(block coreTypes.Block)
- BlockDelivered(blockHash coreCommon.Hash, position coreTypes.Position, result coreTypes.FinalizationResult)
+ BlockDelivered(blockHash coreCommon.Hash, position coreTypes.Position, rand []byte)
SubscribeNewFinalizedBlockEvent(ch chan<- core.NewFinalizedBlockEvent) event.Subscription
Stop()
}
@@ -268,7 +268,7 @@ func (f *ConfigFactory) Run() {
go f.center.DeliverProduct(makerName(f.name),
&PositionProduct{position: coreTypes.Position{
Round: 0,
- Height: 0,
+ Height: coreTypes.GenesisHeight,
}})
f.initialized = true
@@ -1634,15 +1634,11 @@ func (f *BlockConfirmedFactory) Run() {
block := f.convertProduct(product)
block.ProposerID = coreTypes.NewNodeID(f.masterKey.PublicKey())
+ block.Timestamp = time.Now()
f.stopTimeMu.RLock()
f.App.BlockConfirmed(block)
f.stopTimeMu.RUnlock()
- block.Finalization = coreTypes.FinalizationResult{
- Timestamp: time.Now(),
- Height: block.Position.Height + 1,
- }
-
f.center.DeliverProduct(makerName(f.name), &BlockConfirmedProduct{
block: block,
})
@@ -1916,7 +1912,7 @@ func (f *BlockDeliveredFactory) Run() {
block := f.convertProduct(product)
f.stopTimeMu.RLock()
- f.App.BlockDelivered(block.Hash, block.Position, block.Finalization)
+ f.App.BlockDelivered(block.Hash, block.Position, block.Randomness)
f.stopTimeMu.RUnlock()
}
}
@@ -1987,7 +1983,7 @@ func (t *bdBlockHashTester) ViewAndRecord(product Product) {
func (t bdBlockHashTester) InputsForTest(product Product) []reflect.Value {
block := product.(*BlockConfirmedProduct).block
return []reflect.Value{reflect.ValueOf(coreCommon.Hash{}), reflect.ValueOf(block.Position),
- reflect.ValueOf(block.Finalization)}
+ reflect.ValueOf(block.Randomness)}
}
func (t *bdBlockHashTester) ValidateResults(results []reflect.Value) error {
@@ -2042,7 +2038,7 @@ func (t *bdBlockDeliveredTester) ViewAndRecord(product Product) {
case *BlockConfirmedProduct:
app := t.App.(*DexconApp)
block := product.(*BlockConfirmedProduct).block
- t.expectHeight = block.Position.Height + 1
+ t.expectHeight = block.Position.Height
var txs []*types.Transaction
_, txs = app.getConfirmedBlockByHash(block.Hash)
@@ -2079,7 +2075,7 @@ func (t *bdBlockDeliveredTester) ViewAndRecord(product Product) {
func (t bdBlockDeliveredTester) InputsForTest(product Product) []reflect.Value {
block := product.(*BlockConfirmedProduct).block
return []reflect.Value{reflect.ValueOf(block.Hash), reflect.ValueOf(block.Position),
- reflect.ValueOf(block.Finalization)}
+ reflect.ValueOf(block.Randomness)}
}
func (t *bdBlockDeliveredTester) ValidateResults(results []reflect.Value) error {
diff --git a/dex/blockproposer.go b/dex/blockproposer.go
index 846e65617..c035eda7c 100644
--- a/dex/blockproposer.go
+++ b/dex/blockproposer.go
@@ -172,13 +172,13 @@ Loop:
b.watchCat.Feed(blocks[len(blocks)-1].Position)
log.Debug("Filling compaction chain", "num", len(blocks),
- "first", blocks[0].Finalization.Height,
- "last", blocks[len(blocks)-1].Finalization.Height)
+ "first", blocks[0].Position.Height,
+ "last", blocks[len(blocks)-1].Position.Height)
if _, err := consensusSync.SyncBlocks(blocks, false); err != nil {
log.Debug("SyncBlocks fail", "err", err)
return nil, err
}
- coreHeight = blocks[len(blocks)-1].Finalization.Height
+ coreHeight = blocks[len(blocks)-1].Position.Height
select {
case <-b.stopCh:
@@ -203,8 +203,8 @@ ListenLoop:
if len(blocks) > 0 {
b.watchCat.Feed(blocks[len(blocks)-1].Position)
log.Debug("Filling compaction chain", "num", len(blocks),
- "first", blocks[0].Finalization.Height,
- "last", blocks[len(blocks)-1].Finalization.Height)
+ "first", blocks[0].Position.Height,
+ "last", blocks[len(blocks)-1].Position.Height)
synced, err := consensusSync.SyncBlocks(blocks, true)
if err != nil {
log.Error("SyncBlocks fail", "err", err)
@@ -215,7 +215,7 @@ ListenLoop:
log.Debug("Consensus core synced")
break ListenLoop
}
- coreHeight = blocks[len(blocks)-1].Finalization.Height
+ coreHeight = blocks[len(blocks)-1].Position.Height
}
case <-sub.Err():
log.Debug("System stopped when syncing consensus core")
diff --git a/dex/cache.go b/dex/cache.go
index 04030eaaf..951657fae 100644
--- a/dex/cache.go
+++ b/dex/cache.go
@@ -99,7 +99,6 @@ func (c *cache) addBlock(block *coreTypes.Block) {
c.lock.Lock()
defer c.lock.Unlock()
block = block.Clone()
- block.Finalization.Height = 0
if len(c.blockCache) >= c.size {
// Randomly delete one entry.
for k := range c.blockCache {
diff --git a/dex/cache_test.go b/dex/cache_test.go
index 22b1b9b26..b06effafb 100644
--- a/dex/cache_test.go
+++ b/dex/cache_test.go
@@ -216,37 +216,29 @@ func TestCacheFinalizedBlock(t *testing.T) {
Position: coreTypes.Position{
Height: 1,
},
- Hash: coreCommon.NewRandomHash(),
- Finalization: coreTypes.FinalizationResult{
- Randomness: randomBytes(),
- },
+ Hash: coreCommon.NewRandomHash(),
+ Randomness: randomBytes(),
}
block2 := &coreTypes.Block{
Position: coreTypes.Position{
Height: 2,
},
- Hash: coreCommon.NewRandomHash(),
- Finalization: coreTypes.FinalizationResult{
- Randomness: randomBytes(),
- },
+ Hash: coreCommon.NewRandomHash(),
+ Randomness: randomBytes(),
}
block3 := &coreTypes.Block{
Position: coreTypes.Position{
Height: 3,
},
- Hash: coreCommon.NewRandomHash(),
- Finalization: coreTypes.FinalizationResult{
- Randomness: randomBytes(),
- },
+ Hash: coreCommon.NewRandomHash(),
+ Randomness: randomBytes(),
}
block4 := &coreTypes.Block{
Position: coreTypes.Position{
Height: 4,
},
- Hash: coreCommon.NewRandomHash(),
- Finalization: coreTypes.FinalizationResult{
- Randomness: randomBytes(),
- },
+ Hash: coreCommon.NewRandomHash(),
+ Randomness: randomBytes(),
}
cache.addFinalizedBlock(block1)
cache.addFinalizedBlock(block2)
@@ -291,18 +283,18 @@ func TestCacheFinalizedBlock(t *testing.T) {
}
}
finalizedBlock5 := block5.Clone()
- finalizedBlock5.Finalization.Randomness = randomBytes()
+ finalizedBlock5.Randomness = randomBytes()
cache.addFinalizedBlock(finalizedBlock5)
block = cache.finalizedBlock(block5.Position)
if block == nil {
t.Errorf("expecting block %s in cache", finalizedBlock5)
}
if !reflect.DeepEqual(
- block.Finalization.Randomness,
- finalizedBlock5.Finalization.Randomness) {
+ block.Randomness,
+ finalizedBlock5.Randomness) {
t.Errorf("mismatch randomness, have %s, want %s",
- block.Finalization.Randomness,
- finalizedBlock5.Finalization.Randomness)
+ block.Randomness,
+ finalizedBlock5.Randomness)
}
blocks = cache.blocks(coreCommon.Hashes{block5.Hash})
if len(blocks) != 1 {
@@ -312,11 +304,11 @@ func TestCacheFinalizedBlock(t *testing.T) {
t.Errorf("get wrong block: have %s, want %s", blocks[0], block5)
}
if !reflect.DeepEqual(
- blocks[0].Finalization.Randomness,
- finalizedBlock5.Finalization.Randomness) {
+ blocks[0].Randomness,
+ finalizedBlock5.Randomness) {
t.Errorf("mismatch randomness, have %s, want %s",
- blocks[0].Finalization.Randomness,
- finalizedBlock5.Finalization.Randomness)
+ blocks[0].Randomness,
+ finalizedBlock5.Randomness)
}
}
}
diff --git a/dex/handler.go b/dex/handler.go
index 6395c4113..61e382610 100644
--- a/dex/handler.go
+++ b/dex/handler.go
@@ -1083,7 +1083,7 @@ func (pm *ProtocolManager) BroadcastRecords(records []*enr.Record) {
// BroadcastFinalizedBlock broadcasts the finalized core block to some of its peers.
func (pm *ProtocolManager) BroadcastFinalizedBlock(block *coreTypes.Block) {
- if len(block.Finalization.Randomness) == 0 {
+ if len(block.Randomness) == 0 {
log.Warn("Ignore broadcast finalized block without randomness", "block", block)
return
}
@@ -1132,8 +1132,7 @@ func (pm *ProtocolManager) BroadcastAgreementResult(
agreement *coreTypes.AgreementResult) {
block := pm.cache.blocks(coreCommon.Hashes{agreement.BlockHash})
if len(block) != 0 {
- block[0].Finalization.Height = agreement.FinalizationHeight
- block[0].Finalization.Randomness = agreement.Randomness
+ block[0].Randomness = agreement.Randomness
pm.cache.addFinalizedBlock(block[0])
}
diff --git a/dex/protocol_test.go b/dex/protocol_test.go
index 7e0e1a9a4..d6bebc18a 100644
--- a/dex/protocol_test.go
+++ b/dex/protocol_test.go
@@ -334,11 +334,7 @@ func TestRecvCoreBlocks(t *testing.T) {
Height: 13,
Data: []byte{4, 4, 4, 4, 4},
},
- Finalization: coreTypes.FinalizationResult{
- Randomness: []byte{5, 5, 5, 5, 5},
- Timestamp: time.Now().UTC(),
- Height: 13,
- },
+ Randomness: []byte{5, 5, 5, 5, 5},
Signature: coreCrypto.Signature{
Type: "signature",
Signature: []byte("signature"),
@@ -387,11 +383,7 @@ func TestSendCoreBlocks(t *testing.T) {
Height: 13,
Data: []byte{4, 4, 4, 4, 4},
},
- Finalization: coreTypes.FinalizationResult{
- Randomness: []byte{5, 5, 5, 5, 5},
- Timestamp: time.Now().UTC(),
- Height: 13,
- },
+ Randomness: []byte{5, 5, 5, 5, 5},
Signature: coreCrypto.Signature{
Type: "signature",
Signature: []byte("signature"),
diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/common/utils.go b/vendor/github.com/dexon-foundation/dexon-consensus/common/utils.go
index e46b3e9c9..0e847900f 100644
--- a/vendor/github.com/dexon-foundation/dexon-consensus/common/utils.go
+++ b/vendor/github.com/dexon-foundation/dexon-consensus/common/utils.go
@@ -29,3 +29,13 @@ func GenerateRandomBytes() []byte {
}
return randomness
}
+
+// CopyBytes copies byte slice.
+func CopyBytes(src []byte) (dst []byte) {
+ if len(src) == 0 {
+ return
+ }
+ dst = make([]byte, len(src))
+ copy(dst, src)
+ return
+}
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 7006242b1..423174c48 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
@@ -116,8 +116,7 @@ type agreementMgr struct {
lock sync.RWMutex
}
-func newAgreementMgr(con *Consensus,
- initConfig agreementMgrConfig) (mgr *agreementMgr, err error) {
+func newAgreementMgr(con *Consensus) (mgr *agreementMgr, err error) {
mgr = &agreementMgr{
con: con,
ID: con.ID,
@@ -130,7 +129,6 @@ func newAgreementMgr(con *Consensus,
bcModule: con.bcModule,
ctx: con.ctx,
processedBAResult: make(map[types.Position]struct{}, maxResultCache),
- configs: []agreementMgrConfig{initConfig},
voteFilter: utils.NewVoteFilter(),
}
mgr.recv = &consensusBAReceiver{
@@ -199,11 +197,6 @@ func (mgr *agreementMgr) notifyRoundEvents(evts []utils.RoundEventParam) error {
if len(mgr.configs) > 0 {
lastCfg := mgr.configs[len(mgr.configs)-1]
if e.BeginHeight != lastCfg.RoundEndHeight() {
- // the init config of BA part is provided when constructing.
- if len(mgr.configs) == 1 &&
- e.BeginHeight == lastCfg.LastPeriodBeginHeight() {
- return nil
- }
return ErrInvalidBlockHeight
}
if lastCfg.RoundID() == e.Round {
diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement.go
index 6727ecbee..f2a9e3def 100644
--- a/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement.go
+++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement.go
@@ -419,8 +419,8 @@ func (a *agreement) processVote(vote *types.Vote) error {
aID := a.agreementID()
// Agreement module has stopped.
if isStop(aID) {
- // Hacky way to not drop first votes for height 0.
- if vote.Position.Height == uint64(0) {
+ // Hacky way to not drop first votes for genesis height.
+ if vote.Position.Height == types.GenesisHeight {
a.pendingVote = append(a.pendingVote, pendingVote{
vote: vote,
receivedTime: time.Now().UTC(),
diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/blockchain.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/blockchain.go
index 51747d83b..2d67d626f 100644
--- a/vendor/github.com/dexon-foundation/dexon-consensus/core/blockchain.go
+++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/blockchain.go
@@ -18,6 +18,7 @@
package core
import (
+ "bytes"
"errors"
"fmt"
"sort"
@@ -38,6 +39,7 @@ var (
ErrIncorrectParentHash = errors.New("incorrect parent hash")
ErrInvalidBlockHeight = errors.New("invalid block height")
ErrInvalidRoundID = errors.New("invalid round id")
+ ErrInvalidTimestamp = errors.New("invalid timestamp")
ErrNotFollowTipPosition = errors.New("not follow tip position")
ErrDuplicatedPendingBlock = errors.New("duplicated pending block")
ErrRetrySanityCheckLater = errors.New("retry sanity check later")
@@ -182,12 +184,13 @@ func (bc *blockChain) notifyRoundEvents(evts []utils.RoundEventParam) error {
c.SetRoundBeginHeight(e.BeginHeight)
if bc.lastConfirmed == nil {
if c.RoundID() != 0 {
- panic(fmt.Errorf("genesis config should from round 0 %d",
+ panic(fmt.Errorf(
+ "genesis config should from round 0, but %d",
c.RoundID()))
}
} else {
if c.RoundID() != bc.lastConfirmed.Position.Round {
- panic(fmt.Errorf("incompatible config/block %s %d",
+ panic(fmt.Errorf("incompatible config/block round %s %d",
bc.lastConfirmed, c.RoundID()))
}
if !c.Contains(bc.lastConfirmed.Position.Height) {
@@ -224,15 +227,11 @@ func (bc *blockChain) extractBlocks() (ret []*types.Block) {
for len(bc.confirmedBlocks) > 0 {
c := bc.confirmedBlocks[0]
if c.Position.Round >= DKGDelayRound &&
- len(c.Finalization.Randomness) == 0 &&
+ len(c.Randomness) == 0 &&
!bc.setRandomnessFromPending(c) {
break
}
c, bc.confirmedBlocks = bc.confirmedBlocks[0], bc.confirmedBlocks[1:]
- // TODO(mission): remove these duplicated field if we fully converted
- // to single chain.
- c.Finalization.ParentHash = c.ParentHash
- c.Finalization.Timestamp = c.Timestamp
ret = append(ret, c)
bc.lastDelivered = c
}
@@ -240,9 +239,6 @@ func (bc *blockChain) extractBlocks() (ret []*types.Block) {
}
func (bc *blockChain) sanityCheck(b *types.Block) error {
- if b.IsEmpty() {
- panic(fmt.Errorf("pass empty block to sanity check: %s", b))
- }
bc.lock.RLock()
defer bc.lock.RUnlock()
if bc.lastConfirmed == nil {
@@ -250,7 +246,9 @@ func (bc *blockChain) sanityCheck(b *types.Block) error {
if !b.IsGenesis() {
return ErrNotGenesisBlock
}
- // TODO(mission): Do we have to check timestamp of genesis block?
+ if b.Timestamp.Before(bc.dMoment.Add(bc.configs[0].minBlockInterval)) {
+ return ErrInvalidTimestamp
+ }
return nil
}
if b.IsGenesis() {
@@ -275,6 +273,10 @@ func (bc *blockChain) sanityCheck(b *types.Block) error {
if !b.ParentHash.Equal(bc.lastConfirmed.Hash) {
return ErrIncorrectParentHash
}
+ if b.Timestamp.Before(bc.lastConfirmed.Timestamp.Add(
+ tipConfig.minBlockInterval)) {
+ return ErrInvalidTimestamp
+ }
if err := utils.VerifyBlockSignature(b); err != nil {
return err
}
@@ -293,7 +295,6 @@ func (bc *blockChain) addEmptyBlock(position types.Position) (
// to be confirmed.
panic(err)
}
- emptyB.Finalization.Height = emptyB.Position.Height + 1
bc.confirmBlock(emptyB)
bc.checkIfBlocksConfirmed()
return emptyB
@@ -308,8 +309,10 @@ func (bc *blockChain) addEmptyBlock(position types.Position) (
if bc.lastConfirmed.Position.Height+1 == position.Height {
return add(), nil
}
- } else if position.Height == 0 && position.Round == 0 {
+ } else if position.Height == types.GenesisHeight && position.Round == 0 {
return add(), nil
+ } else {
+ return nil, ErrInvalidBlockHeight
}
return nil, bc.addPendingBlockRecord(pendingBlockRecord{position, nil})
}
@@ -318,7 +321,7 @@ func (bc *blockChain) addEmptyBlock(position types.Position) (
// sanity check against this block, it's ok to add block with skipping height.
func (bc *blockChain) addBlock(b *types.Block) error {
if b.Position.Round >= DKGDelayRound &&
- len(b.Finalization.Randomness) == 0 &&
+ len(b.Randomness) == 0 &&
!bc.setRandomnessFromPending(b) {
return ErrMissingRandomness
}
@@ -346,8 +349,6 @@ func (bc *blockChain) addBlock(b *types.Block) error {
return nil
}
-// TODO(mission): remove this method after removing the strong binding between
-// BA and blockchain.
func (bc *blockChain) tipRound() uint64 {
bc.lock.RLock()
defer bc.lock.RUnlock()
@@ -361,8 +362,6 @@ func (bc *blockChain) tipRound() uint64 {
return bc.lastConfirmed.Position.Round + offset
}
-// TODO(mission): the pulling should be done inside of blockchain, then we don't
-// have to expose this method.
func (bc *blockChain) confirmed(h uint64) bool {
bc.lock.RLock()
defer bc.lock.RUnlock()
@@ -376,8 +375,6 @@ func (bc *blockChain) confirmed(h uint64) bool {
return r.block != nil
}
-// TODO(mission): this method can be removed after refining the relation between
-// BA and block storage.
func (bc *blockChain) nextBlock() (uint64, time.Time) {
bc.lock.RLock()
defer bc.lock.RUnlock()
@@ -385,7 +382,7 @@ func (bc *blockChain) nextBlock() (uint64, time.Time) {
// lastConfirmed block in the scenario of "nextBlock" method.
tip, config := bc.lastConfirmed, bc.configs[0]
if tip == nil {
- return 0, bc.dMoment
+ return types.GenesisHeight, bc.dMoment
}
return tip.Position.Height + 1, tip.Timestamp.Add(config.minBlockInterval)
}
@@ -396,7 +393,7 @@ func (bc *blockChain) pendingBlocksWithoutRandomness() []*types.Block {
blocks := make([]*types.Block, 0)
for _, b := range bc.confirmedBlocks {
if b.Position.Round < DKGDelayRound ||
- len(b.Finalization.Randomness) > 0 ||
+ len(b.Randomness) > 0 ||
bc.setRandomnessFromPending(b) {
continue
}
@@ -407,7 +404,7 @@ func (bc *blockChain) pendingBlocksWithoutRandomness() []*types.Block {
continue
}
if r.block != nil &&
- len(r.block.Finalization.Randomness) == 0 &&
+ len(r.block.Randomness) == 0 &&
!bc.setRandomnessFromPending(r.block) {
blocks = append(blocks, r.block)
}
@@ -452,8 +449,8 @@ func (bc *blockChain) findPendingBlock(p types.Position) *types.Block {
func (bc *blockChain) addPendingBlockRecord(p pendingBlockRecord) error {
if err := bc.pendingBlocks.insert(p); err != nil {
if err == ErrDuplicatedPendingBlock {
- // TODO(mission): stop ignoreing this error once our BA can confirm
- // blocks uniquely and sequentially.
+ // We need to ignore this error because BA might confirm duplicated
+ // blocks in position.
err = nil
}
return err
@@ -501,7 +498,7 @@ func (bc *blockChain) purgeConfig() {
func (bc *blockChain) verifyRandomness(
blockHash common.Hash, round uint64, randomness []byte) (bool, error) {
if round < DKGDelayRound {
- return len(randomness) == 0, nil
+ return bytes.Compare(randomness, NoRand) == 0, nil
}
v, ok, err := bc.vGetter.UpdateAndGet(round)
if err != nil {
@@ -517,17 +514,23 @@ func (bc *blockChain) verifyRandomness(
func (bc *blockChain) prepareBlock(position types.Position,
proposeTime time.Time, empty bool) (b *types.Block, err error) {
- // TODO(mission): refine timestamp.
b = &types.Block{Position: position, Timestamp: proposeTime}
tip := bc.lastConfirmed
// Make sure we can propose a block at expected position for callers.
if tip == nil {
- // The case for genesis block.
- if !position.Equal(types.Position{}) {
+ if bc.configs[0].RoundID() != uint64(0) {
+ panic(fmt.Errorf(
+ "Genesis config should be ready when preparing genesis: %d",
+ bc.configs[0].RoundID()))
+ }
+ // It should be the case for genesis block.
+ if !position.Equal(types.Position{Height: types.GenesisHeight}) {
b, err = nil, ErrNotGenesisBlock
return
- } else if empty {
- b.Timestamp = bc.dMoment
+ }
+ minExpectedTime := bc.dMoment.Add(bc.configs[0].minBlockInterval)
+ if empty {
+ b.Timestamp = minExpectedTime
} else {
bc.logger.Debug("Calling genesis Application.PreparePayload")
if b.Payload, err = bc.app.PreparePayload(b.Position); err != nil {
@@ -539,6 +542,9 @@ func (bc *blockChain) prepareBlock(position types.Position,
b = nil
return
}
+ if proposeTime.Before(minExpectedTime) {
+ b.Timestamp = minExpectedTime
+ }
}
} else {
tipConfig := bc.tipConfig()
@@ -548,11 +554,8 @@ func (bc *blockChain) prepareBlock(position types.Position,
}
if tipConfig.IsLastBlock(tip) {
if tip.Position.Round+1 != position.Round {
- if !empty {
- b, err = nil, ErrRoundNotSwitch
- return
- }
- b.Position.Round = tip.Position.Round + 1
+ b, err = nil, ErrRoundNotSwitch
+ return
}
} else {
if tip.Position.Round != position.Round {
@@ -560,6 +563,7 @@ func (bc *blockChain) prepareBlock(position types.Position,
return
}
}
+ minExpectedTime := tip.Timestamp.Add(bc.configs[0].minBlockInterval)
b.ParentHash = tip.Hash
if !empty {
bc.logger.Debug("Calling Application.PreparePayload",
@@ -575,14 +579,14 @@ func (bc *blockChain) prepareBlock(position types.Position,
b = nil
return
}
- if !b.Timestamp.After(tip.Timestamp) {
- b.Timestamp = tip.Timestamp.Add(tipConfig.minBlockInterval)
+ if b.Timestamp.Before(minExpectedTime) {
+ b.Timestamp = minExpectedTime
}
} else {
b.Witness.Height = tip.Witness.Height
b.Witness.Data = make([]byte, len(tip.Witness.Data))
copy(b.Witness.Data, tip.Witness.Data)
- b.Timestamp = tip.Timestamp.Add(tipConfig.minBlockInterval)
+ b.Timestamp = minExpectedTime
}
}
if empty {
@@ -628,7 +632,7 @@ func (bc *blockChain) setRandomnessFromPending(b *types.Block) bool {
if !r.BlockHash.Equal(b.Hash) {
panic(fmt.Errorf("mismathed randomness: %s %s", b, r))
}
- b.Finalization.Randomness = r.Randomness
+ b.Randomness = r.Randomness
delete(bc.pendingRandomnesses, b.Position)
return true
}
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 6e3072371..57b30383c 100644
--- a/vendor/github.com/dexon-foundation/dexon-consensus/core/consensus.go
+++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/consensus.go
@@ -60,7 +60,6 @@ var (
// consensusBAReceiver implements agreementReceiver.
type consensusBAReceiver struct {
- // TODO(mission): consensus would be replaced by blockChain and network.
consensus *Consensus
agreementModule *agreement
changeNotaryHeightValue *atomic.Value
@@ -262,10 +261,7 @@ func (recv *consensusBAReceiver) ConfirmBlock(
}
}
- // It's a workaround, the height for application is one-based.
- block.Finalization.Height = block.Position.Height + 1
-
- if len(votes) == 0 && len(block.Finalization.Randomness) == 0 {
+ if len(votes) == 0 && len(block.Randomness) == 0 {
recv.consensus.logger.Error("No votes to recover randomness",
"block", block)
} else if votes != nil {
@@ -293,18 +289,19 @@ func (recv *consensusBAReceiver) ConfirmBlock(
"block", block,
"error", err)
} else {
- block.Finalization.Randomness = rand.Signature[:]
+ block.Randomness = rand.Signature[:]
}
+ } else {
+ block.Randomness = NoRand
}
if recv.isNotary {
result := &types.AgreementResult{
- BlockHash: block.Hash,
- Position: block.Position,
- Votes: voteList,
- FinalizationHeight: block.Finalization.Height,
- IsEmptyBlock: isEmptyBlockConfirmed,
- Randomness: block.Finalization.Randomness,
+ BlockHash: block.Hash,
+ Position: block.Position,
+ Votes: voteList,
+ IsEmptyBlock: isEmptyBlockConfirmed,
+ Randomness: block.Randomness,
}
recv.consensus.logger.Debug("Broadcast AgreementResult",
"result", result)
@@ -327,7 +324,7 @@ func (recv *consensusBAReceiver) ConfirmBlock(
}
}
- if block.Position.Height != 0 &&
+ if !block.IsGenesis() &&
!recv.consensus.bcModule.confirmed(block.Position.Height-1) {
go func(hash common.Hash) {
parentHash := hash
@@ -362,16 +359,15 @@ func (recv *consensusBAReceiver) ConfirmBlock(
recv.consensus.logger.Info("Receive parent block",
"parent-hash", block.ParentHash.String()[:6],
"cur-position", block.Position)
- if block.Finalization.Height == 0 {
+ if !block.IsFinalized() {
// TODO(jimmy): use a seperate message to pull finalized
// block. Here, we pull it again as workaround.
continue
}
recv.consensus.processBlockChan <- block
parentHash = block.ParentHash
- if block.Position.Height == 0 ||
- recv.consensus.bcModule.confirmed(
- block.Position.Height-1) {
+ if block.IsGenesis() || recv.consensus.bcModule.confirmed(
+ block.Position.Height-1) {
return
}
}
@@ -646,9 +642,11 @@ func NewConsensusFromSyncer(
refBlock = b
}
if startWithEmpty {
- pos := initBlock.Position
- pos.Height++
- _, err := con.bcModule.addEmptyBlock(pos)
+ emptyPos := types.Position{
+ Round: con.bcModule.tipRound(),
+ Height: initBlock.Position.Height + 1,
+ }
+ _, err := con.bcModule.addEmptyBlock(emptyPos)
if err != nil {
panic(err)
}
@@ -657,7 +655,6 @@ func NewConsensusFromSyncer(
}
// newConsensusForRound creates a Consensus instance.
-// TODO(mission): remove dMoment, it's no longer one part of consensus.
func newConsensusForRound(
initBlock *types.Block,
dMoment time.Time,
@@ -678,14 +675,13 @@ func newConsensusForRound(
debugApp = a
}
// Get configuration for bootstrap round.
- initRound := uint64(0)
- initBlockHeight := uint64(0)
+ initPos := types.Position{
+ Round: 0,
+ Height: types.GenesisHeight,
+ }
if initBlock != nil {
- initRound = initBlock.Position.Round
- initBlockHeight = initBlock.Position.Height
+ initPos = initBlock.Position
}
- initConfig := utils.GetConfigWithPanic(gov, initRound, logger)
- initCRS := utils.GetCRSWithPanic(gov, initRound, logger)
// Init configuration chain.
ID := types.NewNodeID(prv.PublicKey())
recv := &consensusDKGReceiver{
@@ -729,21 +725,12 @@ func newConsensusForRound(
}
con.ctx, con.ctxCancel = context.WithCancel(context.Background())
var err error
- con.roundEvent, err = utils.NewRoundEvent(con.ctx, gov, logger, initRound,
- initBlockHeight, ConfigRoundShift)
+ con.roundEvent, err = utils.NewRoundEvent(con.ctx, gov, logger, initPos,
+ ConfigRoundShift)
if err != nil {
panic(err)
}
- baConfig := agreementMgrConfig{}
- baConfig.from(initRound, initConfig, initCRS)
- // TODO(jimmy): remove -1 after we match the height with fullnode.
- roundHeight := gov.GetRoundHeight(initRound)
- if initRound > 0 {
- roundHeight--
- }
- baConfig.SetRoundBeginHeight(roundHeight)
- con.baMgr, err = newAgreementMgr(con, baConfig)
- if err != nil {
+ if con.baMgr, err = newAgreementMgr(con); err != nil {
panic(err)
}
if err = con.prepare(initBlock); err != nil {
@@ -907,9 +894,6 @@ func (con *Consensus) prepare(initBlock *types.Block) (err error) {
con.roundEvent.Register(func(evts []utils.RoundEventParam) {
e := evts[len(evts)-1]
defer elapse("touch-NodeSetCache", e)()
- if e.Reset != 0 {
- return
- }
con.event.RegisterHeight(e.NextTouchNodeSetCacheHeight(), func(uint64) {
if err := con.nodeSetCache.Touch(e.Round + 1); err != nil {
con.logger.Warn("Failed to update nodeSetCache",
@@ -997,7 +981,7 @@ func (con *Consensus) prepare(initBlock *types.Block) (err error) {
})
con.roundEvent.TriggerInitEvent()
if initBlock != nil {
- con.event.NotifyHeight(initBlock.Finalization.Height)
+ con.event.NotifyHeight(initBlock.Position.Height)
}
con.baMgr.prepare()
return
@@ -1265,7 +1249,7 @@ MessageLoop:
}
} else {
ok, err := con.bcModule.verifyRandomness(
- val.Hash, val.Position.Round, val.Finalization.Randomness)
+ val.Hash, val.Position.Round, val.Randomness)
if err != nil {
con.logger.Error("error verifying confirmed block randomness",
"block", val,
@@ -1395,7 +1379,7 @@ func (con *Consensus) processFinalizedBlock(b *types.Block) (err error) {
}
if !verifier.VerifySignature(b.Hash, crypto.Signature{
Type: "bls",
- Signature: b.Finalization.Randomness,
+ Signature: b.Randomness,
}) {
err = ErrIncorrectBlockRandomness
return
@@ -1441,16 +1425,15 @@ func (con *Consensus) deliverBlock(b *types.Block) {
case con.resetDeliveryGuardTicker <- struct{}{}:
default:
}
- // TODO(mission): do we need to put block when confirmed now?
if err := con.db.PutBlock(*b); err != nil {
panic(err)
}
- if err := con.db.PutCompactionChainTipInfo(
- b.Hash, b.Finalization.Height); err != nil {
+ if err := con.db.PutCompactionChainTipInfo(b.Hash,
+ b.Position.Height); err != nil {
panic(err)
}
con.logger.Debug("Calling Application.BlockDelivered", "block", b)
- con.app.BlockDelivered(b.Hash, b.Position, b.Finalization.Clone())
+ con.app.BlockDelivered(b.Hash, b.Position, common.CopyBytes(b.Randomness))
if con.debugApp != nil {
con.debugApp.BlockReady(b.Hash)
}
@@ -1471,7 +1454,7 @@ func (con *Consensus) deliverFinalizedBlocksWithoutLock() (err error) {
"pending", con.bcModule.lastPendingBlock())
for _, b := range deliveredBlocks {
con.deliverBlock(b)
- con.event.NotifyHeight(b.Finalization.Height)
+ con.event.NotifyHeight(b.Position.Height)
}
return
}
diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/constant.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/constant.go
index f80e1b9d8..29dae8b73 100644
--- a/vendor/github.com/dexon-foundation/dexon-consensus/core/constant.go
+++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/constant.go
@@ -32,6 +32,10 @@ const ConfigRoundShift uint64 = 2
// have neither DKG nor CRS.
const DKGDelayRound uint64 = 1
+// NoRand is the magic placeholder for randomness field in blocks for blocks
+// proposed before DKGDelayRound.
+var NoRand = []byte("norand")
+
func init() {
utils.SetDKGDelayRound(DKGDelayRound)
}
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 88f5801fc..52968331e 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
@@ -362,7 +362,6 @@ func (lvl *LevelDBBackedDB) Close() error {
func (lvl *LevelDBBackedDB) HasBlock(hash common.Hash) bool {
exists, err := lvl.internalHasBlock(lvl.getBlockKey(hash))
if err != nil {
- // TODO(missionliao): Modify the interface to return error.
panic(err)
}
return exists
@@ -429,7 +428,6 @@ func (lvl *LevelDBBackedDB) PutBlock(block types.Block) (err error) {
// 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/interfaces.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/interfaces.go
index 407eaeace..f76ee1975 100644
--- a/vendor/github.com/dexon-foundation/dexon-consensus/core/interfaces.go
+++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/interfaces.go
@@ -42,8 +42,7 @@ type Application interface {
BlockConfirmed(block types.Block)
// BlockDelivered is called when a block is added to the compaction chain.
- BlockDelivered(blockHash common.Hash,
- blockPosition types.Position, result types.FinalizationResult)
+ BlockDelivered(hash common.Hash, position types.Position, rand []byte)
}
// Debug describes the application interface that requires
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 095170bf0..10b47b822 100644
--- a/vendor/github.com/dexon-foundation/dexon-consensus/core/nonblocking.go
+++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/nonblocking.go
@@ -32,7 +32,7 @@ type blockConfirmedEvent struct {
type blockDeliveredEvent struct {
blockHash common.Hash
blockPosition types.Position
- result *types.FinalizationResult
+ rand []byte
}
// nonBlocking implements these interfaces and is a decorator for
@@ -87,7 +87,7 @@ func (nb *nonBlocking) run() {
case blockConfirmedEvent:
nb.app.BlockConfirmed(*e.block)
case blockDeliveredEvent:
- nb.app.BlockDelivered(e.blockHash, e.blockPosition, *e.result)
+ nb.app.BlockDelivered(e.blockHash, e.blockPosition, e.rand)
default:
fmt.Printf("Unknown event %v.", e)
}
@@ -128,10 +128,10 @@ func (nb *nonBlocking) BlockConfirmed(block types.Block) {
// BlockDelivered is called when a block is add to the compaction chain.
func (nb *nonBlocking) BlockDelivered(blockHash common.Hash,
- blockPosition types.Position, result types.FinalizationResult) {
+ blockPosition types.Position, rand []byte) {
nb.addEvent(blockDeliveredEvent{
blockHash: blockHash,
blockPosition: blockPosition,
- result: &result,
+ rand: rand,
})
}
diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/syncer/agreement.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/syncer/agreement.go
index 13da027bd..d39c24627 100644
--- a/vendor/github.com/dexon-foundation/dexon-consensus/core/syncer/agreement.go
+++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/syncer/agreement.go
@@ -18,6 +18,7 @@
package syncer
import (
+ "bytes"
"context"
"fmt"
"time"
@@ -87,7 +88,7 @@ func (a *agreement) run() {
}
switch v := val.(type) {
case *types.Block:
- if v.IsFinalized() {
+ if v.Position.Round >= core.DKGDelayRound && v.IsFinalized() {
a.processFinalizedBlock(v)
} else {
a.processBlock(v)
@@ -106,9 +107,8 @@ func (a *agreement) processBlock(b *types.Block) {
return
}
if rand, exist := a.agreementResults[b.Hash]; exist {
- if b.Position.Round >= core.DKGDelayRound &&
- len(b.Finalization.Randomness) == 0 {
- b.Finalization.Randomness = rand
+ if len(b.Randomness) == 0 {
+ b.Randomness = rand
}
a.confirm(b)
} else {
@@ -120,9 +120,6 @@ func (a *agreement) processBlock(b *types.Block) {
}
func (a *agreement) processFinalizedBlock(block *types.Block) {
- if block.Position.Round < core.DKGDelayRound {
- return
- }
// Cache those results that CRS is not ready yet.
if _, exists := a.confirmedBlocks[block.Hash]; exists {
a.logger.Trace("finalized block already confirmed", "block", block)
@@ -141,7 +138,8 @@ func (a *agreement) processFinalizedBlock(block *types.Block) {
if err := utils.VerifyBlockSignature(block); err != nil {
return
}
- verifier, ok, err := a.tsigVerifierCache.UpdateAndGet(block.Position.Round)
+ verifier, ok, err := a.tsigVerifierCache.UpdateAndGet(
+ block.Position.Round)
if err != nil {
a.logger.Error("error verifying block randomness",
"block", block,
@@ -154,7 +152,7 @@ func (a *agreement) processFinalizedBlock(block *types.Block) {
}
if !verifier.VerifySignature(block.Hash, crypto.Signature{
Type: "bls",
- Signature: block.Finalization.Randomness,
+ Signature: block.Randomness,
}) {
a.logger.Error("incorrect block randomness", "block", block)
return
@@ -203,13 +201,17 @@ func (a *agreement) processAgreementResult(r *types.AgreementResult) {
a.logger.Error("incorrect agreement result randomness", "result", r)
return
}
+ } else {
+ // Special case for rounds before DKGDelayRound.
+ if bytes.Compare(r.Randomness, core.NoRand) != 0 {
+ a.logger.Error("incorrect agreement result randomness", "result", r)
+ return
+ }
}
if r.IsEmptyBlock {
b := &types.Block{
- Position: r.Position,
- Finalization: types.FinalizationResult{
- Randomness: r.Randomness,
- },
+ Position: r.Position,
+ Randomness: r.Randomness,
}
// Empty blocks should be confirmed directly, they won't be sent over
// the wire.
@@ -218,7 +220,7 @@ func (a *agreement) processAgreementResult(r *types.AgreementResult) {
}
if bs, exist := a.blocks[r.Position]; exist {
if b, exist := bs[r.BlockHash]; exist {
- b.Finalization.Randomness = r.Randomness
+ b.Randomness = r.Randomness
a.confirm(b)
return
}
@@ -271,11 +273,9 @@ func (a *agreement) processNewCRS(round uint64) {
// confirm notifies consensus the confirmation of a block in BA.
func (a *agreement) confirm(b *types.Block) {
- if b.Position.Round >= core.DKGDelayRound &&
- len(b.Finalization.Randomness) == 0 {
+ if !b.IsFinalized() {
panic(fmt.Errorf("confirm a block %s without randomness", b))
}
- b.Finalization.Height = b.Position.Height + 1
if _, exist := a.confirmedBlocks[b.Hash]; !exist {
delete(a.blocks, b.Position)
delete(a.agreementResults, b.Hash)
diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/syncer/consensus.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/syncer/consensus.go
index b692b56ef..f777e35bb 100644
--- a/vendor/github.com/dexon-foundation/dexon-consensus/core/syncer/consensus.go
+++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/syncer/consensus.go
@@ -42,13 +42,9 @@ var (
// ErrInvalidBlockOrder is reported when SyncBlocks receives unordered
// blocks.
ErrInvalidBlockOrder = fmt.Errorf("invalid block order")
- // ErrMismatchBlockHashSequence means the delivering sequence is not
- // correct, compared to finalized blocks.
- ErrMismatchBlockHashSequence = fmt.Errorf("mismatch block hash sequence")
- // ErrInvalidSyncingFinalizationHeight raised when the blocks to sync is
- // not following the compaction chain tip in database.
- ErrInvalidSyncingFinalizationHeight = fmt.Errorf(
- "invalid syncing finalization height")
+ // ErrInvalidSyncingHeight raised when the blocks to sync is not following
+ // the compaction chain tip in database.
+ ErrInvalidSyncingHeight = fmt.Errorf("invalid syncing height")
)
// Consensus is for syncing consensus module.
@@ -150,13 +146,12 @@ func (con *Consensus) assureBuffering() {
)
if height == 0 {
con.roundEvt, err = utils.NewRoundEvent(con.ctx, con.gov, con.logger,
- 0, 0, core.ConfigRoundShift)
+ types.Position{}, core.ConfigRoundShift)
} else {
var b types.Block
if b, err = con.db.GetBlock(blockHash); err == nil {
con.roundEvt, err = utils.NewRoundEvent(con.ctx, con.gov,
- con.logger, b.Position.Round, b.Finalization.Height,
- core.ConfigRoundShift)
+ con.logger, b.Position, core.ConfigRoundShift)
}
}
if err != nil {
@@ -297,7 +292,7 @@ func (con *Consensus) SyncBlocks(
}
// Check if blocks are consecutive.
for i := 1; i < len(blocks); i++ {
- if blocks[i].Finalization.Height != blocks[i-1].Finalization.Height+1 {
+ if blocks[i].Position.Height != blocks[i-1].Position.Height+1 {
err = ErrInvalidBlockOrder
return
}
@@ -305,17 +300,16 @@ func (con *Consensus) SyncBlocks(
// Make sure the first block is the next block of current compaction chain
// tip in DB.
_, tipHeight := con.db.GetCompactionChainTipInfo()
- if blocks[0].Finalization.Height != tipHeight+1 {
- con.logger.Error("Mismatched finalization height",
- "now", blocks[0].Finalization.Height,
+ if blocks[0].Position.Height != tipHeight+1 {
+ con.logger.Error("Mismatched block height",
+ "now", blocks[0].Position.Height,
"expected", tipHeight+1,
)
- err = ErrInvalidSyncingFinalizationHeight
+ err = ErrInvalidSyncingHeight
return
}
con.logger.Trace("SyncBlocks",
"position", &blocks[0].Position,
- "final height", blocks[0].Finalization.Height,
"len", len(blocks),
"latest", latest,
)
@@ -331,10 +325,10 @@ func (con *Consensus) SyncBlocks(
}
}
if err = con.db.PutCompactionChainTipInfo(
- b.Hash, b.Finalization.Height); err != nil {
+ b.Hash, b.Position.Height); err != nil {
return
}
- con.heightEvt.NotifyHeight(b.Finalization.Height)
+ con.heightEvt.NotifyHeight(b.Position.Height)
}
if latest {
con.assureBuffering()
diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/types/block-randomness.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/block-randomness.go
index b87e8a11d..1c7454398 100644
--- a/vendor/github.com/dexon-foundation/dexon-consensus/core/types/block-randomness.go
+++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/block-randomness.go
@@ -26,12 +26,11 @@ import (
// AgreementResult describes an agremeent result.
type AgreementResult struct {
- BlockHash common.Hash `json:"block_hash"`
- Position Position `json:"position"`
- Votes []Vote `json:"votes"`
- IsEmptyBlock bool `json:"is_empty_block"`
- FinalizationHeight uint64 `json:"finalization_height"`
- Randomness []byte `json:"randomness"`
+ BlockHash common.Hash `json:"block_hash"`
+ Position Position `json:"position"`
+ Votes []Vote `json:"votes"`
+ IsEmptyBlock bool `json:"is_empty_block"`
+ Randomness []byte `json:"randomness"`
}
func (r *AgreementResult) String() string {
diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/types/block.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/block.go
index 2b23e96e3..cff954652 100644
--- a/vendor/github.com/dexon-foundation/dexon-consensus/core/types/block.go
+++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/block.go
@@ -31,6 +31,9 @@ import (
"github.com/dexon-foundation/dexon-consensus/core/crypto"
)
+// GenesisHeight refers to the initial height the genesis block should be.
+const GenesisHeight uint64 = 1
+
// BlockVerifyStatus is the return code for core.Application.VerifyBlock
type BlockVerifyStatus int
@@ -64,58 +67,6 @@ func (t *rlpTimestamp) DecodeRLP(s *rlp.Stream) error {
return err
}
-// FinalizationResult represents the result of DEXON consensus algorithm.
-type FinalizationResult struct {
- ParentHash common.Hash `json:"parent_hash"`
- Randomness []byte `json:"randomness"`
- Timestamp time.Time `json:"timestamp"`
- Height uint64 `json:"height"`
-}
-
-// Clone returns a deep copy of FinalizationResult
-func (f FinalizationResult) Clone() FinalizationResult {
- frcopy := FinalizationResult{
- ParentHash: f.ParentHash,
- Timestamp: f.Timestamp,
- Height: f.Height,
- }
- frcopy.Randomness = make([]byte, len(f.Randomness))
- copy(frcopy.Randomness, f.Randomness)
- return frcopy
-}
-
-type rlpFinalizationResult struct {
- ParentHash common.Hash
- Randomness []byte
- Timestamp *rlpTimestamp
- Height uint64
-}
-
-// EncodeRLP implements rlp.Encoder
-func (f *FinalizationResult) EncodeRLP(w io.Writer) error {
- return rlp.Encode(w, &rlpFinalizationResult{
- ParentHash: f.ParentHash,
- Randomness: f.Randomness,
- Timestamp: &rlpTimestamp{f.Timestamp},
- Height: f.Height,
- })
-}
-
-// DecodeRLP implements rlp.Decoder
-func (f *FinalizationResult) DecodeRLP(s *rlp.Stream) error {
- var dec rlpFinalizationResult
- err := s.Decode(&dec)
- if err == nil {
- *f = FinalizationResult{
- ParentHash: dec.ParentHash,
- Randomness: dec.Randomness,
- Timestamp: dec.Timestamp.Time,
- Height: dec.Height,
- }
- }
- return err
-}
-
// Witness represents the consensus information on the compaction chain.
type Witness struct {
Height uint64 `json:"height"`
@@ -124,31 +75,31 @@ type Witness struct {
// Block represents a single event broadcasted on the network.
type Block struct {
- ProposerID NodeID `json:"proposer_id"`
- ParentHash common.Hash `json:"parent_hash"`
- Hash common.Hash `json:"hash"`
- Position Position `json:"position"`
- Timestamp time.Time `json:"timestamp"`
- Payload []byte `json:"payload"`
- PayloadHash common.Hash `json:"payload_hash"`
- Witness Witness `json:"witness"`
- Finalization FinalizationResult `json:"finalization"`
- Signature crypto.Signature `json:"signature"`
+ ProposerID NodeID `json:"proposer_id"`
+ ParentHash common.Hash `json:"parent_hash"`
+ Hash common.Hash `json:"hash"`
+ Position Position `json:"position"`
+ Timestamp time.Time `json:"timestamp"`
+ Payload []byte `json:"payload"`
+ PayloadHash common.Hash `json:"payload_hash"`
+ Witness Witness `json:"witness"`
+ Randomness []byte `json:"finalization"`
+ Signature crypto.Signature `json:"signature"`
CRSSignature crypto.Signature `json:"crs_signature"`
}
type rlpBlock struct {
- ProposerID NodeID
- ParentHash common.Hash
- Hash common.Hash
- Position Position
- Timestamp *rlpTimestamp
- Payload []byte
- PayloadHash common.Hash
- Witness *Witness
- Finalization *FinalizationResult
- Signature crypto.Signature
+ ProposerID NodeID
+ ParentHash common.Hash
+ Hash common.Hash
+ Position Position
+ Timestamp *rlpTimestamp
+ Payload []byte
+ PayloadHash common.Hash
+ Witness *Witness
+ Randomness []byte
+ Signature crypto.Signature
CRSSignature crypto.Signature
}
@@ -164,7 +115,7 @@ func (b *Block) EncodeRLP(w io.Writer) error {
Payload: b.Payload,
PayloadHash: b.PayloadHash,
Witness: &b.Witness,
- Finalization: &b.Finalization,
+ Randomness: b.Randomness,
Signature: b.Signature,
CRSSignature: b.CRSSignature,
})
@@ -184,7 +135,7 @@ func (b *Block) DecodeRLP(s *rlp.Stream) error {
Payload: dec.Payload,
PayloadHash: dec.PayloadHash,
Witness: *dec.Witness,
- Finalization: *dec.Finalization,
+ Randomness: dec.Randomness,
Signature: dec.Signature,
CRSSignature: dec.CRSSignature,
}
@@ -206,25 +157,23 @@ func (b *Block) Clone() (bcopy *Block) {
bcopy.Position.Height = b.Position.Height
bcopy.Signature = b.Signature.Clone()
bcopy.CRSSignature = b.CRSSignature.Clone()
- bcopy.Finalization = b.Finalization.Clone()
bcopy.Witness.Height = b.Witness.Height
- bcopy.Witness.Data = make([]byte, len(b.Witness.Data))
- copy(bcopy.Witness.Data, b.Witness.Data)
+ bcopy.Witness.Data = common.CopyBytes(b.Witness.Data)
bcopy.Timestamp = b.Timestamp
- bcopy.Payload = make([]byte, len(b.Payload))
- copy(bcopy.Payload, b.Payload)
+ bcopy.Payload = common.CopyBytes(b.Payload)
bcopy.PayloadHash = b.PayloadHash
+ bcopy.Randomness = common.CopyBytes(b.Randomness)
return
}
// IsGenesis checks if the block is a genesisBlock
func (b *Block) IsGenesis() bool {
- return b.Position.Height == 0 && b.ParentHash == common.Hash{}
+ return b.Position.Height == GenesisHeight && b.ParentHash == common.Hash{}
}
-// IsFinalized checks if the finalization data is ready.
+// IsFinalized checks if the block is finalized.
func (b *Block) IsFinalized() bool {
- return b.Finalization.Height != 0
+ return len(b.Randomness) > 0
}
// IsEmpty checks if the block is an 'empty block'.
@@ -276,34 +225,3 @@ func (bs *BlocksByPosition) Pop() (ret interface{}) {
*bs, ret = (*bs)[0:n-1], (*bs)[n-1]
return
}
-
-// BlocksByFinalizationHeight is the helper type for sorting slice of blocks by
-// finalization height.
-type BlocksByFinalizationHeight []*Block
-
-// Len implements Len method in sort.Sort interface.
-func (bs BlocksByFinalizationHeight) Len() int {
- return len(bs)
-}
-
-// Less implements Less method in sort.Sort interface.
-func (bs BlocksByFinalizationHeight) Less(i int, j int) bool {
- return bs[i].Finalization.Height < bs[j].Finalization.Height
-}
-
-// Swap implements Swap method in sort.Sort interface.
-func (bs BlocksByFinalizationHeight) Swap(i int, j int) {
- bs[i], bs[j] = bs[j], bs[i]
-}
-
-// Push implements Push method in heap interface.
-func (bs *BlocksByFinalizationHeight) Push(x interface{}) {
- *bs = append(*bs, x.(*Block))
-}
-
-// Pop implements Pop method in heap interface.
-func (bs *BlocksByFinalizationHeight) Pop() (ret interface{}) {
- n := len(*bs)
- *bs, ret = (*bs)[0:n-1], (*bs)[n-1]
- return
-}
diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/round-event.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/round-event.go
index 0e70cf250..472c7247b 100644
--- a/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/round-event.go
+++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/round-event.go
@@ -169,42 +169,39 @@ type RoundEvent struct {
// NewRoundEvent creates an RoundEvent instance.
func NewRoundEvent(parentCtx context.Context, gov governanceAccessor,
- logger common.Logger, initRound uint64,
- initBlockHeight uint64,
- roundShift uint64) (*RoundEvent, error) {
+ logger common.Logger, initPos types.Position, roundShift uint64) (
+ *RoundEvent, error) {
// We need to generate valid ending block height of this round (taken
// DKG reset count into consideration).
- initConfig := GetConfigWithPanic(gov, initRound, logger)
+ logger.Info("new RoundEvent", "position", initPos, "shift", roundShift)
+ initConfig := GetConfigWithPanic(gov, initPos.Round, logger)
e := &RoundEvent{
gov: gov,
logger: logger,
- lastTriggeredRound: initRound,
+ lastTriggeredRound: initPos.Round,
roundShift: roundShift,
}
e.ctx, e.ctxCancel = context.WithCancel(parentCtx)
e.config = RoundBasedConfig{}
- e.config.SetupRoundBasedFields(initRound, initConfig)
- // TODO(jimmy): remove -1 after we match the height with fullnode.
- roundHeight := gov.GetRoundHeight(initRound)
- if initRound != 0 {
- roundHeight--
- }
- e.config.SetRoundBeginHeight(roundHeight)
+ e.config.SetupRoundBasedFields(initPos.Round, initConfig)
+ e.config.SetRoundBeginHeight(GetRoundHeight(gov, initPos.Round))
// Make sure the DKG reset count in current governance can cover the initial
// block height.
- resetCount := gov.DKGResetCount(initRound + 1)
- remains := resetCount
- for ; remains > 0 && !e.config.Contains(initBlockHeight); remains-- {
- e.config.ExtendLength()
- }
- if !e.config.Contains(initBlockHeight) {
- return nil, ErrUnmatchedBlockHeightWithConfig{
- round: initRound,
- reset: resetCount,
- blockHeight: initBlockHeight,
+ if initPos.Height >= types.GenesisHeight {
+ resetCount := gov.DKGResetCount(initPos.Round + 1)
+ remains := resetCount
+ for ; remains > 0 && !e.config.Contains(initPos.Height); remains-- {
+ e.config.ExtendLength()
+ }
+ if !e.config.Contains(initPos.Height) {
+ return nil, ErrUnmatchedBlockHeightWithConfig{
+ round: initPos.Round,
+ reset: resetCount,
+ blockHeight: initPos.Height,
+ }
}
+ e.lastTriggeredResetCount = resetCount - remains
}
- e.lastTriggeredResetCount = resetCount - remains
return e, nil
}
diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/utils.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/utils.go
index 9a4ae923b..e6739ce2b 100644
--- a/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/utils.go
+++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/utils.go
@@ -149,3 +149,16 @@ func GetDKGValidThreshold(config *types.Config) int {
func GetNextRoundValidationHeight(begin, length uint64) uint64 {
return begin + length*9/10
}
+
+// GetRoundHeight wraps the workaround for the round height logic in fullnode.
+func GetRoundHeight(accessor interface{}, round uint64) uint64 {
+ type roundHeightAccessor interface {
+ GetRoundHeight(round uint64) uint64
+ }
+ accessorInst := accessor.(roundHeightAccessor)
+ height := accessorInst.GetRoundHeight(round)
+ if round == 0 && height < types.GenesisHeight {
+ return types.GenesisHeight
+ }
+ return height
+}
diff --git a/vendor/vendor.json b/vendor/vendor.json
index 659de1a33..a3182f836 100644
--- a/vendor/vendor.json
+++ b/vendor/vendor.json
@@ -139,18 +139,18 @@
"versionExact": "dev"
},
{
- "checksumSHA1": "8EuKVkP1v/w5fRuuvUaXX5k/F+I=",
+ "checksumSHA1": "In6vBHYUsX7DUIGiFN2hQggBgvI=",
"path": "github.com/dexon-foundation/dexon-consensus/common",
- "revision": "a69376bd9d144c462ae2b577c8147e96e4a60553",
- "revisionTime": "2019-03-29T07:18:33Z",
+ "revision": "ecc5e12b1ac4826e302607769f5b831ab4c27046",
+ "revisionTime": "2019-04-01T04:25:09Z",
"version": "single-chain",
"versionExact": "single-chain"
},
{
- "checksumSHA1": "sz6Y25/7bPgDZLBywY4wgqYuczs=",
+ "checksumSHA1": "fE4+Jlw+2y4JJMHtGuHxHWqqPfY=",
"path": "github.com/dexon-foundation/dexon-consensus/core",
- "revision": "a69376bd9d144c462ae2b577c8147e96e4a60553",
- "revisionTime": "2019-03-29T07:18:33Z",
+ "revision": "ecc5e12b1ac4826e302607769f5b831ab4c27046",
+ "revisionTime": "2019-04-01T04:25:09Z",
"version": "single-chain",
"versionExact": "single-chain"
},
@@ -165,64 +165,64 @@
{
"checksumSHA1": "tQSbYCu5P00lUhKsx3IbBZCuSLY=",
"path": "github.com/dexon-foundation/dexon-consensus/core/crypto",
- "revision": "a69376bd9d144c462ae2b577c8147e96e4a60553",
- "revisionTime": "2019-03-29T07:18:33Z",
+ "revision": "ecc5e12b1ac4826e302607769f5b831ab4c27046",
+ "revisionTime": "2019-04-01T04:25:09Z",
"version": "single-chain",
"versionExact": "single-chain"
},
{
"checksumSHA1": "mMdctxTa/jNwAwZjjYoyEZdLoF8=",
"path": "github.com/dexon-foundation/dexon-consensus/core/crypto/dkg",
- "revision": "a69376bd9d144c462ae2b577c8147e96e4a60553",
- "revisionTime": "2019-03-29T07:18:33Z",
+ "revision": "ecc5e12b1ac4826e302607769f5b831ab4c27046",
+ "revisionTime": "2019-04-01T04:25:09Z",
"version": "single-chain",
"versionExact": "single-chain"
},
{
"checksumSHA1": "BhLKK8RveoLaeXc9UyUKMwQqchU=",
"path": "github.com/dexon-foundation/dexon-consensus/core/crypto/ecdsa",
- "revision": "a69376bd9d144c462ae2b577c8147e96e4a60553",
- "revisionTime": "2019-03-29T07:18:33Z",
+ "revision": "ecc5e12b1ac4826e302607769f5b831ab4c27046",
+ "revisionTime": "2019-04-01T04:25:09Z",
"version": "single-chain",
"versionExact": "single-chain"
},
{
- "checksumSHA1": "b99zZvbWvBimv1NiPGGF1yQ4dKY=",
+ "checksumSHA1": "hj/KetWUHp+1CX+50V0QnCthfWc=",
"path": "github.com/dexon-foundation/dexon-consensus/core/db",
- "revision": "a69376bd9d144c462ae2b577c8147e96e4a60553",
- "revisionTime": "2019-03-29T07:18:33Z",
+ "revision": "ecc5e12b1ac4826e302607769f5b831ab4c27046",
+ "revisionTime": "2019-04-01T04:25:09Z",
"version": "single-chain",
"versionExact": "single-chain"
},
{
- "checksumSHA1": "HfacdQdRnsj9vtx2xwJqQ07tEzs=",
+ "checksumSHA1": "pxAzlI5kjyIAJSX+/aRGjjhR+pw=",
"path": "github.com/dexon-foundation/dexon-consensus/core/syncer",
- "revision": "a69376bd9d144c462ae2b577c8147e96e4a60553",
- "revisionTime": "2019-03-29T07:18:33Z",
+ "revision": "ecc5e12b1ac4826e302607769f5b831ab4c27046",
+ "revisionTime": "2019-04-01T04:25:09Z",
"version": "single-chain",
"versionExact": "single-chain"
},
{
- "checksumSHA1": "YhUsUJjNHitRb/ZdxEaXCClMyxc=",
+ "checksumSHA1": "TmZF8DyrzGHTTfXXIFnKlzva3mU=",
"path": "github.com/dexon-foundation/dexon-consensus/core/types",
- "revision": "a69376bd9d144c462ae2b577c8147e96e4a60553",
- "revisionTime": "2019-03-29T07:18:33Z",
+ "revision": "ecc5e12b1ac4826e302607769f5b831ab4c27046",
+ "revisionTime": "2019-04-01T04:25:09Z",
"version": "single-chain",
"versionExact": "single-chain"
},
{
"checksumSHA1": "yoVRmvJDCp/1jSfY7wMt2LBQ9e8=",
"path": "github.com/dexon-foundation/dexon-consensus/core/types/dkg",
- "revision": "a69376bd9d144c462ae2b577c8147e96e4a60553",
- "revisionTime": "2019-03-29T07:18:33Z",
+ "revision": "ecc5e12b1ac4826e302607769f5b831ab4c27046",
+ "revisionTime": "2019-04-01T04:25:09Z",
"version": "single-chain",
"versionExact": "single-chain"
},
{
- "checksumSHA1": "M18S9KequUVKsfslTD6JC0MlZCY=",
+ "checksumSHA1": "pvJYiUy3EubRjeh5VYpt73Jjg1Q=",
"path": "github.com/dexon-foundation/dexon-consensus/core/utils",
- "revision": "a69376bd9d144c462ae2b577c8147e96e4a60553",
- "revisionTime": "2019-03-29T07:18:33Z",
+ "revision": "ecc5e12b1ac4826e302607769f5b831ab4c27046",
+ "revisionTime": "2019-04-01T04:25:09Z",
"version": "single-chain",
"versionExact": "single-chain"
},