diff options
author | Jimmy Hu <jimmy.hu@dexon.org> | 2019-01-04 16:24:26 +0800 |
---|---|---|
committer | Wei-Ning Huang <w@byzantine-lab.io> | 2019-06-12 17:27:21 +0800 |
commit | 9a8e616df90409e1a94b7843d1ceddcf010bc11b (patch) | |
tree | 9ee2a492ea8c5406bf7df078b1b2f028af1d65a7 | |
parent | b92aa8f1590c3ecb1e2fe8ba12a5092ca190786c (diff) | |
download | go-tangerine-9a8e616df90409e1a94b7843d1ceddcf010bc11b.tar.gz go-tangerine-9a8e616df90409e1a94b7843d1ceddcf010bc11b.tar.zst go-tangerine-9a8e616df90409e1a94b7843d1ceddcf010bc11b.zip |
vendor: sync to latest core (#125)
10 files changed, 288 insertions, 86 deletions
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 2b5c4bc51..e8cafbd68 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 @@ -148,7 +148,11 @@ func (mgr *agreementMgr) run() { } mgr.isRunning = true for i := uint32(0); i < uint32(len(mgr.baModules)); i++ { - go mgr.runBA(mgr.initRound, i) + mgr.waitGroup.Add(1) + go func(idx uint32) { + defer mgr.waitGroup.Done() + mgr.runBA(mgr.initRound, idx) + }(i) } } @@ -186,7 +190,11 @@ func (mgr *agreementMgr) appendConfig( recv.agreementModule = agrModule mgr.baModules = append(mgr.baModules, agrModule) if mgr.isRunning { - go mgr.runBA(round, i) + mgr.waitGroup.Add(1) + go func(idx uint32) { + defer mgr.waitGroup.Done() + mgr.runBA(round, idx) + }(i) } } return nil @@ -277,8 +285,6 @@ func (mgr *agreementMgr) stop() { } func (mgr *agreementMgr) runBA(initRound uint64, chainID uint32) { - mgr.waitGroup.Add(1) - defer mgr.waitGroup.Done() // Acquire agreement module. agr, recv := func() (*agreement, *consensusBAReceiver) { mgr.lock.RLock() 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 5c389a70f..a4636cb7b 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 @@ -107,6 +107,7 @@ func (cc *configurationChain) registerDKG(round uint64, threshold int) { threshold) go func() { ticker := newTicker(cc.gov, round, TickerDKG) + defer ticker.Stop() <-ticker.Tick() cc.dkgLock.Lock() defer cc.dkgLock.Unlock() @@ -142,6 +143,7 @@ func (cc *configurationChain) runDKG(round uint64) error { cc.dkgLock.Lock() } ticker := newTicker(cc.gov, round, TickerDKG) + defer ticker.Stop() cc.dkgLock.Unlock() <-ticker.Tick() cc.dkgLock.Lock() diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/dkg-tsig-protocol.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/dkg-tsig-protocol.go index 492271e98..7076ef376 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/dkg-tsig-protocol.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/dkg-tsig-protocol.go @@ -142,10 +142,6 @@ type tsigProtocol struct { threshold int } -func newDKGID(ID types.NodeID) dkg.ID { - return dkg.NewID(ID.Hash[:]) -} - func newDKGProtocol( ID types.NodeID, recv dkgReceiver, @@ -156,7 +152,7 @@ func newDKGProtocol( recv.ProposeDKGMasterPublicKey(&typesDKG.MasterPublicKey{ Round: round, - DKGID: newDKGID(ID), + DKGID: typesDKG.NewID(ID), PublicKeyShares: *pubShare, }) 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 591c63dfd..b30306aef 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/lattice.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/lattice.go @@ -207,7 +207,8 @@ func (l *Lattice) addBlockToLattice( if _, ok := err.(*ErrAckingBlockNotExists); ok { l.logger.Debug("Pending block for lattice", "pending", tip, - "last", l.data.chains[tip.Position.ChainID]) + "err", err, + "last", l.data.chains[tip.Position.ChainID].tip) err = nil continue } else { @@ -244,26 +245,27 @@ func (l *Lattice) ProcessBlock( toDelivered []*types.Block deliveredMode uint32 ) - l.lock.Lock() defer l.lock.Unlock() - if inLattice, err = l.addBlockToLattice(input); err != nil { return } - if len(inLattice) == 0 { return } - for _, b = range inLattice { - toDelivered, deliveredMode, err = l.toModule.processBlock(b) - if err != nil { + if err = l.toModule.addBlock(b); err != nil { // All errors from total ordering is serious, should panic. panic(err) } + } + for { + toDelivered, deliveredMode, err = l.toModule.extractBlocks() + if err != nil { + panic(err) + } if len(toDelivered) == 0 { - continue + break } hashes := make(common.Hashes, len(toDelivered)) for idx := range toDelivered { @@ -274,7 +276,7 @@ func (l *Lattice) ProcessBlock( } // Perform consensus timestamp module. if err = l.ctModule.processBlocks(toDelivered); err != nil { - return + break } delivered = append(delivered, toDelivered...) } @@ -316,32 +318,40 @@ 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) ([]*types.Block, error) { +func (l *Lattice) ProcessFinalizedBlock( + b *types.Block) (delivered []*types.Block, err error) { + var ( + toDelivered []*types.Block + deliveredMode uint32 + ) l.lock.Lock() defer l.lock.Unlock() // Syncing state for core.latticeData module. - if err := l.data.addFinalizedBlock(b); err != nil { - return nil, err + if err = l.data.addFinalizedBlock(b); err != nil { + return } 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 { - return nil, err - } - if len(toDelivered) == 0 { - return nil, nil - } - hashes := make(common.Hashes, len(toDelivered)) - for idx := range toDelivered { - hashes[idx] = toDelivered[idx].Hash - } - if l.debug != nil { - l.debug.TotalOrderingDelivered(hashes, deliveredMode) + if err = l.toModule.addBlock(b); err != nil { + return } - // Sync core.consensusTimestamp module. - if err = l.ctModule.processBlocks(toDelivered); err != nil { - return nil, err + for { + toDelivered, deliveredMode, err = l.toModule.extractBlocks() + if err != nil || len(toDelivered) == 0 { + break + } + hashes := make(common.Hashes, len(toDelivered)) + for idx := range toDelivered { + hashes[idx] = toDelivered[idx].Hash + } + if l.debug != nil { + l.debug.TotalOrderingDelivered(hashes, deliveredMode) + } + // Sync core.consensusTimestamp module. + if err = l.ctModule.processBlocks(toDelivered); err != nil { + break + } + delivered = append(delivered, toDelivered...) } - return toDelivered, nil + return } 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 744471a84..de8dd0bb7 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 @@ -1159,14 +1159,11 @@ CheckNextCandidateLoop: } // flushBlocks flushes blocks. -func (to *totalOrdering) flushBlocks( - b *types.Block) (flushed []*types.Block, mode uint32, err error) { - +func (to *totalOrdering) flushBlocks() ( + flushed []*types.Block, mode uint32, err error) { mode = TotalOrderingModeFlush cfg := to.getCurrentConfig() - if cfg.isLastBlock(b) { - to.flushReadyChains[b.Position.ChainID] = struct{}{} - } + // Flush blocks until last blocks from all chains appeared. if len(to.flushReadyChains) < int(cfg.numChains) { return @@ -1281,9 +1278,8 @@ func (to *totalOrdering) getCurrentConfig() *totalOrderingConfig { return to.configs[cfgIdx] } -// processBlock is the entry point of totalOrdering. -func (to *totalOrdering) processBlock( - b *types.Block) ([]*types.Block, uint32, error) { +// addBlock adds a block to the working set of total ordering module. +func (to *totalOrdering) addBlock(b *types.Block) error { // NOTE: Block b is assumed to be in topologically sorted, i.e., all its // acking blocks are during or after total ordering stage. cfg := to.getCurrentConfig() @@ -1291,7 +1287,7 @@ func (to *totalOrdering) processBlock( to.buildBlockRelation(b) isOldest, err := to.updateVectors(b) if err != nil { - return nil, uint32(0), err + return err } // Mark the proposer of incoming block as dirty. if b.Position.ChainID < cfg.numChains { @@ -1310,8 +1306,16 @@ func (to *totalOrdering) processBlock( to.prepareCandidate(b) } } + if to.duringFlush && cfg.isLastBlock(b) { + to.flushReadyChains[b.Position.ChainID] = struct{}{} + } + return nil +} + +// extractBlocks check if there is any deliverable set. +func (to *totalOrdering) extractBlocks() ([]*types.Block, uint32, error) { if to.duringFlush { - return to.flushBlocks(b) + return to.flushBlocks() } return to.deliverBlocks() } diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/types/dkg/dkg.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/dkg/dkg.go index f021d1bfb..efe846755 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/types/dkg/dkg.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/dkg/dkg.go @@ -31,6 +31,11 @@ import ( "github.com/dexon-foundation/dexon-consensus/core/types" ) +// NewID creates a DKGID from NodeID. +func NewID(ID types.NodeID) cryptoDKG.ID { + return cryptoDKG.NewID(ID.Hash[:]) +} + // PrivateShare describe a secret share in DKG protocol. type PrivateShare struct { ProposerID types.NodeID `json:"proposer_id"` diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/types/nodeset.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/nodeset.go index 89dfef3fd..da615e1f0 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/types/nodeset.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/types/nodeset.go @@ -32,7 +32,9 @@ type NodeSet struct { } // SubSetTarget is the sub set target for GetSubSet(). -type SubSetTarget *big.Int +type SubSetTarget struct { + data [][]byte +} type subSetTargetType byte @@ -71,7 +73,7 @@ func NewNodeSet() *NodeSet { } // NewNotarySetTarget is the target for getting Notary Set. -func NewNotarySetTarget(crs common.Hash, chainID uint32) SubSetTarget { +func NewNotarySetTarget(crs common.Hash, chainID uint32) *SubSetTarget { binaryChainID := make([]byte, 4) binary.LittleEndian.PutUint32(binaryChainID, chainID) @@ -79,7 +81,7 @@ func NewNotarySetTarget(crs common.Hash, chainID uint32) SubSetTarget { } // NewDKGSetTarget is the target for getting DKG Set. -func NewDKGSetTarget(crs common.Hash) SubSetTarget { +func NewDKGSetTarget(crs common.Hash) *SubSetTarget { return newTarget(targetDKGSet, crs[:]) } @@ -99,7 +101,7 @@ func (ns *NodeSet) Clone() *NodeSet { // GetSubSet returns the subset of given target. func (ns *NodeSet) GetSubSet( - size int, target SubSetTarget) map[NodeID]struct{} { + size int, target *SubSetTarget) map[NodeID]struct{} { if size == 0 { return make(map[NodeID]struct{}) } @@ -129,18 +131,20 @@ func (ns *NodeSet) GetSubSet( return nIDs } -func newTarget(targetType subSetTargetType, data ...[]byte) SubSetTarget { +func newTarget(targetType subSetTargetType, data ...[]byte) *SubSetTarget { data = append(data, []byte{byte(targetType)}) - h := crypto.Keccak256Hash(data...) - num := big.NewInt(0) - num.SetBytes(h[:]) - return SubSetTarget(num) + return &SubSetTarget{ + data: data, + } } -func newNodeRank(ID NodeID, target SubSetTarget) *nodeRank { - num := big.NewInt(0) - num.SetBytes(ID.Hash[:]) - num.Abs(num.Sub((*big.Int)(target), num)) +func newNodeRank(ID NodeID, target *SubSetTarget) *nodeRank { + data := make([][]byte, 1, len(target.data)+1) + data[0] = make([]byte, len(ID.Hash)) + copy(data[0], ID.Hash[:]) + data = append(data, target.data...) + h := crypto.Keccak256Hash(data...) + num := new(big.Int).SetBytes(h[:]) return &nodeRank{ ID: ID, rank: num, diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/penalty-helper.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/penalty-helper.go new file mode 100644 index 000000000..2b2456c62 --- /dev/null +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils/penalty-helper.go @@ -0,0 +1,126 @@ +// Copyright 2019 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 utils + +import ( + "errors" + + "github.com/dexon-foundation/dexon-consensus/core/types" + typesDKG "github.com/dexon-foundation/dexon-consensus/core/types/dkg" +) + +var ( + // ErrInvalidDKGMasterPublicKey means the DKG MasterPublicKey is invalid. + ErrInvalidDKGMasterPublicKey = errors.New("invalid DKG master public key") +) + +// NeedPenaltyDKGPrivateShare checks if the proposer of dkg private share +// should be penalized. +func NeedPenaltyDKGPrivateShare( + complaint *typesDKG.Complaint, mpk *typesDKG.MasterPublicKey) (bool, error) { + if complaint.IsNack() { + return false, nil + } + if mpk.ProposerID != complaint.PrivateShare.ProposerID { + return false, nil + } + ok, err := VerifyDKGMasterPublicKeySignature(mpk) + if err != nil { + return false, err + } + if !ok { + return false, ErrInvalidDKGMasterPublicKey + } + ok, err = VerifyDKGComplaintSignature(complaint) + if err != nil { + return false, err + } + if !ok { + return false, nil + } + ok, err = mpk.PublicKeyShares.VerifyPrvShare( + typesDKG.NewID(complaint.PrivateShare.ReceiverID), + &complaint.PrivateShare.PrivateShare) + if err != nil { + return false, err + } + return !ok, nil +} + +// NeedPenaltyForkVote checks if two votes are fork vote. +func NeedPenaltyForkVote(vote1, vote2 *types.Vote) (bool, error) { + if vote1.ProposerID != vote2.ProposerID || + vote1.Type != vote2.Type || + vote1.Period != vote2.Period || + vote1.Position != vote2.Position || + vote1.BlockHash == vote2.BlockHash { + return false, nil + } + ok, err := VerifyVoteSignature(vote1) + if err != nil { + return false, err + } + if !ok { + return false, nil + } + ok, err = VerifyVoteSignature(vote2) + if err != nil { + return false, err + } + if !ok { + return false, nil + } + return true, nil +} + +// NeedPenaltyForkBlock checks if two blocks are fork block. +func NeedPenaltyForkBlock(block1, block2 *types.Block) (bool, error) { + if block1.ProposerID != block2.ProposerID || + block1.Position != block2.Position || + block1.Hash == block2.Hash { + return false, nil + } + verifyBlock := func(block *types.Block) (bool, error) { + err := VerifyBlockSignature(block) + switch err { + case nil: + return true, nil + case ErrIncorrectSignature: + return false, nil + case ErrIncorrectHash: + return false, nil + default: + return false, err + } + } + ok, err := verifyBlock(block1) + if err != nil { + return false, err + } + if !ok { + return false, nil + } + ok, err = verifyBlock(block2) + if err != nil { + return false, err + } + if !ok { + return false, nil + } + return true, 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 3e3803d06..687d0ea22 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 @@ -1,3 +1,20 @@ +// 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/>. + // This file is part of the dexon-consensus library. // // The dexon-consensus library is free software: you can redistribute it @@ -21,6 +38,7 @@ import ( "github.com/dexon-foundation/dexon-consensus/common" "github.com/dexon-foundation/dexon-consensus/core/types" + typesDKG "github.com/dexon-foundation/dexon-consensus/core/types/dkg" ) type configAccessor interface { @@ -57,5 +75,36 @@ func GetCRSWithPanic(accessor crsAccessor, round uint64, panic(fmt.Errorf("CRS is not ready %v", round)) } return crs +} +// VerifyDKGComplaint verifies if its a valid DKGCompliant. +func VerifyDKGComplaint( + complaint *typesDKG.Complaint, mpk *typesDKG.MasterPublicKey) (bool, error) { + ok, err := VerifyDKGComplaintSignature(complaint) + if err != nil { + return false, err + } + if !ok { + return false, nil + } + if complaint.IsNack() { + return true, nil + } + if complaint.Round != mpk.Round { + return false, nil + } + ok, err = VerifyDKGMasterPublicKeySignature(mpk) + if err != nil { + return false, err + } + if !ok { + return false, nil + } + ok, err = mpk.PublicKeyShares.VerifyPrvShare( + typesDKG.NewID(complaint.PrivateShare.ReceiverID), + &complaint.PrivateShare.PrivateShare) + if err != nil { + return false, err + } + return ok, nil } diff --git a/vendor/vendor.json b/vendor/vendor.json index ec9c59f37..38d199375 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -141,14 +141,14 @@ { "checksumSHA1": "65L1yf+f0OCiLFniljqfRxVdsQA=", "path": "github.com/dexon-foundation/dexon-consensus/common", - "revision": "3c3e5d0b11758e2385b3890013be3e3698b992a8", - "revisionTime": "2019-01-02T10:56:02Z" + "revision": "beaef47dd5dd4b342cef3c8b26508ce3c334be06", + "revisionTime": "2019-01-04T06:43:20Z" }, { - "checksumSHA1": "Lr1fcYwV5dysAfISBDx7aQfZUCE=", + "checksumSHA1": "Udj+vrFiUDboPRspH3S7URdKj+0=", "path": "github.com/dexon-foundation/dexon-consensus/core", - "revision": "3c3e5d0b11758e2385b3890013be3e3698b992a8", - "revisionTime": "2019-01-02T10:56:02Z" + "revision": "beaef47dd5dd4b342cef3c8b26508ce3c334be06", + "revisionTime": "2019-01-04T06:43:20Z" }, { "checksumSHA1": "v4fKR7uhoyufi6hAVO44cFEb+tY=", @@ -159,50 +159,50 @@ { "checksumSHA1": "tQSbYCu5P00lUhKsx3IbBZCuSLY=", "path": "github.com/dexon-foundation/dexon-consensus/core/crypto", - "revision": "3c3e5d0b11758e2385b3890013be3e3698b992a8", - "revisionTime": "2019-01-02T10:56:02Z" + "revision": "beaef47dd5dd4b342cef3c8b26508ce3c334be06", + "revisionTime": "2019-01-04T06:43:20Z" }, { "checksumSHA1": "W2P7pkuJ+26BpJg03K4Y0nB5obI=", "path": "github.com/dexon-foundation/dexon-consensus/core/crypto/dkg", - "revision": "3c3e5d0b11758e2385b3890013be3e3698b992a8", - "revisionTime": "2019-01-02T10:56:02Z" + "revision": "beaef47dd5dd4b342cef3c8b26508ce3c334be06", + "revisionTime": "2019-01-04T06:43:20Z" }, { "checksumSHA1": "6Pf6caC8LTNCI7IflFmglKYnxYo=", "path": "github.com/dexon-foundation/dexon-consensus/core/crypto/ecdsa", - "revision": "3c3e5d0b11758e2385b3890013be3e3698b992a8", - "revisionTime": "2019-01-02T10:56:02Z" + "revision": "beaef47dd5dd4b342cef3c8b26508ce3c334be06", + "revisionTime": "2019-01-04T06:43:20Z" }, { "checksumSHA1": "PJXR1OuWwVVYrdJMK3skPr1/8ls=", "path": "github.com/dexon-foundation/dexon-consensus/core/db", - "revision": "3c3e5d0b11758e2385b3890013be3e3698b992a8", - "revisionTime": "2019-01-02T10:56:02Z" + "revision": "beaef47dd5dd4b342cef3c8b26508ce3c334be06", + "revisionTime": "2019-01-04T06:43:20Z" }, { "checksumSHA1": "tFFonPHlve/3JqqRSopnLb6Rn2o=", "path": "github.com/dexon-foundation/dexon-consensus/core/syncer", - "revision": "3c3e5d0b11758e2385b3890013be3e3698b992a8", - "revisionTime": "2019-01-02T10:56:02Z" + "revision": "beaef47dd5dd4b342cef3c8b26508ce3c334be06", + "revisionTime": "2019-01-04T06:43:20Z" }, { - "checksumSHA1": "tY+yi5kYk1u/scq+6e1KzhPv4kU=", + "checksumSHA1": "Kpmnp6XIAnnSSncijzOBo77OshY=", "path": "github.com/dexon-foundation/dexon-consensus/core/types", - "revision": "3c3e5d0b11758e2385b3890013be3e3698b992a8", - "revisionTime": "2019-01-02T10:56:02Z" + "revision": "beaef47dd5dd4b342cef3c8b26508ce3c334be06", + "revisionTime": "2019-01-04T06:43:20Z" }, { - "checksumSHA1": "sY+2eiOoWvsNMvuPl9qQ+rlT9sA=", + "checksumSHA1": "rmv8uxwrqMhJAeA3RPvwYP8mFro=", "path": "github.com/dexon-foundation/dexon-consensus/core/types/dkg", - "revision": "3c3e5d0b11758e2385b3890013be3e3698b992a8", - "revisionTime": "2019-01-02T10:56:02Z" + "revision": "beaef47dd5dd4b342cef3c8b26508ce3c334be06", + "revisionTime": "2019-01-04T06:43:20Z" }, { - "checksumSHA1": "0JFlVFny0IyANnlelQDl8ot16wU=", + "checksumSHA1": "zvk7bSkUGBwMGi9j+15Ve10noyg=", "path": "github.com/dexon-foundation/dexon-consensus/core/utils", - "revision": "3c3e5d0b11758e2385b3890013be3e3698b992a8", - "revisionTime": "2019-01-02T10:56:02Z" + "revision": "beaef47dd5dd4b342cef3c8b26508ce3c334be06", + "revisionTime": "2019-01-04T06:43:20Z" }, { "checksumSHA1": "TAkwduKZqLyimyTPPWIllZWYFuE=", |