aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJimmy Hu <jimmy.hu@dexon.org>2019-03-20 14:57:12 +0800
committerJimmy Hu <jimmy.hu@dexon.org>2019-03-27 15:25:10 +0800
commit6efe199cb38eb4cb9a9a64d98ff5f8c4fb997da7 (patch)
tree2c18fe616f84df7274f19f88cf325fe558869918
parentfa3b5a29499739e90b3cf17f9a0cf60a72a64fc0 (diff)
downloaddexon-consensus-6efe199cb38eb4cb9a9a64d98ff5f8c4fb997da7.tar
dexon-consensus-6efe199cb38eb4cb9a9a64d98ff5f8c4fb997da7.tar.gz
dexon-consensus-6efe199cb38eb4cb9a9a64d98ff5f8c4fb997da7.tar.bz2
dexon-consensus-6efe199cb38eb4cb9a9a64d98ff5f8c4fb997da7.tar.lz
dexon-consensus-6efe199cb38eb4cb9a9a64d98ff5f8c4fb997da7.tar.xz
dexon-consensus-6efe199cb38eb4cb9a9a64d98ff5f8c4fb997da7.tar.zst
dexon-consensus-6efe199cb38eb4cb9a9a64d98ff5f8c4fb997da7.zip
core: merge notarySet and DKGSet (#488)
* core: さよなら DKGSet * test logger * temporary fix before finalized * core: Sign psig on commit vote * Add syncer log * fixup
-rw-r--r--core/agreement-mgr.go4
-rw-r--r--core/agreement-state_test.go4
-rw-r--r--core/agreement.go11
-rw-r--r--core/agreement_test.go4
-rw-r--r--core/blockchain.go84
-rw-r--r--core/blockchain_test.go154
-rw-r--r--core/configuration-chain.go32
-rw-r--r--core/configuration-chain_test.go17
-rw-r--r--core/consensus.go383
-rw-r--r--core/consensus_test.go13
-rw-r--r--core/interfaces.go6
-rw-r--r--core/syncer/consensus.go83
-rw-r--r--core/test/governance.go6
-rw-r--r--core/test/governance_test.go16
-rw-r--r--core/test/marshaller.go15
-rw-r--r--core/test/network.go272
-rw-r--r--core/test/network_test.go20
-rw-r--r--core/test/state-change-request.go5
-rw-r--r--core/test/state-change-request_test.go2
-rw-r--r--core/test/state.go11
-rw-r--r--core/test/state_test.go3
-rw-r--r--core/test/tcp-transport.go2
-rw-r--r--core/test/utils.go8
-rw-r--r--core/types/block-randomness.go31
-rw-r--r--core/types/config.go5
-rw-r--r--core/types/config_test.go1
-rw-r--r--core/types/nodeset.go6
-rw-r--r--core/types/vote.go8
-rw-r--r--core/utils/crypto.go10
-rw-r--r--core/utils/nodeset-cache.go15
-rw-r--r--core/utils/nodeset-cache_test.go4
-rw-r--r--core/utils/utils.go2
-rw-r--r--integration_test/consensus_test.go41
-rw-r--r--simulation/config/utils.go4
-rw-r--r--simulation/node.go1
35 files changed, 413 insertions, 870 deletions
diff --git a/core/agreement-mgr.go b/core/agreement-mgr.go
index d29863d..02b7b7b 100644
--- a/core/agreement-mgr.go
+++ b/core/agreement-mgr.go
@@ -141,7 +141,7 @@ func newAgreementMgr(con *Consensus, initRound uint64,
roundValue: &atomic.Value{},
changeNotaryHeightValue: &atomic.Value{},
}
- mgr.recv.roundValue.Store(uint64(0))
+ mgr.recv.updateRound(uint64(0))
mgr.recv.changeNotaryHeightValue.Store(uint64(0))
agr := newAgreement(
mgr.ID,
@@ -377,7 +377,7 @@ Loop:
}
mgr.recv.isNotary = checkRound()
// Run BA for this round.
- mgr.recv.roundValue.Store(currentRound)
+ mgr.recv.updateRound(currentRound)
mgr.recv.changeNotaryHeightValue.Store(curConfig.RoundEndHeight())
mgr.recv.restartNotary <- types.Position{
Round: mgr.recv.round(),
diff --git a/core/agreement-state_test.go b/core/agreement-state_test.go
index 1b7d41b..c4197b5 100644
--- a/core/agreement-state_test.go
+++ b/core/agreement-state_test.go
@@ -43,6 +43,10 @@ type agreementStateTestReceiver struct {
leader *leaderSelector
}
+func (r *agreementStateTestReceiver) VerifyPartialSignature(*types.Vote) bool {
+ return true
+}
+
func (r *agreementStateTestReceiver) ProposeVote(vote *types.Vote) {
r.s.voteChan <- vote
}
diff --git a/core/agreement.go b/core/agreement.go
index 16f36bc..1ba9034 100644
--- a/core/agreement.go
+++ b/core/agreement.go
@@ -38,9 +38,10 @@ func init() {
// Errors for agreement module.
var (
- ErrInvalidVote = fmt.Errorf("invalid vote")
- ErrNotInNotarySet = fmt.Errorf("not in notary set")
- ErrIncorrectVoteSignature = fmt.Errorf("incorrect vote signature")
+ ErrInvalidVote = fmt.Errorf("invalid vote")
+ ErrNotInNotarySet = fmt.Errorf("not in notary set")
+ ErrIncorrectVoteSignature = fmt.Errorf("incorrect vote signature")
+ ErrIncorrectVotePartialSignature = fmt.Errorf("incorrect vote psig")
)
// ErrFork for fork error in agreement.
@@ -83,6 +84,7 @@ type agreementReceiver interface {
PullBlocks(common.Hashes)
ReportForkVote(v1, v2 *types.Vote)
ReportForkBlock(b1, b2 *types.Block)
+ VerifyPartialSignature(vote *types.Vote) bool
}
type pendingBlock struct {
@@ -332,6 +334,9 @@ func (a *agreement) sanityCheck(vote *types.Vote) error {
if !ok {
return ErrIncorrectVoteSignature
}
+ if !a.data.recv.VerifyPartialSignature(vote) {
+ return ErrIncorrectVotePartialSignature
+ }
return nil
}
diff --git a/core/agreement_test.go b/core/agreement_test.go
index 4ddff8d..dfeb783 100644
--- a/core/agreement_test.go
+++ b/core/agreement_test.go
@@ -34,6 +34,10 @@ type agreementTestReceiver struct {
agreementIndex int
}
+func (r *agreementTestReceiver) VerifyPartialSignature(*types.Vote) bool {
+ return true
+}
+
func (r *agreementTestReceiver) ProposeVote(vote *types.Vote) {
r.s.voteChan <- vote
}
diff --git a/core/blockchain.go b/core/blockchain.go
index 610ab28..0ecd083 100644
--- a/core/blockchain.go
+++ b/core/blockchain.go
@@ -32,18 +32,19 @@ import (
// Errors for sanity check error.
var (
- ErrBlockFromOlderPosition = errors.New("block from older position")
- ErrNotGenesisBlock = errors.New("not a genesis block")
- ErrIsGenesisBlock = errors.New("is a genesis block")
- ErrIncorrectParentHash = errors.New("incorrect parent hash")
- ErrInvalidBlockHeight = errors.New("invalid block height")
- ErrInvalidRoundID = errors.New("invalid round id")
- ErrNotFollowTipPosition = errors.New("not follow tip position")
- ErrDuplicatedPendingBlock = errors.New("duplicated pending block")
- ErrRetrySanityCheckLater = errors.New("retry sanity check later")
- ErrRoundNotSwitch = errors.New("round not switch")
- ErrIncorrectBlockRandomnessResult = errors.New(
+ ErrBlockFromOlderPosition = errors.New("block from older position")
+ ErrNotGenesisBlock = errors.New("not a genesis block")
+ ErrIsGenesisBlock = errors.New("is a genesis block")
+ ErrIncorrectParentHash = errors.New("incorrect parent hash")
+ ErrInvalidBlockHeight = errors.New("invalid block height")
+ ErrInvalidRoundID = errors.New("invalid round id")
+ ErrNotFollowTipPosition = errors.New("not follow tip position")
+ ErrDuplicatedPendingBlock = errors.New("duplicated pending block")
+ ErrRetrySanityCheckLater = errors.New("retry sanity check later")
+ ErrRoundNotSwitch = errors.New("round not switch")
+ ErrIncorrectAgreementResult = errors.New(
"incorrect block randomness result")
+ ErrMissingRandomness = errors.New("missing block randomness")
)
type pendingBlockRecord struct {
@@ -134,7 +135,7 @@ type blockChain struct {
vGetter tsigVerifierGetter
app Application
logger common.Logger
- pendingRandomnesses map[types.Position]*types.BlockRandomnessResult
+ pendingRandomnesses map[types.Position]*types.AgreementResult
configs []blockChainConfig
pendingBlocks pendingBlockRecords
confirmedBlocks types.BlocksByPosition
@@ -154,7 +155,7 @@ func newBlockChain(nID types.NodeID, dMoment time.Time, initBlock *types.Block,
logger: logger,
dMoment: dMoment,
pendingRandomnesses: make(
- map[types.Position]*types.BlockRandomnessResult),
+ map[types.Position]*types.AgreementResult),
}
}
@@ -211,10 +212,10 @@ func (bc *blockChain) notifyRoundEvents(evts []utils.RoundEventParam) error {
}
func (bc *blockChain) proposeBlock(position types.Position,
- proposeTime time.Time) (b *types.Block, err error) {
+ proposeTime time.Time, isEmpty bool) (b *types.Block, err error) {
bc.lock.RLock()
defer bc.lock.RUnlock()
- return bc.prepareBlock(position, proposeTime, false)
+ return bc.prepareBlock(position, proposeTime, isEmpty)
}
func (bc *blockChain) extractBlocks() (ret []*types.Block) {
@@ -222,9 +223,6 @@ func (bc *blockChain) extractBlocks() (ret []*types.Block) {
defer bc.lock.Unlock()
for len(bc.confirmedBlocks) > 0 {
c := bc.confirmedBlocks[0]
- if c.Position.Round >= DKGDelayRound && len(c.Finalization.Randomness) == 0 {
- break
- }
c, bc.confirmedBlocks = bc.confirmedBlocks[0], bc.confirmedBlocks[1:]
// TODO(mission): remove these duplicated field if we fully converted
// to single chain.
@@ -315,6 +313,9 @@ func (bc *blockChain) addEmptyBlock(position types.Position) (
// addBlock should be called when the block is confirmed by BA, we won't perform
// 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 {
+ return ErrMissingRandomness
+ }
bc.lock.Lock()
defer bc.lock.Unlock()
confirmed := false
@@ -338,45 +339,6 @@ func (bc *blockChain) addBlock(b *types.Block) error {
return nil
}
-func (bc *blockChain) shouldAddRandomness(r *types.BlockRandomnessResult) bool {
- bc.lock.RLock()
- defer bc.lock.RUnlock()
- if bc.lastDelivered != nil &&
- bc.lastDelivered.Position.Newer(r.Position) {
- return false
- }
- _, exists := bc.pendingRandomnesses[r.Position]
- if exists {
- return false
- }
- b := bc.findPendingBlock(r.Position)
- return b == nil || len(b.Finalization.Randomness) == 0
-}
-
-func (bc *blockChain) addRandomness(r *types.BlockRandomnessResult) error {
- if !bc.shouldAddRandomness(r) {
- return nil
- }
- ok, err := bc.verifyRandomness(r.BlockHash, r.Position.Round, r.Randomness)
- if err != nil {
- return err
- }
- if !ok {
- return ErrIncorrectBlockRandomnessResult
- }
- bc.lock.Lock()
- defer bc.lock.Unlock()
- if b := bc.findPendingBlock(r.Position); b != nil {
- if !r.BlockHash.Equal(b.Hash) {
- panic(fmt.Errorf("mismathed randomness: %s %s", b, r))
- }
- b.Finalization.Randomness = r.Randomness
- } else {
- bc.pendingRandomnesses[r.Position] = r
- }
- return nil
-}
-
// TODO(mission): remove this method after removing the strong binding between
// BA and blockchain.
func (bc *blockChain) tipRound() uint64 {
@@ -456,14 +418,6 @@ func (bc *blockChain) lastPendingBlock() *types.Block {
return bc.confirmedBlocks[0]
}
-func (bc *blockChain) processFinalizedBlock(b *types.Block) error {
- return bc.addRandomness(&types.BlockRandomnessResult{
- BlockHash: b.Hash,
- Position: b.Position,
- Randomness: b.Finalization.Randomness,
- })
-}
-
/////////////////////////////////////////////
//
// internal helpers
diff --git a/core/blockchain_test.go b/core/blockchain_test.go
index 87b8eac..6a615c1 100644
--- a/core/blockchain_test.go
+++ b/core/blockchain_test.go
@@ -18,7 +18,6 @@
package core
import (
- "fmt"
"testing"
"time"
@@ -82,6 +81,9 @@ func (s *BlockChainTestSuite) newBlocks(c uint64, initBlock *types.Block) (
Position: types.Position{Round: initRound, Height: baseHeight + i},
Timestamp: t,
}
+ if b.Position.Round >= DKGDelayRound {
+ b.Finalization.Randomness = common.GenerateRandomBytes()
+ }
s.Require().NoError(s.signer.SignBlock(b))
blocks = append(blocks, b)
parentHash = b.Hash
@@ -116,19 +118,13 @@ func (s *BlockChainTestSuite) newBlock(parent *types.Block, round uint64,
},
Timestamp: parent.Timestamp.Add(blockInterval),
}
+ if b.Position.Round >= DKGDelayRound {
+ b.Finalization.Randomness = common.GenerateRandomBytes()
+ }
s.Require().NoError(s.signer.SignBlock(b))
return b
}
-func (s *BlockChainTestSuite) newRandomnessFromBlock(
- b *types.Block) *types.BlockRandomnessResult {
- return &types.BlockRandomnessResult{
- BlockHash: b.Hash,
- Position: b.Position,
- Randomness: common.GenerateRandomBytes(),
- }
-}
-
func (s *BlockChainTestSuite) newBlockChain(initB *types.Block,
roundLength uint64) (bc *blockChain) {
initRound := uint64(0)
@@ -163,64 +159,6 @@ func (s *BlockChainTestSuite) newRoundOneInitBlock() *types.Block {
return initBlock
}
-func (s *BlockChainTestSuite) baseConcurrentAceessTest(initBlock *types.Block,
- blocks []*types.Block, rands []*types.BlockRandomnessResult) {
- var (
- bc = s.newBlockChain(initBlock, uint64(len(blocks)+1))
- start = make(chan struct{})
- newNotif = make(chan struct{}, 1)
- delivered []*types.Block
- )
- add := func(v interface{}) {
- <-start
- switch val := v.(type) {
- case *types.Block:
- if err := bc.addBlock(val); err != nil {
- // Never assertion in sub routine when testing.
- panic(err)
- }
- case *types.BlockRandomnessResult:
- if err := bc.addRandomness(val); err != nil {
- // Never assertion in sub routine when testing.
- panic(err)
- }
- default:
- panic(fmt.Errorf("unknown type: %v", v))
- }
- select {
- case newNotif <- struct{}{}:
- default:
- }
- }
- for _, b := range blocks {
- go add(b)
- }
- for _, r := range rands {
- go add(r)
- }
- close(start)
- for {
- select {
- case <-newNotif:
- delivered = append(delivered, bc.extractBlocks()...)
- case <-time.After(100 * time.Millisecond):
- delivered = append(delivered, bc.extractBlocks()...)
- }
- if len(delivered) == len(blocks) {
- break
- }
- }
- // Check result.
- b := delivered[0]
- s.Require().Equal(b.Position.Height, uint64(1))
- s.Require().NotEmpty(b.Finalization.Randomness)
- for _, bb := range delivered[1:] {
- s.Require().Equal(b.Position.Height+1, bb.Position.Height)
- s.Require().NotEmpty(b.Finalization.Randomness)
- b = bb
- }
-}
-
func (s *BlockChainTestSuite) TestBasicUsage() {
initBlock := s.newRoundOneInitBlock()
bc := s.newBlockChain(initBlock, 10)
@@ -233,20 +171,11 @@ func (s *BlockChainTestSuite) TestBasicUsage() {
b5 := &types.Block{
ParentHash: b4.Hash,
Position: types.Position{Round: 1, Height: b4.Position.Height + 1},
+ Finalization: types.FinalizationResult{
+ Randomness: common.GenerateRandomBytes(),
+ },
}
s.Require().NoError(s.signer.SignBlock(b5))
- r0 := s.newRandomnessFromBlock(b0)
- r1 := s.newRandomnessFromBlock(b1)
- r2 := s.newRandomnessFromBlock(b2)
- r3 := s.newRandomnessFromBlock(b3)
- r4 := s.newRandomnessFromBlock(b4)
- r5 := s.newRandomnessFromBlock(b5)
- // add those datum in reversed order of position.
- s.Require().NoError(bc.addRandomness(r4))
- s.Require().NoError(bc.addRandomness(r3))
- s.Require().NoError(bc.addRandomness(r2))
- s.Require().NoError(bc.addRandomness(r1))
- s.Require().NoError(bc.addRandomness(r0))
s.Require().NoError(bc.addBlock(b5))
emptyB, err := bc.addEmptyBlock(b4.Position)
s.Require().Nil(emptyB)
@@ -256,29 +185,10 @@ func (s *BlockChainTestSuite) TestBasicUsage() {
s.Require().NoError(bc.addBlock(b1))
s.Require().NoError(bc.addBlock(b0))
extracted := bc.extractBlocks()
- s.Require().Len(extracted, 5)
+ s.Require().Len(extracted, 6)
s.Require().Equal(extracted[4].Hash, b4.Hash)
- s.Require().NoError(bc.addRandomness(r5))
extracted = bc.extractBlocks()
- s.Require().Len(extracted, 1)
- s.Require().Equal(extracted[0].Hash, b5.Hash)
-}
-
-func (s *BlockChainTestSuite) TestConcurrentAccess() {
- // Raise one go routine for each block and randomness. And let them try to
- // add to blockChain at the same time. Make sure we can delivered them all.
- var (
- retry = 10
- initBlock = s.newRoundOneInitBlock()
- blocks = s.newBlocks(500, initBlock)
- rands = []*types.BlockRandomnessResult{}
- )
- for _, b := range blocks {
- rands = append(rands, s.newRandomnessFromBlock(b))
- }
- for i := 0; i < retry; i++ {
- s.baseConcurrentAceessTest(initBlock, blocks, rands)
- }
+ s.Require().Len(extracted, 0)
}
func (s *BlockChainTestSuite) TestSanityCheck() {
@@ -411,20 +321,6 @@ func (s *BlockChainTestSuite) TestNextBlockAndTipRound() {
s.Require().Equal(bc.tipRound(), uint64(1))
}
-func (s *BlockChainTestSuite) TestPendingBlocksWithoutRandomness() {
- initBlock := s.newRoundOneInitBlock()
- bc := s.newBlockChain(initBlock, 10)
- blocks := s.newBlocks(4, initBlock)
- s.Require().NoError(bc.addBlock(blocks[0]))
- s.Require().NoError(bc.addBlock(blocks[1]))
- s.Require().NoError(bc.addBlock(blocks[3]))
- s.Require().Equal(bc.pendingBlocksWithoutRandomness(), common.Hashes{
- blocks[0].Hash, blocks[1].Hash, blocks[3].Hash})
- s.Require().NoError(bc.addRandomness(s.newRandomnessFromBlock(blocks[0])))
- s.Require().Equal(bc.pendingBlocksWithoutRandomness(), common.Hashes{
- blocks[1].Hash, blocks[3].Hash})
-}
-
func (s *BlockChainTestSuite) TestLastXBlock() {
initBlock := s.newRoundOneInitBlock()
bc := s.newBlockChain(initBlock, 10)
@@ -434,7 +330,6 @@ func (s *BlockChainTestSuite) TestLastXBlock() {
s.Require().NoError(bc.addBlock(blocks[0]))
s.Require().True(bc.lastPendingBlock() == blocks[0])
s.Require().True(bc.lastDeliveredBlock() == initBlock)
- s.Require().NoError(bc.addRandomness(s.newRandomnessFromBlock(blocks[0])))
s.Require().Len(bc.extractBlocks(), 1)
s.Require().Nil(bc.lastPendingBlock())
s.Require().True(bc.lastDeliveredBlock() == blocks[0])
@@ -498,7 +393,7 @@ func (s *BlockChainTestSuite) TestAddEmptyBlockDirectly() {
s.Require().NoError(err)
// prepare a normal block.
pos = types.Position{Height: 3}
- b3, err := bc.proposeBlock(pos, emptyB2.Timestamp.Add(s.blockInterval))
+ b3, err := bc.proposeBlock(pos, emptyB2.Timestamp.Add(s.blockInterval), false)
s.Require().NotNil(b3)
s.Require().NoError(err)
// Add an empty block far away from current tip.
@@ -525,31 +420,6 @@ func (s *BlockChainTestSuite) TestAddEmptyBlockDirectly() {
s.Require().NotNil(rec.block)
}
-func (s *BlockChainTestSuite) TestShouldAddRandomness() {
- initBlock := s.newRoundOneInitBlock()
- bc := s.newBlockChain(initBlock, 10)
- blocks := s.newBlocks(2, initBlock)
- b0, b1 := blocks[0], blocks[1]
- r0 := s.newRandomnessFromBlock(b0)
- r1 := s.newRandomnessFromBlock(b1)
-
- // If a block is extracted, the randomness should not be added.
- s.Require().NoError(bc.addBlock(b0))
- s.True(bc.shouldAddRandomness(r0))
- s.Require().NoError(bc.addRandomness(r0))
- s.False(bc.shouldAddRandomness(r0))
- s.Require().Len(bc.extractBlocks(), 1)
- s.Require().Equal(b0.Hash, bc.lastDelivered.Hash)
-
- // If a block has already have randomness, it should not be added.
- s.True(bc.shouldAddRandomness(r1))
- s.Require().NoError(bc.addRandomness(r1))
- s.Require().Len(bc.pendingRandomnesses, 1)
- s.False(bc.shouldAddRandomness(r1))
- s.Require().NoError(bc.addBlock(b1))
- s.False(bc.shouldAddRandomness(r1))
-}
-
func TestBlockChain(t *testing.T) {
suite.Run(t, new(BlockChainTestSuite))
}
diff --git a/core/configuration-chain.go b/core/configuration-chain.go
index 48b0f2a..92b2830 100644
--- a/core/configuration-chain.go
+++ b/core/configuration-chain.go
@@ -76,7 +76,7 @@ type configurationChain struct {
tsigReady *sync.Cond
cache *utils.NodeSetCache
db db.Database
- dkgSet map[types.NodeID]struct{}
+ notarySet map[types.NodeID]struct{}
mpkReady bool
pendingPrvShare map[types.NodeID]*typesDKG.PrivateShare
// TODO(jimmy-dexon): add timeout to pending psig.
@@ -194,12 +194,12 @@ func (cc *configurationChain) registerDKG(
})
}
}
- dkgSet, err := cc.cache.GetDKGSet(round)
+ notarySet, err := cc.cache.GetNotarySet(round)
if err != nil {
- cc.logger.Error("Error getting DKG set from cache", "error", err)
+ cc.logger.Error("Error getting notary set from cache", "error", err)
return
}
- cc.dkgSet = dkgSet
+ cc.notarySet = notarySet
cc.pendingPrvShare = make(map[types.NodeID]*typesDKG.PrivateShare)
cc.mpkReady = false
cc.dkg, err = recoverDKGProtocol(cc.ID, cc.recv, round, reset, cc.db)
@@ -479,7 +479,7 @@ func (cc *configurationChain) runDKG(round uint64, reset uint64) (err error) {
cc.dkgRunning = false
}()
// Check if corresponding DKG signer is ready.
- if _, _, err = cc.getDKGInfo(round); err == nil {
+ if _, _, err = cc.getDKGInfo(round, true); err == nil {
return ErrSkipButNoError
}
tickStartAt := 1
@@ -518,12 +518,13 @@ func (cc *configurationChain) isDKGFinal(round uint64) bool {
if !cc.gov.IsDKGFinal(round) {
return false
}
- _, _, err := cc.getDKGInfo(round)
+ _, _, err := cc.getDKGInfo(round, false)
return err == nil
}
func (cc *configurationChain) getDKGInfo(
- round uint64) (*typesDKG.NodePublicKeys, *dkgShareSecret, error) {
+ round uint64, ignoreSigner bool) (
+ *typesDKG.NodePublicKeys, *dkgShareSecret, error) {
getFromCache := func() (*typesDKG.NodePublicKeys, *dkgShareSecret) {
cc.dkgResult.RLock()
defer cc.dkgResult.RUnlock()
@@ -532,19 +533,20 @@ func (cc *configurationChain) getDKGInfo(
return npks, signer
}
npks, signer := getFromCache()
- if npks == nil || signer == nil {
- if err := cc.recoverDKGInfo(round); err != nil {
+ if npks == nil || (!ignoreSigner && signer == nil) {
+ if err := cc.recoverDKGInfo(round, ignoreSigner); err != nil {
return nil, nil, err
}
npks, signer = getFromCache()
}
- if npks == nil || signer == nil {
+ if npks == nil || (!ignoreSigner && signer == nil) {
return nil, nil, ErrDKGNotReady
}
return npks, signer, nil
}
-func (cc *configurationChain) recoverDKGInfo(round uint64) error {
+func (cc *configurationChain) recoverDKGInfo(
+ round uint64, ignoreSigner bool) error {
var npksExists, signerExists bool
func() {
cc.dkgResult.Lock()
@@ -582,7 +584,7 @@ func (cc *configurationChain) recoverDKGInfo(round uint64) error {
cc.npks[round] = npks
}()
}
- if !signerExists {
+ if !signerExists && !ignoreSigner {
// Check if we have private shares in DB.
prvKey, err := cc.db.GetDKGPrivateKey(round)
if err != nil {
@@ -603,7 +605,7 @@ func (cc *configurationChain) recoverDKGInfo(round uint64) error {
func (cc *configurationChain) preparePartialSignature(
round uint64, hash common.Hash) (*typesDKG.PartialSignature, error) {
- _, signer, _ := cc.getDKGInfo(round)
+ _, signer, _ := cc.getDKGInfo(round, false)
if signer == nil {
return nil, ErrDKGNotReady
}
@@ -632,7 +634,7 @@ func (cc *configurationChain) untouchTSigHash(hash common.Hash) {
func (cc *configurationChain) runTSig(
round uint64, hash common.Hash) (
crypto.Signature, error) {
- npks, _, _ := cc.getDKGInfo(round)
+ npks, _, _ := cc.getDKGInfo(round, false)
if npks == nil {
return crypto.Signature{}, ErrDKGNotReady
}
@@ -697,7 +699,7 @@ func (cc *configurationChain) processPrivateShare(
if cc.dkg == nil {
return nil
}
- if _, exist := cc.dkgSet[prvShare.ProposerID]; !exist {
+ if _, exist := cc.notarySet[prvShare.ProposerID]; !exist {
return ErrNotDKGParticipant
}
if !cc.mpkReady {
diff --git a/core/configuration-chain_test.go b/core/configuration-chain_test.go
index af7e36d..a4c6e2a 100644
--- a/core/configuration-chain_test.go
+++ b/core/configuration-chain_test.go
@@ -430,10 +430,17 @@ func (s *ConfigurationChainTestSuite) TestDKGComplaintDelayAdd() {
errs <- cc.runDKG(round, reset)
}(cc)
}
+ complaints := -1
go func() {
// Node 0 proposes NackComplaint to all others at 3λ but they should
- // be ignored because NackComplaint shoould be proposed before 2λ.
+ // be ignored because NackComplaint should be proposed before 2λ.
time.Sleep(lambdaDKG * 3)
+ for _, gov := range recv.govs {
+ if complaints == -1 {
+ complaints = len(gov.DKGComplaints(round))
+ }
+ s.Require().Len(gov.DKGComplaints(round), complaints)
+ }
nID := s.nIDs[0]
for _, targetNode := range s.nIDs {
if targetNode == nID {
@@ -449,15 +456,19 @@ func (s *ConfigurationChainTestSuite) TestDKGComplaintDelayAdd() {
}
}()
wg.Wait()
+ complaints += len(s.nIDs) - 1
+ for _, gov := range recv.govs {
+ s.Require().Len(gov.DKGComplaints(round), complaints)
+ }
for range cfgChains {
s.Require().NoError(<-errs)
}
for nID, cc := range cfgChains {
if _, exist := cc.npks[round]; !exist {
- s.FailNow("Should be qualifyied")
+ s.FailNow("Should be qualified")
}
if _, exist := cc.npks[round].QualifyNodeIDs[nID]; !exist {
- s.FailNow("Should be qualifyied")
+ s.FailNow("Should be qualified")
}
}
}
diff --git a/core/consensus.go b/core/consensus.go
index d74a4a2..2b0d5a4 100644
--- a/core/consensus.go
+++ b/core/consensus.go
@@ -27,6 +27,7 @@ import (
"github.com/dexon-foundation/dexon-consensus/common"
"github.com/dexon-foundation/dexon-consensus/core/crypto"
+ cryptoDKG "github.com/dexon-foundation/dexon-consensus/core/crypto/dkg"
"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"
@@ -51,6 +52,8 @@ var (
"CRS not ready")
ErrConfigurationNotReady = fmt.Errorf(
"Configuration not ready")
+ ErrIncorrectBlockRandomness = fmt.Errorf(
+ "randomness of block is incorrect")
)
// consensusBAReceiver implements agreementReceiver.
@@ -62,6 +65,8 @@ type consensusBAReceiver struct {
roundValue *atomic.Value
isNotary bool
restartNotary chan types.Position
+ npks *typesDKG.NodePublicKeys
+ psigSigner *dkgShareSecret
}
func (recv *consensusBAReceiver) round() uint64 {
@@ -72,10 +77,51 @@ func (recv *consensusBAReceiver) changeNotaryHeight() uint64 {
return recv.changeNotaryHeightValue.Load().(uint64)
}
+func (recv *consensusBAReceiver) VerifyPartialSignature(vote *types.Vote) bool {
+ if recv.round() >= DKGDelayRound && vote.BlockHash != types.SkipBlockHash {
+ if vote.Type == types.VoteCom || vote.Type == types.VoteFastCom {
+ if recv.npks == nil || recv.npks.Round != vote.Position.Round {
+ var err error
+ recv.npks, _, err =
+ recv.consensus.cfgModule.getDKGInfo(vote.Position.Round, true)
+ if err != nil || recv.npks == nil {
+ recv.consensus.logger.Warn("cannot get npks",
+ "round", vote.Position.Round, "error", err)
+ return false
+ }
+ }
+ pubKey, exist := recv.npks.PublicKeys[vote.ProposerID]
+ if !exist {
+ return false
+ }
+ blockHash := vote.BlockHash
+ if blockHash == types.NullBlockHash {
+ blockHash = utils.HashPosition(vote.Position)
+ }
+ return pubKey.VerifySignature(
+ vote.BlockHash, crypto.Signature(vote.PartialSignature))
+ }
+ }
+ return len(vote.PartialSignature.Signature) == 0
+}
+
func (recv *consensusBAReceiver) ProposeVote(vote *types.Vote) {
if !recv.isNotary {
return
}
+ if recv.round() >= DKGDelayRound && vote.BlockHash != types.SkipBlockHash {
+ if vote.Type == types.VoteCom || vote.Type == types.VoteFastCom {
+ if recv.psigSigner == nil {
+ return
+ }
+ if vote.BlockHash == types.NullBlockHash {
+ vote.PartialSignature = recv.psigSigner.sign(
+ utils.HashPosition(vote.Position))
+ } else {
+ vote.PartialSignature = recv.psigSigner.sign(vote.BlockHash)
+ }
+ }
+ }
if err := recv.agreementModule.prepareVote(vote); err != nil {
recv.consensus.logger.Error("Failed to prepare vote", "error", err)
return
@@ -120,6 +166,7 @@ func (recv *consensusBAReceiver) ConfirmBlock(
block *types.Block
aID = recv.agreementModule.agreementID()
)
+
isEmptyBlockConfirmed := hash == common.Hash{}
if isEmptyBlockConfirmed {
recv.consensus.logger.Info("Empty block is confirmed", "position", aID)
@@ -177,6 +224,47 @@ func (recv *consensusBAReceiver) ConfirmBlock(
return
}
}
+
+ voteList := make([]types.Vote, 0, len(votes))
+ IDs := make(cryptoDKG.IDs, 0, len(votes))
+ psigs := make([]cryptoDKG.PartialSignature, 0, len(votes))
+ for _, vote := range votes {
+ if vote.BlockHash != hash {
+ continue
+ }
+ if recv.round() >= DKGDelayRound {
+ ID, exist := recv.npks.IDMap[vote.ProposerID]
+ if !exist {
+ continue
+ }
+ IDs = append(IDs, ID)
+ psigs = append(psigs, vote.PartialSignature)
+ }
+ voteList = append(voteList, *vote)
+ }
+ if recv.round() >= DKGDelayRound {
+ rand, err := cryptoDKG.RecoverSignature(psigs, IDs)
+ if err != nil {
+ recv.consensus.logger.Warn("Unable to recover randomness",
+ "block", block,
+ "error", err)
+ } else {
+ block.Finalization.Randomness = rand.Signature[:]
+ }
+ }
+ if recv.isNotary {
+ result := &types.AgreementResult{
+ BlockHash: block.Hash,
+ Position: block.Position,
+ Votes: voteList,
+ Randomness: block.Finalization.Randomness,
+ IsEmptyBlock: isEmptyBlockConfirmed,
+ }
+ recv.consensus.logger.Debug("Propose AgreementResult",
+ "result", result)
+ recv.consensus.msgChan <- result
+ }
+
if block.Position.Height != 0 &&
!recv.consensus.bcModule.confirmed(block.Position.Height-1) {
go func(hash common.Hash) {
@@ -222,25 +310,9 @@ func (recv *consensusBAReceiver) ConfirmBlock(
}
}(block.ParentHash)
}
- if recv.isNotary {
- voteList := make([]types.Vote, 0, len(votes))
- for _, vote := range votes {
- if vote.BlockHash != hash {
- continue
- }
- voteList = append(voteList, *vote)
- }
- 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)
+ if !block.IsEmpty() {
+ recv.consensus.processBlockChan <- block
}
- recv.consensus.processBlockChan <- block
// Clean the restartNotary channel so BA will not stuck by deadlock.
CleanChannelLoop:
for {
@@ -253,7 +325,7 @@ CleanChannelLoop:
newPos := block.Position
if block.Position.Height+1 == recv.changeNotaryHeight() {
newPos.Round++
- recv.roundValue.Store(newPos.Round)
+ recv.updateRound(newPos.Round)
}
currentRound := recv.round()
changeNotaryHeight := recv.changeNotaryHeight()
@@ -282,6 +354,18 @@ func (recv *consensusBAReceiver) ReportForkBlock(b1, b2 *types.Block) {
recv.consensus.gov.ReportForkBlock(b1, b2)
}
+func (recv *consensusBAReceiver) updateRound(round uint64) {
+ recv.roundValue.Store(round)
+ var err error
+ _, recv.psigSigner, err =
+ recv.consensus.cfgModule.getDKGInfo(round, false)
+ if err != nil {
+ recv.consensus.logger.Warn("cannot get dkg info",
+ "round", round, "error", err)
+ recv.psigSigner = nil
+ }
+}
+
// consensusDKGReceiver implements dkgReceiver.
type consensusDKGReceiver struct {
ID types.NodeID
@@ -401,13 +485,13 @@ type Consensus struct {
bcModule *blockChain
dMoment time.Time
nodeSetCache *utils.NodeSetCache
+ tsigVerifierCache *TSigVerifierCache
lock sync.RWMutex
ctx context.Context
ctxCancel context.CancelFunc
event *common.Event
roundEvent *utils.RoundEvent
logger common.Logger
- resetRandomnessTicker chan struct{}
resetDeliveryGuardTicker chan struct{}
msgChan chan interface{}
waitGroup sync.WaitGroup
@@ -465,7 +549,6 @@ func NewConsensusFromSyncer(
networkModule Network,
prv crypto.PrivateKey,
confirmedBlocks []*types.Block,
- randomnessResults []*types.BlockRandomnessResult,
cachedMessages []interface{},
logger common.Logger) (*Consensus, error) {
// Setup Consensus instance.
@@ -492,30 +575,13 @@ func NewConsensusFromSyncer(
}
refBlock = b
}
- // Dump all randomness result to the consensus instance.
- for _, r := range randomnessResults {
- if err := con.ProcessBlockRandomnessResult(r, false); err != nil {
- con.logger.Error("failed to process randomness result when syncing",
- "result", r)
- continue
- }
- }
if startWithEmpty {
pos := initBlock.Position
pos.Height++
- block, err := con.bcModule.addEmptyBlock(pos)
+ _, err := con.bcModule.addEmptyBlock(pos)
if err != nil {
panic(err)
}
- con.processBlockChan <- block
- if pos.Round >= DKGDelayRound {
- rand := &types.AgreementResult{
- BlockHash: block.Hash,
- Position: block.Position,
- IsEmptyBlock: true,
- }
- go con.prepareRandomnessResult(rand)
- }
}
return con, nil
}
@@ -566,8 +632,9 @@ func newConsensusForRound(
if usingNonBlocking {
appModule = newNonBlocking(app, debugApp)
}
+ tsigVerifierCache := NewTSigVerifierCache(gov, 7)
bcModule := newBlockChain(ID, dMoment, initBlock, appModule,
- NewTSigVerifierCache(gov, 7), signer, logger)
+ tsigVerifierCache, signer, logger)
// Construct Consensus instance.
con := &Consensus{
ID: ID,
@@ -582,10 +649,10 @@ func newConsensusForRound(
bcModule: bcModule,
dMoment: dMoment,
nodeSetCache: nodeSetCache,
+ tsigVerifierCache: tsigVerifierCache,
signer: signer,
event: common.NewEvent(),
logger: logger,
- resetRandomnessTicker: make(chan struct{}),
resetDeliveryGuardTicker: make(chan struct{}),
msgChan: make(chan interface{}, 1024),
processBlockChan: make(chan *types.Block, 1024),
@@ -690,14 +757,14 @@ func (con *Consensus) prepare(initBlock *types.Block) (err error) {
if nextRound < DKGDelayRound {
return
}
- curDKGSet, err := con.nodeSetCache.GetDKGSet(e.Round)
+ curNotarySet, err := con.nodeSetCache.GetNotarySet(e.Round)
if err != nil {
- con.logger.Error("Error getting DKG set when proposing CRS",
+ con.logger.Error("Error getting notary set when proposing CRS",
"round", e.Round,
"error", err)
return
}
- if _, exist := curDKGSet[con.ID]; !exist {
+ if _, exist := curNotarySet[con.ID]; !exist {
return
}
isDKGValid := func() bool {
@@ -733,18 +800,18 @@ func (con *Consensus) prepare(initBlock *types.Block) (err error) {
// Register round event handler to propose new CRS.
con.roundEvent.Register(func(evts []utils.RoundEventParam) {
// We don't have to propose new CRS during DKG reset, the reset of DKG
- // would be done by the DKG set in previous round.
+ // would be done by the notary set in previous round.
e := evts[len(evts)-1]
defer elapse("propose-CRS", e)()
if e.Reset != 0 || e.Round < DKGDelayRound {
return
}
- if curDkgSet, err := con.nodeSetCache.GetDKGSet(e.Round); err != nil {
- con.logger.Error("Error getting DKG set when proposing CRS",
+ if curNotarySet, err := con.nodeSetCache.GetNotarySet(e.Round); err != nil {
+ con.logger.Error("Error getting notary set when proposing CRS",
"round", e.Round,
"error", err)
} else {
- if _, exist := curDkgSet[con.ID]; !exist {
+ if _, exist := curNotarySet[con.ID]; !exist {
return
}
con.event.RegisterHeight(e.NextCRSProposingHeight(), func(uint64) {
@@ -809,26 +876,26 @@ func (con *Consensus) prepare(initBlock *types.Block) (err error) {
// of unexpected network fluctuation and ensure the robustness.
if !checkWithCancel(
con.ctx, 500*time.Millisecond, checkCRS(nextRound)) {
- con.logger.Debug("unable to prepare CRS for DKG set",
+ con.logger.Debug("unable to prepare CRS for notary set",
"round", nextRound,
"reset", e.Reset)
return
}
- nextDkgSet, err := con.nodeSetCache.GetDKGSet(nextRound)
+ nextNotarySet, err := con.nodeSetCache.GetNotarySet(nextRound)
if err != nil {
- con.logger.Error("Error getting DKG set for next round",
+ con.logger.Error("Error getting notary set for next round",
"round", nextRound,
"reset", e.Reset,
"error", err)
return
}
- if _, exist := nextDkgSet[con.ID]; !exist {
- con.logger.Info("Not selected as DKG set",
+ if _, exist := nextNotarySet[con.ID]; !exist {
+ con.logger.Info("Not selected as notary set",
"round", nextRound,
"reset", e.Reset)
return
}
- con.logger.Info("Selected as DKG set",
+ con.logger.Info("Selected as notary set",
"round", nextRound,
"reset", e.Reset)
nextConfig := utils.GetConfigWithPanic(con.gov, nextRound,
@@ -865,12 +932,6 @@ func (con *Consensus) Run() {
con.waitGroup.Add(1)
go con.processMsg()
go con.processBlockLoop()
- // Sleep until dMoment come.
- time.Sleep(con.dMoment.Sub(time.Now().UTC()))
- // Take some time to bootstrap.
- time.Sleep(3 * time.Second)
- con.waitGroup.Add(1)
- go con.pullRandomness()
// Stop dummy receiver if launched.
if con.dummyCancel != nil {
con.logger.Trace("Stop dummy receiver")
@@ -893,6 +954,10 @@ func (con *Consensus) Run() {
}
con.logger.Trace("Finish dumping cached messages")
}
+ // Sleep until dMoment come.
+ time.Sleep(con.dMoment.Sub(time.Now().UTC()))
+ // Take some time to bootstrap.
+ time.Sleep(3 * time.Second)
con.waitGroup.Add(1)
go con.deliveryGuard()
// Block until done.
@@ -964,7 +1029,6 @@ func (con *Consensus) Stop() {
con.event.Reset()
con.waitGroup.Wait()
if nbApp, ok := con.app.(*nonBlocking); ok {
- fmt.Println("Stopping nonBlocking App")
nbApp.wait()
}
}
@@ -1019,11 +1083,47 @@ MessageLoop:
ch, e := con.baConfirmedBlock[val.Hash]
return ch, e
}(); exist {
- if err := utils.VerifyBlockSignature(val); err != nil {
- con.logger.Error("VerifyBlockSignature failed",
- "block", val,
- "error", err)
- continue MessageLoop
+ if val.IsEmpty() {
+ hash, err := utils.HashBlock(val)
+ if err != nil {
+ con.logger.Error("error verifying empty block hash",
+ "block", val,
+ "error, err")
+ continue MessageLoop
+ }
+ if hash != val.Hash {
+ con.logger.Error("incorrect confirmed empty block hash",
+ "block", val,
+ "hash", hash)
+ continue MessageLoop
+ }
+ if _, err := con.bcModule.proposeBlock(
+ val.Position, time.Time{}, true); err != nil {
+ con.logger.Error("error adding empty block",
+ "block", val,
+ "error", err)
+ continue MessageLoop
+ }
+ } else {
+ ok, err := con.bcModule.verifyRandomness(
+ val.Hash, val.Position.Round, val.Finalization.Randomness)
+ if err != nil {
+ con.logger.Error("error verifying confirmed block randomness",
+ "block", val,
+ "error", err)
+ continue MessageLoop
+ }
+ if !ok {
+ con.logger.Error("incorrect confirmed block randomness",
+ "block", val)
+ continue MessageLoop
+ }
+ if err := utils.VerifyBlockSignature(val); err != nil {
+ con.logger.Error("VerifyBlockSignature failed",
+ "block", val,
+ "error", err)
+ continue MessageLoop
+ }
}
func() {
con.lock.Lock()
@@ -1035,13 +1135,6 @@ MessageLoop:
delete(con.baConfirmedBlock, val.Hash)
ch <- val
}()
- } else if val.IsFinalized() {
- // 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",
@@ -1061,13 +1154,6 @@ MessageLoop:
"result", val,
"error", err)
}
- case *types.BlockRandomnessResult:
- 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,
- "error", err)
- }
case *typesDKG.PrivateShare:
if err := con.cfgModule.processPrivateShare(val); err != nil {
con.logger.Error("Failed to process private share",
@@ -1096,6 +1182,15 @@ func (con *Consensus) ProcessAgreementResult(
if !con.baMgr.touchAgreementResult(rand) {
return nil
}
+ // TODO(jimmy): merge tsig check to VerifyAgreementResult
+ ok, err := con.bcModule.verifyRandomness(
+ rand.BlockHash, rand.Position.Round, rand.Randomness)
+ if err != nil {
+ return err
+ }
+ if !ok {
+ return ErrIncorrectBlockRandomness
+ }
// Sanity Check.
if err := VerifyAgreementResult(rand, con.nodeSetCache); err != nil {
con.baMgr.untouchAgreementResult(rand)
@@ -1105,96 +1200,11 @@ func (con *Consensus) ProcessAgreementResult(
if err := con.baMgr.processAgreementResult(rand); err != nil {
return err
}
- // Calculating randomness.
- if rand.Position.Round == 0 {
- 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
- }
- con.logger.Debug("Rebroadcast AgreementResult",
+ con.logger.Debug("Broadcast AgreementResult",
"result", rand)
con.network.BroadcastAgreementResult(rand)
- go con.prepareRandomnessResult(rand)
- return nil
-}
-func (con *Consensus) prepareRandomnessResult(rand *types.AgreementResult) {
- dkgSet, err := con.nodeSetCache.GetDKGSet(rand.Position.Round)
- if err != nil {
- con.logger.Error("Failed to get dkg set",
- "round", rand.Position.Round, "error", err)
- return
- }
- if _, exist := dkgSet[con.ID]; !exist {
- return
- }
- con.logger.Debug("PrepareRandomness", "round", rand.Position.Round, "hash", rand.BlockHash)
- psig, err := con.cfgModule.preparePartialSignature(rand.Position.Round, rand.BlockHash)
- if err != nil {
- con.logger.Error("Failed to prepare psig",
- "round", rand.Position.Round,
- "hash", rand.BlockHash.String()[:6],
- "error", err)
- return
- }
- if err = con.signer.SignDKGPartialSignature(psig); err != nil {
- con.logger.Error("Failed to sign psig",
- "hash", rand.BlockHash.String()[:6],
- "error", err)
- return
- }
- if err = con.cfgModule.processPartialSignature(psig); err != nil {
- con.logger.Error("Failed process psig",
- "hash", rand.BlockHash.String()[:6],
- "error", err)
- return
- }
- con.logger.Debug("Calling Network.BroadcastDKGPartialSignature",
- "proposer", psig.ProposerID,
- "round", psig.Round,
- "hash", psig.Hash.String()[:6])
- con.network.BroadcastDKGPartialSignature(psig)
- tsig, err := con.cfgModule.runTSig(rand.Position.Round, rand.BlockHash)
- if err != nil {
- if err != ErrTSigAlreadyRunning {
- con.logger.Error("Failed to run TSIG",
- "position", rand.Position,
- "hash", rand.BlockHash.String()[:6],
- "error", err)
- }
- return
- }
- result := &types.BlockRandomnessResult{
- BlockHash: rand.BlockHash,
- Position: rand.Position,
- Randomness: tsig.Signature,
- }
- // ProcessBlockRandomnessResult is not thread-safe so we put the result in
- // the message channnel to be processed in the main thread.
- con.msgChan <- result
-}
-
-// ProcessBlockRandomnessResult processes the randomness result.
-func (con *Consensus) ProcessBlockRandomnessResult(
- rand *types.BlockRandomnessResult, needBroadcast bool) error {
- if rand.Position.Round == 0 {
- return nil
- }
- if !con.bcModule.shouldAddRandomness(rand) {
- return nil
- }
- if err := con.bcModule.addRandomness(rand); err != nil {
- return err
- }
- if needBroadcast {
- con.logger.Debug("Calling Network.BroadcastRandomnessResult",
- "randomness", rand)
- con.network.BroadcastRandomnessResult(rand)
- }
return con.deliverFinalizedBlocks()
}
@@ -1207,33 +1217,12 @@ func (con *Consensus) preProcessBlock(b *types.Block) (err error) {
return
}
-func (con *Consensus) pullRandomness() {
- defer con.waitGroup.Done()
- for {
- select {
- case <-con.ctx.Done():
- return
- default:
- }
- select {
- case <-con.ctx.Done():
- return
- case <-con.resetRandomnessTicker:
- case <-time.After(1500 * time.Millisecond):
- // TODO(jimmy): pulling period should be related to lambdaBA.
- hashes := con.bcModule.pendingBlocksWithoutRandomness()
- if len(hashes) > 0 {
- con.logger.Debug(
- "Calling Network.PullRandomness", "blocks", hashes)
- con.network.PullRandomness(hashes)
- }
- }
- }
-}
-
func (con *Consensus) deliveryGuard() {
defer con.waitGroup.Done()
- time.Sleep(con.dMoment.Sub(time.Now()))
+ select {
+ case <-con.ctx.Done():
+ case <-time.After(con.dMoment.Sub(time.Now())):
+ }
// Node takes time to start.
select {
case <-con.ctx.Done():
@@ -1259,10 +1248,6 @@ func (con *Consensus) deliveryGuard() {
// deliverBlock deliver a block to application layer.
func (con *Consensus) deliverBlock(b *types.Block) {
select {
- case con.resetRandomnessTicker <- struct{}{}:
- default:
- }
- select {
case con.resetDeliveryGuardTicker <- struct{}{}:
default:
}
@@ -1274,7 +1259,6 @@ func (con *Consensus) deliverBlock(b *types.Block) {
b.Hash, b.Finalization.Height); err != nil {
panic(err)
}
- con.cfgModule.untouchTSigHash(b.Hash)
con.logger.Debug("Calling Application.BlockDelivered", "block", b)
con.app.BlockDelivered(b.Hash, b.Position, b.Finalization.Clone())
if con.debugApp != nil {
@@ -1338,15 +1322,10 @@ func (con *Consensus) processBlock(block *types.Block) (err error) {
return
}
-// processFinalizedBlock is the entry point for handling finalized blocks.
-func (con *Consensus) processFinalizedBlock(block *types.Block) error {
- return con.bcModule.processFinalizedBlock(block)
-}
-
// PrepareBlock would setup header fields of block based on its ProposerID.
func (con *Consensus) proposeBlock(position types.Position) (
*types.Block, error) {
- b, err := con.bcModule.proposeBlock(position, time.Now().UTC())
+ b, err := con.bcModule.proposeBlock(position, time.Now().UTC(), false)
if err != nil {
return nil, err
}
diff --git a/core/consensus_test.go b/core/consensus_test.go
index 8744c00..9565e95 100644
--- a/core/consensus_test.go
+++ b/core/consensus_test.go
@@ -67,12 +67,6 @@ func (n *network) BroadcastAgreementResult(
n.conn.broadcast(n.nID, randRequest)
}
-// BroadcastRandomnessResult broadcasts rand request to Notary set.
-func (n *network) BroadcastRandomnessResult(
- randResult *types.BlockRandomnessResult) {
- n.conn.broadcast(n.nID, randResult)
-}
-
// SendDKGPrivateShare sends PrivateShare to a DKG participant.
func (n *network) SendDKGPrivateShare(
recv crypto.PublicKey, prvShare *typesDKG.PrivateShare) {
@@ -158,8 +152,6 @@ func (nc *networkConnection) setCon(nID types.NodeID, con *Consensus) {
err = con.ProcessVote(val)
case *types.AgreementResult:
err = con.ProcessAgreementResult(val)
- case *types.BlockRandomnessResult:
- err = con.ProcessBlockRandomnessResult(val, true)
case *typesDKG.PrivateShare:
err = con.cfgModule.processPrivateShare(val)
case *typesDKG.PartialSignature:
@@ -236,10 +228,14 @@ func (s *ConsensusTestSuite) TestRegisteredDKGRecover() {
s.Require().Nil(con.cfgModule.dkg)
con.cfgModule.registerDKG(con.ctx, 0, 0, 10)
+ con.cfgModule.dkgLock.Lock()
+ defer con.cfgModule.dkgLock.Unlock()
_, newCon := s.prepareConsensusWithDB(dMoment, gov, prvKeys[0], conn, dbInst)
newCon.cfgModule.registerDKG(newCon.ctx, 0, 0, 10)
+ newCon.cfgModule.dkgLock.Lock()
+ defer newCon.cfgModule.dkgLock.Unlock()
s.Require().NotNil(newCon.cfgModule.dkg)
s.Require().True(newCon.cfgModule.dkg.prvShares.Equal(con.cfgModule.dkg.prvShares))
@@ -377,7 +373,6 @@ func (s *ConsensusTestSuite) TestInitialHeightEventTriggered() {
network,
prvKey,
[]*types.Block(nil),
- []*types.BlockRandomnessResult(nil),
[]interface{}(nil),
&common.NullLogger{},
)
diff --git a/core/interfaces.go b/core/interfaces.go
index 06838e0..407eaea 100644
--- a/core/interfaces.go
+++ b/core/interfaces.go
@@ -64,9 +64,6 @@ type Network interface {
// PullVotes tries to pull votes from the DEXON network.
PullVotes(position types.Position)
- // PullRandomness tries to pull randomness from the DEXON network.
- PullRandomness(hashes common.Hashes)
-
// BroadcastVote broadcasts vote to all nodes in DEXON network.
BroadcastVote(vote *types.Vote)
@@ -76,9 +73,6 @@ type Network interface {
// BroadcastAgreementResult broadcasts agreement result to DKG set.
BroadcastAgreementResult(randRequest *types.AgreementResult)
- // BroadcastRandomnessResult broadcasts rand request to Notary set.
- BroadcastRandomnessResult(randResult *types.BlockRandomnessResult)
-
// SendDKGPrivateShare sends PrivateShare to a DKG participant.
SendDKGPrivateShare(pub crypto.PublicKey, prvShare *typesDKG.PrivateShare)
diff --git a/core/syncer/consensus.go b/core/syncer/consensus.go
index 24c781a..65068a4 100644
--- a/core/syncer/consensus.go
+++ b/core/syncer/consensus.go
@@ -63,7 +63,6 @@ type Consensus struct {
nodeSetCache *utils.NodeSetCache
tsigVerifier *core.TSigVerifierCache
- randomnessResults map[common.Hash]*types.BlockRandomnessResult
blocks types.BlocksByPosition
agreementModule *agreement
agreementRoundCut uint64
@@ -100,19 +99,18 @@ func NewConsensus(
logger common.Logger) *Consensus {
con := &Consensus{
- dMoment: dMoment,
- app: app,
- gov: gov,
- db: db,
- network: network,
- nodeSetCache: utils.NewNodeSetCache(gov),
- tsigVerifier: core.NewTSigVerifierCache(gov, 7),
- prv: prv,
- logger: logger,
- receiveChan: make(chan *types.Block, 1000),
- pullChan: make(chan common.Hash, 1000),
- randomnessResults: make(map[common.Hash]*types.BlockRandomnessResult),
- heightEvt: common.NewEvent(),
+ dMoment: dMoment,
+ app: app,
+ gov: gov,
+ db: db,
+ network: network,
+ nodeSetCache: utils.NewNodeSetCache(gov),
+ tsigVerifier: core.NewTSigVerifierCache(gov, 7),
+ prv: prv,
+ logger: logger,
+ receiveChan: make(chan *types.Block, 1000),
+ pullChan: make(chan common.Hash, 1000),
+ heightEvt: common.NewEvent(),
}
con.ctx, con.ctxCancel = context.WithCancel(context.Background())
_, con.initChainTipHeight = db.GetCompactionChainTipInfo()
@@ -360,10 +358,6 @@ func (con *Consensus) GetSyncedConsensus() (*core.Consensus, error) {
}
// flush all blocks in con.blocks into core.Consensus, and build
// core.Consensus from syncer.
- randomnessResults := []*types.BlockRandomnessResult{}
- for _, r := range con.randomnessResults {
- randomnessResults = append(randomnessResults, r)
- }
con.dummyCancel()
<-con.dummyFinished
var err error
@@ -377,7 +371,6 @@ func (con *Consensus) GetSyncedConsensus() (*core.Consensus, error) {
con.network,
con.prv,
con.blocks,
- randomnessResults,
con.dummyMsgBuffer,
con.logger)
return con.syncedConsensus, err
@@ -475,55 +468,6 @@ func (con *Consensus) startAgreement() {
}()
}
-func (con *Consensus) cacheRandomnessResult(r *types.BlockRandomnessResult) {
- // There is no block randomness at round-0.
- if r.Position.Round == 0 {
- return
- }
- // We only have to cache randomness result after cutting round.
- if func() bool {
- con.lock.RLock()
- defer con.lock.RUnlock()
- if len(con.blocks) > 0 && r.Position.Older(con.blocks[0].Position) {
- return true
- }
- if r.Position.Round > con.latestCRSRound {
- // We can't process randomness from rounds that its CRS is still
- // unknown.
- return true
- }
- _, exists := con.randomnessResults[r.BlockHash]
- return exists
- }() {
- return
- }
- v, ok, err := con.tsigVerifier.UpdateAndGet(r.Position.Round)
- if err != nil {
- con.logger.Error("Unable to get tsig verifier",
- "hash", r.BlockHash.String()[:6],
- "position", r.Position,
- "error", err,
- )
- return
- }
- if !ok {
- con.logger.Error("Tsig is not ready", "position", &r.Position)
- return
- }
- if !v.VerifySignature(r.BlockHash, crypto.Signature{
- Type: "bls",
- Signature: r.Randomness}) {
- con.logger.Info("Block randomness is not valid",
- "position", r.Position,
- "hash", r.BlockHash.String()[:6],
- )
- return
- }
- con.lock.Lock()
- defer con.lock.Unlock()
- con.randomnessResults[r.BlockHash] = r
-}
-
// startNetwork starts network for receiving blocks and agreement results.
func (con *Consensus) startNetwork() {
con.waitGroup.Add(1)
@@ -542,9 +486,6 @@ func (con *Consensus) startNetwork() {
if v.Position.Height <= con.initChainTipHeight {
continue loop
}
- case *types.BlockRandomnessResult:
- con.cacheRandomnessResult(v)
- continue loop
default:
continue loop
}
diff --git a/core/test/governance.go b/core/test/governance.go
index e256504..538d064 100644
--- a/core/test/governance.go
+++ b/core/test/governance.go
@@ -231,7 +231,7 @@ func (g *Governance) IsDKGMPKReady(round uint64) bool {
if round >= uint64(len(g.configs)) {
return false
}
- return g.stateModule.IsDKGMPKReady(round, int(g.configs[round].DKGSetSize)/3*2)
+ return g.stateModule.IsDKGMPKReady(round, int(g.configs[round].NotarySetSize)/3*2)
}
// AddDKGFinalize adds a DKG finalize message.
@@ -259,7 +259,7 @@ func (g *Governance) IsDKGFinal(round uint64) bool {
if round >= uint64(len(g.configs)) {
return false
}
- return g.stateModule.IsDKGFinal(round, int(g.configs[round].DKGSetSize)/3*2)
+ return g.stateModule.IsDKGFinal(round, int(g.configs[round].NotarySetSize)/3*2)
}
// ReportForkVote reports a node for forking votes.
@@ -449,7 +449,7 @@ func (g *Governance) Equal(other *Governance, checkState bool) bool {
// NOTE: this function should be called before running.
func (g *Governance) RegisterConfigChange(
round uint64, t StateChangeType, v interface{}) (err error) {
- if t < StateAddCRS || t > StateChangeDKGSetSize {
+ if t < StateAddCRS || t > StateChangeNotarySetSize {
return fmt.Errorf("state changes to register is not supported: %v", t)
}
if round < 2 {
diff --git a/core/test/governance_test.go b/core/test/governance_test.go
index b64f785..474ec80 100644
--- a/core/test/governance_test.go
+++ b/core/test/governance_test.go
@@ -92,16 +92,16 @@ func (s *GovernanceTestSuite) TestRegisterChange() {
req.NoError(g.State().RequestChange(StateChangeRoundLength,
uint64(roundLength)))
// Unable to register change for genesis round.
- req.Error(g.RegisterConfigChange(0, StateChangeDKGSetSize, uint32(32)))
+ req.Error(g.RegisterConfigChange(0, StateChangeNotarySetSize, uint32(32)))
// Make some round prepared.
g.CatchUpWithRound(4)
- req.Equal(g.Configuration(4).DKGSetSize, uint32(20))
+ req.Equal(g.Configuration(4).NotarySetSize, uint32(20))
// Unable to register change for prepared round.
- req.Error(g.RegisterConfigChange(4, StateChangeDKGSetSize, uint32(32)))
+ req.Error(g.RegisterConfigChange(4, StateChangeNotarySetSize, uint32(32)))
// It's ok to make some change when condition is met.
- req.NoError(g.RegisterConfigChange(5, StateChangeDKGSetSize, uint32(32)))
- req.NoError(g.RegisterConfigChange(6, StateChangeDKGSetSize, uint32(32)))
- req.NoError(g.RegisterConfigChange(7, StateChangeDKGSetSize, uint32(40)))
+ req.NoError(g.RegisterConfigChange(5, StateChangeNotarySetSize, uint32(32)))
+ req.NoError(g.RegisterConfigChange(6, StateChangeNotarySetSize, uint32(32)))
+ req.NoError(g.RegisterConfigChange(7, StateChangeNotarySetSize, uint32(40)))
// In local mode, state for round 6 would be ready after notified with
// round 2.
g.NotifyRound(2, roundLength*2)
@@ -111,8 +111,8 @@ func (s *GovernanceTestSuite) TestRegisterChange() {
g.NotifyRound(4, roundLength*4)
// Notify governance to take a snapshot for round 7's configuration.
g.NotifyRound(5, roundLength*5)
- req.Equal(g.Configuration(6).DKGSetSize, uint32(32))
- req.Equal(g.Configuration(7).DKGSetSize, uint32(40))
+ req.Equal(g.Configuration(6).NotarySetSize, uint32(32))
+ req.Equal(g.Configuration(7).NotarySetSize, uint32(40))
}
func (s *GovernanceTestSuite) TestProhibit() {
diff --git a/core/test/marshaller.go b/core/test/marshaller.go
index 5f15e11..91a3057 100644
--- a/core/test/marshaller.go
+++ b/core/test/marshaller.go
@@ -53,14 +53,8 @@ func (m *DefaultMarshaller) Unmarshal(
break
}
msg = vote
- case "block-randomness-request":
- request := &types.AgreementResult{}
- if err = json.Unmarshal(payload, request); err != nil {
- break
- }
- msg = request
- case "block-randomness-result":
- result := &types.BlockRandomnessResult{}
+ case "agreement-result":
+ result := &types.AgreementResult{}
if err = json.Unmarshal(payload, result); err != nil {
break
}
@@ -128,10 +122,7 @@ func (m *DefaultMarshaller) Marshal(
msgType = "vote"
payload, err = json.Marshal(msg)
case *types.AgreementResult:
- msgType = "block-randomness-request"
- payload, err = json.Marshal(msg)
- case *types.BlockRandomnessResult:
- msgType = "block-randomness-result"
+ msgType = "agreement-result"
payload, err = json.Marshal(msg)
case *typesDKG.PrivateShare:
msgType = "dkg-private-share"
diff --git a/core/test/network.go b/core/test/network.go
index 443a26c..6034fa6 100644
--- a/core/test/network.go
+++ b/core/test/network.go
@@ -39,6 +39,9 @@ const (
maxPullingPeerCount = 3
maxBlockCache = 1000
maxVoteCache = 128
+
+ // Gossiping parameter.
+ gossipAgreementResultPercent = 33
)
// NetworkType is the simulation network type.
@@ -77,8 +80,6 @@ func (req *PullRequest) MarshalJSON() (b []byte, err error) {
idAsBytes, err = json.Marshal(req.Identity.(common.Hashes))
case "vote":
idAsBytes, err = json.Marshal(req.Identity.(types.Position))
- case "randomness":
- idAsBytes, err = json.Marshal(req.Identity.(common.Hashes))
default:
err = fmt.Errorf("unknown ID type for pull request: %v", req.Type)
}
@@ -117,12 +118,6 @@ func (req *PullRequest) UnmarshalJSON(data []byte) (err error) {
break
}
ID = pos
- case "randomness":
- hashes := common.Hashes{}
- if err = json.Unmarshal(rawReq.Identity, &hashes); err != nil {
- break
- }
- ID = hashes
default:
err = fmt.Errorf("unknown pull request type: %v", rawReq.Type)
}
@@ -137,38 +132,30 @@ func (req *PullRequest) UnmarshalJSON(data []byte) (err error) {
// Network implements core.Network interface based on TransportClient.
type Network struct {
- ID types.NodeID
- config NetworkConfig
- ctx context.Context
- ctxCancel context.CancelFunc
- trans TransportClient
- dMoment time.Time
- fromTransport <-chan *TransportEnvelope
- toConsensus chan interface{}
- toNode chan interface{}
- sentRandomnessLock sync.Mutex
- sentRandomness map[common.Hash]struct{}
- sentAgreementLock sync.Mutex
- sentAgreement map[common.Hash]struct{}
- blockCacheLock sync.RWMutex
- blockCache map[common.Hash]*types.Block
- voteCacheLock sync.RWMutex
- voteCache map[types.Position]map[types.VoteHeader]*types.Vote
- voteCacheSize int
- votePositions []types.Position
- randomnessCacheLock sync.RWMutex
- randomnessCache map[common.Hash]*types.BlockRandomnessResult
- stateModule *State
- peers map[types.NodeID]struct{}
- unreceivedBlocksLock sync.RWMutex
- unreceivedBlocks map[common.Hash]chan<- common.Hash
- unreceivedRandomnessLock sync.RWMutex
- unreceivedRandomness map[common.Hash]chan<- common.Hash
- cache *utils.NodeSetCache
- notarySetCachesLock sync.Mutex
- notarySetCaches map[uint64]map[types.NodeID]struct{}
- dkgSetCachesLock sync.Mutex
- dkgSetCaches map[uint64]map[types.NodeID]struct{}
+ ID types.NodeID
+ config NetworkConfig
+ ctx context.Context
+ ctxCancel context.CancelFunc
+ trans TransportClient
+ dMoment time.Time
+ fromTransport <-chan *TransportEnvelope
+ toConsensus chan interface{}
+ toNode chan interface{}
+ sentAgreementLock sync.Mutex
+ sentAgreement map[common.Hash]struct{}
+ blockCacheLock sync.RWMutex
+ blockCache map[common.Hash]*types.Block
+ voteCacheLock sync.RWMutex
+ voteCache map[types.Position]map[types.VoteHeader]*types.Vote
+ voteCacheSize int
+ votePositions []types.Position
+ stateModule *State
+ peers map[types.NodeID]struct{}
+ unreceivedBlocksLock sync.RWMutex
+ unreceivedBlocks map[common.Hash]chan<- common.Hash
+ cache *utils.NodeSetCache
+ notarySetCachesLock sync.Mutex
+ notarySetCaches map[uint64]map[types.NodeID]struct{}
}
// NewNetwork setup network stuffs for nodes, which provides an
@@ -177,19 +164,15 @@ func NewNetwork(pubKey crypto.PublicKey, config NetworkConfig) (
n *Network) {
// Construct basic network instance.
n = &Network{
- ID: types.NewNodeID(pubKey),
- config: config,
- toConsensus: make(chan interface{}, 1000),
- toNode: make(chan interface{}, 1000),
- sentRandomness: make(map[common.Hash]struct{}),
- sentAgreement: make(map[common.Hash]struct{}),
- blockCache: make(map[common.Hash]*types.Block, maxBlockCache),
- randomnessCache: make(map[common.Hash]*types.BlockRandomnessResult),
- unreceivedBlocks: make(map[common.Hash]chan<- common.Hash),
- unreceivedRandomness: make(map[common.Hash]chan<- common.Hash),
- peers: make(map[types.NodeID]struct{}),
- notarySetCaches: make(map[uint64]map[types.NodeID]struct{}),
- dkgSetCaches: make(map[uint64]map[types.NodeID]struct{}),
+ ID: types.NewNodeID(pubKey),
+ config: config,
+ toConsensus: make(chan interface{}, 1000),
+ toNode: make(chan interface{}, 1000),
+ sentAgreement: make(map[common.Hash]struct{}),
+ blockCache: make(map[common.Hash]*types.Block, maxBlockCache),
+ unreceivedBlocks: make(map[common.Hash]chan<- common.Hash),
+ peers: make(map[types.NodeID]struct{}),
+ notarySetCaches: make(map[uint64]map[types.NodeID]struct{}),
voteCache: make(
map[types.Position]map[types.VoteHeader]*types.Vote),
}
@@ -218,11 +201,6 @@ func (n *Network) PullVotes(pos types.Position) {
go n.pullVotesAsync(pos)
}
-// PullRandomness implememnts core.Network interface.
-func (n *Network) PullRandomness(hashes common.Hashes) {
- go n.pullRandomnessAsync(hashes)
-}
-
// BroadcastVote implements core.Network interface.
func (n *Network) BroadcastVote(vote *types.Vote) {
if err := n.trans.Broadcast(n.getNotarySet(vote.Position.Round),
@@ -254,37 +232,22 @@ func (n *Network) BroadcastAgreementResult(
if !n.markAgreementResultAsSent(result.BlockHash) {
return
}
- // Send to DKG set first.
- dkgSet := n.getDKGSet(result.Position.Round)
- if err := n.trans.Broadcast(
- dkgSet, n.config.DirectLatency, result); err != nil {
- panic(err)
- }
- // Gossip to other nodes.
- if err := n.trans.Broadcast(getComplementSet(n.peers, dkgSet),
- n.config.GossipLatency, result); err != nil {
- panic(err)
- }
-}
-
-// BroadcastRandomnessResult implements core.Network interface.
-func (n *Network) BroadcastRandomnessResult(
- randResult *types.BlockRandomnessResult) {
- if !n.markRandomnessResultAsSent(randResult.BlockHash) {
- return
- }
- // Send to notary set first.
- notarySet := n.getNotarySet(randResult.Position.Round)
- if err := n.trans.Broadcast(
- notarySet, n.config.DirectLatency, randResult); err != nil {
- panic(err)
+ n.addBlockRandomnessToCache(result.BlockHash, result.Randomness)
+ notarySet := n.getNotarySet(result.Position.Round)
+ count := len(notarySet) * gossipAgreementResultPercent / 100
+ for nID := range notarySet {
+ if count--; count < 0 {
+ break
+ }
+ if err := n.trans.Send(nID, result); err != nil {
+ panic(err)
+ }
}
// Gossip to other nodes.
if err := n.trans.Broadcast(getComplementSet(n.peers, notarySet),
- n.config.GossipLatency, randResult); err != nil {
+ n.config.GossipLatency, result); err != nil {
panic(err)
}
- n.addRandomnessToCache(randResult)
}
// SendDKGPrivateShare implements core.Network interface.
@@ -296,7 +259,7 @@ func (n *Network) SendDKGPrivateShare(
// BroadcastDKGPrivateShare implements core.Network interface.
func (n *Network) BroadcastDKGPrivateShare(
prvShare *typesDKG.PrivateShare) {
- if err := n.trans.Broadcast(n.getDKGSet(prvShare.Round),
+ if err := n.trans.Broadcast(n.getNotarySet(prvShare.Round),
n.config.DirectLatency, prvShare); err != nil {
panic(err)
}
@@ -306,7 +269,7 @@ func (n *Network) BroadcastDKGPrivateShare(
func (n *Network) BroadcastDKGPartialSignature(
psig *typesDKG.PartialSignature) {
if err := n.trans.Broadcast(
- n.getDKGSet(psig.Round), n.config.DirectLatency, psig); err != nil {
+ n.getNotarySet(psig.Round), n.config.DirectLatency, psig); err != nil {
panic(err)
}
}
@@ -358,7 +321,7 @@ func (n *Network) dispatchMsg(e *TransportEnvelope) {
// Add this vote to cache.
n.addVoteToCache(v)
n.toConsensus <- v
- case *types.AgreementResult, *types.BlockRandomnessResult,
+ case *types.AgreementResult,
*typesDKG.PrivateShare, *typesDKG.PartialSignature:
n.toConsensus <- v
case packedStateChanges:
@@ -408,25 +371,6 @@ func (n *Network) handlePullRequest(req *PullRequest) {
}
}
}()
- case "randomness":
- hashes := req.Identity.(common.Hashes)
- func() {
- n.randomnessCacheLock.Lock()
- defer n.randomnessCacheLock.Unlock()
- All:
- for _, h := range hashes {
- r, exists := n.randomnessCache[h]
- if !exists {
- continue
- }
- select {
- case <-n.ctx.Done():
- break All
- default:
- }
- n.send(req.Requester, r)
- }
- }()
default:
panic(fmt.Errorf("unknown type of pull request: %v", req.Type))
}
@@ -582,57 +526,6 @@ func (n *Network) pullVotesAsync(pos types.Position) {
}
}
-func (n *Network) pullRandomnessAsync(hashes common.Hashes) {
- // Setup notification channels for each block hash.
- notYetReceived := make(map[common.Hash]struct{})
- ch := make(chan common.Hash, len(hashes))
- func() {
- n.unreceivedRandomnessLock.Lock()
- defer n.unreceivedRandomnessLock.Unlock()
- for _, h := range hashes {
- if _, exists := n.unreceivedRandomness[h]; exists {
- continue
- }
- n.unreceivedRandomness[h] = ch
- notYetReceived[h] = struct{}{}
- }
- }()
- req := &PullRequest{
- Requester: n.ID,
- Type: "randomness",
- Identity: hashes,
- }
- // Randomly pick peers to send pull requests.
-Loop:
- for nID := range n.peers {
- if nID == n.ID {
- continue
- }
- n.send(nID, req)
- select {
- case <-n.ctx.Done():
- break Loop
- case <-time.After(2 * n.config.DirectLatency.Delay()):
- // Consume everything in the notification channel.
- for {
- select {
- case h, ok := <-ch:
- if !ok {
- // This network module is closed.
- break Loop
- }
- delete(notYetReceived, h)
- if len(notYetReceived) == 0 {
- break Loop
- }
- default:
- continue Loop
- }
- }
- }
- }
-}
-
func (n *Network) addBlockToCache(b *types.Block) {
n.blockCacheLock.Lock()
defer n.blockCacheLock.Unlock()
@@ -646,6 +539,16 @@ func (n *Network) addBlockToCache(b *types.Block) {
n.blockCache[b.Hash] = b.Clone()
}
+func (n *Network) addBlockRandomnessToCache(hash common.Hash, rand []byte) {
+ n.blockCacheLock.Lock()
+ defer n.blockCacheLock.Unlock()
+ block, exist := n.blockCache[hash]
+ if !exist {
+ return
+ }
+ block.Finalization.Randomness = rand
+}
+
func (n *Network) addVoteToCache(v *types.Vote) {
n.voteCacheLock.Lock()
defer n.voteCacheLock.Unlock()
@@ -667,19 +570,6 @@ func (n *Network) addVoteToCache(v *types.Vote) {
n.voteCacheSize++
}
-func (n *Network) addRandomnessToCache(rand *types.BlockRandomnessResult) {
- n.randomnessCacheLock.Lock()
- defer n.randomnessCacheLock.Unlock()
- if len(n.randomnessCache) > 1000 {
- // Randomly purge one randomness from cache.
- for k := range n.randomnessCache {
- delete(n.randomnessCache, k)
- break
- }
- }
- n.randomnessCache[rand.BlockHash] = rand
-}
-
func (n *Network) markAgreementResultAsSent(blockHash common.Hash) bool {
n.sentAgreementLock.Lock()
defer n.sentAgreementLock.Unlock()
@@ -697,23 +587,6 @@ func (n *Network) markAgreementResultAsSent(blockHash common.Hash) bool {
return true
}
-func (n *Network) markRandomnessResultAsSent(blockHash common.Hash) bool {
- n.sentRandomnessLock.Lock()
- defer n.sentRandomnessLock.Unlock()
- if _, exist := n.sentRandomness[blockHash]; exist {
- return false
- }
- if len(n.sentRandomness) > 1000 {
- // Randomly drop one entry.
- for k := range n.sentRandomness {
- delete(n.sentRandomness, k)
- break
- }
- }
- n.sentRandomness[blockHash] = struct{}{}
- return true
-}
-
func (n *Network) cloneForFake(v interface{}) interface{} {
if n.config.Type != NetworkTypeFake {
return v
@@ -721,9 +594,9 @@ func (n *Network) cloneForFake(v interface{}) interface{} {
switch val := v.(type) {
case *types.Block:
return val.Clone()
- case *types.BlockRandomnessResult:
+ case *types.AgreementResult:
// Perform deep copy for randomness result.
- return cloneBlockRandomnessResult(val)
+ return cloneAgreementResult(val)
}
return v
}
@@ -749,27 +622,6 @@ func (n *Network) getNotarySet(round uint64) map[types.NodeID]struct{} {
return set
}
-// getDKGSet gets DKG set for that round from cache.
-func (n *Network) getDKGSet(round uint64) map[types.NodeID]struct{} {
- if n.cache == nil {
- // Default behavior is to broadcast to all peers, which makes it easier
- // to be used in simple test cases.
- return n.peers
- }
- n.dkgSetCachesLock.Lock()
- defer n.dkgSetCachesLock.Unlock()
- set, exists := n.dkgSetCaches[round]
- if !exists {
- var err error
- set, err = n.cache.GetDKGSet(round)
- if err != nil {
- panic(err)
- }
- n.dkgSetCaches[round] = set
- }
- return set
-}
-
func (n *Network) send(endpoint types.NodeID, msg interface{}) {
go func() {
time.Sleep(n.config.DirectLatency.Delay())
diff --git a/core/test/network_test.go b/core/test/network_test.go
index 63407d6..993ae70 100644
--- a/core/test/network_test.go
+++ b/core/test/network_test.go
@@ -251,43 +251,31 @@ func (s *NetworkTestSuite) TestBroadcastToSet() {
gov, err := NewGovernance(NewState(
1, pubKeys, time.Second, &common.NullLogger{}, true), 2)
req.NoError(err)
- req.NoError(gov.State().RequestChange(StateChangeDKGSetSize, uint32(1)))
req.NoError(gov.State().RequestChange(StateChangeNotarySetSize, uint32(1)))
gov.NotifyRound(round, gov.Configuration(0).RoundLength)
networks := s.setupNetworks(pubKeys)
cache := utils.NewNodeSetCache(gov)
// Cache required set of nodeIDs.
- dkgSet, err := cache.GetDKGSet(round)
- req.NoError(err)
- req.Len(dkgSet, 1)
notarySet, err := cache.GetNotarySet(round)
req.NoError(err)
req.Len(notarySet, 1)
var (
// Some node don't belong to any set.
- nerd *Network
- dkgNode, notaryNode *Network
+ nerd *Network
+ notaryNode *Network
)
for nID, n := range networks {
- if _, exists := dkgSet[nID]; exists {
- continue
- }
if _, exists := notarySet[nID]; exists {
continue
}
nerd = n
break
}
- for nID := range dkgSet {
- dkgNode = networks[nID]
- break
- }
for nID := range notarySet {
notaryNode = networks[nID]
break
}
req.NotNil(nerd)
- req.NotNil(dkgNode)
req.NotNil(notaryNode)
nerd.AttachNodeSetCache(cache)
// Try broadcasting with datum from round 0, and make sure only node belongs
@@ -296,9 +284,9 @@ func (s *NetworkTestSuite) TestBroadcastToSet() {
Position: types.Position{Round: round}}})
req.IsType(&types.Vote{}, <-notaryNode.ReceiveChan())
nerd.BroadcastDKGPrivateShare(&typesDKG.PrivateShare{Round: round})
- req.IsType(&typesDKG.PrivateShare{}, <-dkgNode.ReceiveChan())
+ req.IsType(&typesDKG.PrivateShare{}, <-notaryNode.ReceiveChan())
nerd.BroadcastDKGPartialSignature(&typesDKG.PartialSignature{Round: round})
- req.IsType(&typesDKG.PartialSignature{}, <-dkgNode.ReceiveChan())
+ req.IsType(&typesDKG.PartialSignature{}, <-notaryNode.ReceiveChan())
nerd.BroadcastBlock(&types.Block{Position: types.Position{Round: round}})
req.IsType(&types.Block{}, <-notaryNode.ReceiveChan())
}
diff --git a/core/test/state-change-request.go b/core/test/state-change-request.go
index b7c7bac..fe55d6e 100644
--- a/core/test/state-change-request.go
+++ b/core/test/state-change-request.go
@@ -47,7 +47,6 @@ const (
StateChangeRoundLength
StateChangeMinBlockInterval
StateChangeNotarySetSize
- StateChangeDKGSetSize
// Node set related.
StateAddNode
)
@@ -76,8 +75,6 @@ func (t StateChangeType) String() string {
return "ChangeMinBlockInterval"
case StateChangeNotarySetSize:
return "ChangeNotarySetSize"
- case StateChangeDKGSetSize:
- return "ChangeDKGSetSize"
case StateAddNode:
return "AddNode"
}
@@ -195,8 +192,6 @@ func (req *StateChangeRequest) String() (ret string) {
ret += fmt.Sprintf("%v", time.Duration(req.Payload.(uint64)))
case StateChangeNotarySetSize:
ret += fmt.Sprintf("%v", req.Payload.(uint32))
- case StateChangeDKGSetSize:
- ret += fmt.Sprintf("%v", req.Payload.(uint32))
case StateAddNode:
ret += fmt.Sprintf(
"%s", types.NewNodeID(req.Payload.(crypto.PublicKey)).String()[:6])
diff --git a/core/test/state-change-request_test.go b/core/test/state-change-request_test.go
index eeba4c4..517a929 100644
--- a/core/test/state-change-request_test.go
+++ b/core/test/state-change-request_test.go
@@ -42,7 +42,7 @@ func (s *StateChangeRequestTestSuite) TestEqual() {
func (s *StateChangeRequestTestSuite) TestClone() {
// The cloned one should be no error when compared with 'Equal' method.
- st00 := NewStateChangeRequest(StateChangeDKGSetSize, uint32(7))
+ st00 := NewStateChangeRequest(StateChangeNotarySetSize, uint32(7))
s.NoError(st00.Equal(st00.Clone()))
st10 := NewStateChangeRequest(
StateAddDKGMasterPublicKey, typesDKG.NewMasterPublicKey())
diff --git a/core/test/state.go b/core/test/state.go
index ce906ae..41c6b38 100644
--- a/core/test/state.go
+++ b/core/test/state.go
@@ -94,7 +94,6 @@ type State struct {
lambdaBA time.Duration
lambdaDKG time.Duration
notarySetSize uint32
- dkgSetSize uint32
roundInterval uint64
minBlockInterval time.Duration
// Nodes
@@ -145,7 +144,6 @@ func NewState(
crs: crs,
nodes: nodes,
notarySetSize: uint32(len(nodes)),
- dkgSetSize: uint32(len(nodes)),
ownRequests: make(map[common.Hash]*StateChangeRequest),
globalRequests: make(map[common.Hash]*StateChangeRequest),
dkgReadys: make(
@@ -183,7 +181,6 @@ func (s *State) Snapshot() (*types.Config, []crypto.PublicKey) {
LambdaBA: s.lambdaBA,
LambdaDKG: s.lambdaDKG,
NotarySetSize: s.notarySetSize,
- DKGSetSize: s.dkgSetSize,
RoundLength: s.roundInterval,
MinBlockInterval: s.minBlockInterval,
}
@@ -238,10 +235,6 @@ func (s *State) unpackPayload(
var tmp uint32
err = rlp.DecodeBytes(raw.Payload, &tmp)
v = tmp
- case StateChangeDKGSetSize:
- var tmp uint32
- err = rlp.DecodeBytes(raw.Payload, &tmp)
- v = tmp
case StateAddNode:
var tmp []byte
err = rlp.DecodeBytes(raw.Payload, &tmp)
@@ -283,7 +276,6 @@ func (s *State) Equal(other *State) error {
configEqual := s.lambdaBA == other.lambdaBA &&
s.lambdaDKG == other.lambdaDKG &&
s.notarySetSize == other.notarySetSize &&
- s.dkgSetSize == other.dkgSetSize &&
s.roundInterval == other.roundInterval &&
s.minBlockInterval == other.minBlockInterval
if !configEqual {
@@ -452,7 +444,6 @@ func (s *State) Clone() (copied *State) {
lambdaBA: s.lambdaBA,
lambdaDKG: s.lambdaDKG,
notarySetSize: s.notarySetSize,
- dkgSetSize: s.dkgSetSize,
roundInterval: s.roundInterval,
minBlockInterval: s.minBlockInterval,
local: s.local,
@@ -774,8 +765,6 @@ func (s *State) applyRequest(req *StateChangeRequest) error {
s.minBlockInterval = time.Duration(req.Payload.(uint64))
case StateChangeNotarySetSize:
s.notarySetSize = req.Payload.(uint32)
- case StateChangeDKGSetSize:
- s.dkgSetSize = req.Payload.(uint32)
default:
return errors.New("you are definitely kidding me")
}
diff --git a/core/test/state_test.go b/core/test/state_test.go
index 0ec90a4..5ad5a3e 100644
--- a/core/test/state_test.go
+++ b/core/test/state_test.go
@@ -147,7 +147,6 @@ func (s *StateTestSuite) makeConfigChanges(st *State) {
st.RequestChange(StateChangeRoundLength, uint64(1001))
st.RequestChange(StateChangeMinBlockInterval, time.Second)
st.RequestChange(StateChangeNotarySetSize, uint32(5))
- st.RequestChange(StateChangeDKGSetSize, uint32(6))
}
func (s *StateTestSuite) checkConfigChanges(config *types.Config) {
@@ -157,7 +156,6 @@ func (s *StateTestSuite) checkConfigChanges(config *types.Config) {
req.Equal(config.RoundLength, uint64(1001))
req.Equal(config.MinBlockInterval, time.Second)
req.Equal(config.NotarySetSize, uint32(5))
- req.Equal(config.DKGSetSize, uint32(6))
}
func (s *StateTestSuite) TestEqual() {
@@ -265,7 +263,6 @@ func (s *StateTestSuite) TestLocalMode() {
req.Equal(config1.LambdaDKG, lambda*10)
req.Equal(config1.RoundLength, uint64(1000))
req.Equal(config1.NotarySetSize, uint32(len(genesisNodes)))
- req.Equal(config1.DKGSetSize, uint32(len(genesisNodes)))
// Request some changes, every fields for config should be affected.
s.makeConfigChanges(st)
// Add new node.
diff --git a/core/test/tcp-transport.go b/core/test/tcp-transport.go
index 19d9bfa..bbc4d56 100644
--- a/core/test/tcp-transport.go
+++ b/core/test/tcp-transport.go
@@ -896,8 +896,6 @@ func (t *TCPTransport) handleThroughputData(msg interface{}, payload []byte) {
recordType = "agreement_result"
case *dkg.PartialSignature:
recordType = "partial_sig"
- case *types.BlockRandomnessResult:
- recordType = "block_random"
}
if len(recordType) > 0 {
t.throughputRecords = append(t.throughputRecords, ThroughputRecord{
diff --git a/core/test/utils.go b/core/test/utils.go
index a2819ae..74cde45 100644
--- a/core/test/utils.go
+++ b/core/test/utils.go
@@ -184,13 +184,13 @@ func CloneDKGPrivateShare(prvShare *typesDKG.PrivateShare) (
return
}
-func cloneBlockRandomnessResult(rand *types.BlockRandomnessResult) (
- copied *types.BlockRandomnessResult) {
- b, err := rlp.EncodeToBytes(rand)
+func cloneAgreementResult(result *types.AgreementResult) (
+ copied *types.AgreementResult) {
+ b, err := rlp.EncodeToBytes(result)
if err != nil {
panic(err)
}
- copied = &types.BlockRandomnessResult{}
+ copied = &types.AgreementResult{}
if err = rlp.DecodeBytes(b, copied); err != nil {
panic(err)
}
diff --git a/core/types/block-randomness.go b/core/types/block-randomness.go
index 74360c7..9a0a65e 100644
--- a/core/types/block-randomness.go
+++ b/core/types/block-randomness.go
@@ -26,27 +26,20 @@ 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"`
+ BlockHash common.Hash `json:"block_hash"`
+ Position Position `json:"position"`
+ // TODO(jimmy): remove Votes
+ Votes []Vote `json:"votes"`
+ IsEmptyBlock bool `json:"is_empty_block"`
+ Randomness []byte `json:"randomness"`
}
func (r *AgreementResult) String() string {
- return fmt.Sprintf("agreementResult{Hash:%s %s}",
- r.BlockHash.String()[:6], r.Position)
-}
-
-// BlockRandomnessResult describes a block randomness result
-type BlockRandomnessResult struct {
- BlockHash common.Hash `json:"block_hash"`
- Position Position `json:"position"`
- Randomness []byte `json:"randomness"`
-}
-
-func (r *BlockRandomnessResult) String() string {
- return fmt.Sprintf("blockRandomness{Block:%s Pos:%s Rand:%s}",
+ if len(r.Randomness) == 0 {
+ return fmt.Sprintf("agreementResult{Block:%s Pos:%s}",
+ r.BlockHash.String()[:6], r.Position)
+ }
+ return fmt.Sprintf("agreementResult{Block:%s Pos:%s Rand:%s}",
r.BlockHash.String()[:6], r.Position,
- hex.EncodeToString(r.Randomness)[:6],
- )
+ hex.EncodeToString(r.Randomness)[:6])
}
diff --git a/core/types/config.go b/core/types/config.go
index eda09f0..dce3836 100644
--- a/core/types/config.go
+++ b/core/types/config.go
@@ -30,7 +30,6 @@ type Config struct {
// Set related.
NotarySetSize uint32
- DKGSetSize uint32
// Time related.
RoundLength uint64
@@ -43,7 +42,6 @@ func (c *Config) Clone() *Config {
LambdaBA: c.LambdaBA,
LambdaDKG: c.LambdaDKG,
NotarySetSize: c.NotarySetSize,
- DKGSetSize: c.DKGSetSize,
RoundLength: c.RoundLength,
MinBlockInterval: c.MinBlockInterval,
}
@@ -60,8 +58,6 @@ func (c *Config) Bytes() []byte {
binaryNotarySetSize := make([]byte, 4)
binary.LittleEndian.PutUint32(binaryNotarySetSize, c.NotarySetSize)
- binaryDKGSetSize := make([]byte, 4)
- binary.LittleEndian.PutUint32(binaryDKGSetSize, c.DKGSetSize)
binaryRoundLength := make([]byte, 8)
binary.LittleEndian.PutUint64(binaryRoundLength, c.RoundLength)
@@ -73,7 +69,6 @@ func (c *Config) Bytes() []byte {
enc = append(enc, binaryLambdaBA...)
enc = append(enc, binaryLambdaDKG...)
enc = append(enc, binaryNotarySetSize...)
- enc = append(enc, binaryDKGSetSize...)
enc = append(enc, binaryRoundLength...)
enc = append(enc, binaryMinBlockInterval...)
return enc
diff --git a/core/types/config_test.go b/core/types/config_test.go
index ac9ef5e..b55004e 100644
--- a/core/types/config_test.go
+++ b/core/types/config_test.go
@@ -33,7 +33,6 @@ func (s *ConfigTestSuite) TestClone() {
LambdaBA: 1 * time.Millisecond,
LambdaDKG: 2 * time.Hour,
NotarySetSize: 5,
- DKGSetSize: 6,
RoundLength: 1000,
MinBlockInterval: 7 * time.Nanosecond,
}
diff --git a/core/types/nodeset.go b/core/types/nodeset.go
index fccfbb6..8060007 100644
--- a/core/types/nodeset.go
+++ b/core/types/nodeset.go
@@ -40,7 +40,6 @@ type subSetTargetType byte
const (
targetNotarySet subSetTargetType = iota
- targetDKGSet
targetNodeLeader
)
@@ -89,11 +88,6 @@ func NewNotarySetTarget(crs common.Hash) *SubSetTarget {
return newTarget(targetNotarySet, crs[:])
}
-// NewDKGSetTarget is the target for getting DKG Set.
-func NewDKGSetTarget(crs common.Hash) *SubSetTarget {
- return newTarget(targetDKGSet, crs[:])
-}
-
// NewNodeLeaderTarget is the target for getting leader of fast BA.
func NewNodeLeaderTarget(crs common.Hash, height uint64) *SubSetTarget {
binaryHeight := make([]byte, 8)
diff --git a/core/types/vote.go b/core/types/vote.go
index c4a625e..8bc0c78 100644
--- a/core/types/vote.go
+++ b/core/types/vote.go
@@ -22,6 +22,7 @@ import (
"github.com/dexon-foundation/dexon-consensus/common"
"github.com/dexon-foundation/dexon-consensus/core/crypto"
+ cryptoDKG "github.com/dexon-foundation/dexon-consensus/core/crypto/dkg"
)
// VoteType is the type of vote.
@@ -61,8 +62,9 @@ type VoteHeader struct {
// Vote is the vote structure defined in Crypto Shuffle Algorithm.
type Vote struct {
- VoteHeader `json:"header"`
- Signature crypto.Signature `json:"signature"`
+ VoteHeader `json:"header"`
+ PartialSignature cryptoDKG.PartialSignature `json:"partial_signature"`
+ Signature crypto.Signature `json:"signature"`
}
func (v *Vote) String() string {
@@ -91,6 +93,8 @@ func (v *Vote) Clone() *Vote {
Period: v.Period,
Position: v.Position,
},
+ PartialSignature: cryptoDKG.PartialSignature(
+ crypto.Signature(v.PartialSignature).Clone()),
Signature: v.Signature.Clone(),
}
}
diff --git a/core/utils/crypto.go b/core/utils/crypto.go
index 8be503f..34bf08f 100644
--- a/core/utils/crypto.go
+++ b/core/utils/crypto.go
@@ -36,7 +36,7 @@ func hashWitness(witness *types.Witness) (common.Hash, error) {
// HashBlock generates hash of a types.Block.
func HashBlock(block *types.Block) (common.Hash, error) {
- hashPosition := hashPosition(block.Position)
+ hashPosition := HashPosition(block.Position)
binaryTimestamp, err := block.Timestamp.UTC().MarshalBinary()
if err != nil {
return common.Hash{}, err
@@ -88,13 +88,14 @@ func HashVote(vote *types.Vote) common.Hash {
binaryPeriod := make([]byte, 8)
binary.LittleEndian.PutUint64(binaryPeriod, vote.Period)
- hashPosition := hashPosition(vote.Position)
+ hashPosition := HashPosition(vote.Position)
hash := crypto.Keccak256Hash(
vote.ProposerID.Hash[:],
vote.BlockHash[:],
binaryPeriod,
hashPosition[:],
+ vote.PartialSignature.Signature[:],
[]byte{byte(vote.Type)},
)
return hash
@@ -114,7 +115,7 @@ func VerifyVoteSignature(vote *types.Vote) (bool, error) {
}
func hashCRS(block *types.Block, crs common.Hash) common.Hash {
- hashPos := hashPosition(block.Position)
+ hashPos := HashPosition(block.Position)
return crypto.Keccak256Hash(crs[:], hashPos[:])
}
@@ -132,7 +133,8 @@ func VerifyCRSSignature(block *types.Block, crs common.Hash) (
return true, nil
}
-func hashPosition(position types.Position) common.Hash {
+// HashPosition generates hash of a types.Position.
+func HashPosition(position types.Position) common.Hash {
binaryRound := make([]byte, 8)
binary.LittleEndian.PutUint64(binaryRound, position.Round)
diff --git a/core/utils/nodeset-cache.go b/core/utils/nodeset-cache.go
index 0090123..89ebd24 100644
--- a/core/utils/nodeset-cache.go
+++ b/core/utils/nodeset-cache.go
@@ -39,7 +39,6 @@ type sets struct {
crs common.Hash
nodeSet *types.NodeSet
notarySet map[types.NodeID]struct{}
- dkgSet map[types.NodeID]struct{}
leaderNode map[uint64]types.NodeID
}
@@ -134,16 +133,6 @@ func (cache *NodeSetCache) GetNotarySet(
return cache.cloneMap(IDs.notarySet), nil
}
-// GetDKGSet returns of DKG set of this round.
-func (cache *NodeSetCache) GetDKGSet(
- round uint64) (map[types.NodeID]struct{}, error) {
- IDs, err := cache.getOrUpdate(round)
- if err != nil {
- return nil, err
- }
- return cache.cloneMap(IDs.dkgSet), nil
-}
-
// GetLeaderNode returns the BA leader of the position.
func (cache *NodeSetCache) GetLeaderNode(pos types.Position) (
types.NodeID, error) {
@@ -254,10 +243,6 @@ func (cache *NodeSetCache) update(round uint64) (nIDs *sets, err error) {
notarySet: make(map[types.NodeID]struct{}),
leaderNode: make(map[uint64]types.NodeID, cfg.RoundLength),
}
- if round >= dkgDelayRound {
- nIDs.dkgSet = nodeSet.GetSubSet(
- int(cfg.DKGSetSize), types.NewDKGSetTarget(crs))
- }
nIDs.notarySet = nodeSet.GetSubSet(
int(cfg.NotarySetSize), types.NewNotarySetTarget(crs))
cache.rounds[round] = nIDs
diff --git a/core/utils/nodeset-cache_test.go b/core/utils/nodeset-cache_test.go
index 45d30a7..0ee3883 100644
--- a/core/utils/nodeset-cache_test.go
+++ b/core/utils/nodeset-cache_test.go
@@ -37,7 +37,6 @@ type nsIntf struct {
func (g *nsIntf) Configuration(round uint64) (cfg *types.Config) {
return &types.Config{
NotarySetSize: 7,
- DKGSetSize: 7,
RoundLength: 60,
LambdaBA: 250 * time.Millisecond,
MinBlockInterval: 1 * time.Second,
@@ -91,9 +90,6 @@ func (s *NodeSetCacheTestSuite) TestBasicUsage() {
notarySet, err := cache.GetNotarySet(0)
req.NoError(err)
chk(cache, 0, notarySet)
- dkgSet, err := cache.GetDKGSet(0)
- req.NoError(err)
- chk(cache, 0, dkgSet)
leaderNode, err := cache.GetLeaderNode(types.Position{
Round: uint64(0),
Height: uint64(10),
diff --git a/core/utils/utils.go b/core/utils/utils.go
index 14687d6..fcdf422 100644
--- a/core/utils/utils.go
+++ b/core/utils/utils.go
@@ -136,7 +136,7 @@ func LaunchDummyReceiver(
// GetDKGThreshold return expected threshold for given DKG set size.
func GetDKGThreshold(config *types.Config) int {
- return int(config.DKGSetSize/3) + 1
+ return int(config.NotarySetSize*2/3) + 1
}
// GetNextRoundValidationHeight returns the block height to check if the next
diff --git a/integration_test/consensus_test.go b/integration_test/consensus_test.go
index 6bdc3dc..2c7f762 100644
--- a/integration_test/consensus_test.go
+++ b/integration_test/consensus_test.go
@@ -20,6 +20,8 @@ package integration
import (
"context"
"fmt"
+ "log"
+ "os"
"sync"
"testing"
"time"
@@ -110,7 +112,7 @@ func (s *ConsensusTestSuite) setupNodes(
// setup nodes.
nodes := make(map[types.NodeID]*node)
wg.Add(len(prvKeys))
- for _, k := range prvKeys {
+ for i, k := range prvKeys {
dbInst, err := db.NewMemBackedDB()
s.Require().NoError(err)
// Prepare essential modules: app, gov, db.
@@ -124,7 +126,11 @@ func (s *ConsensusTestSuite) setupNodes(
gov.SwitchToRemoteMode(networkModule)
gov.NotifyRound(initRound, 0)
networkModule.AttachNodeSetCache(utils.NewNodeSetCache(gov))
- logger := &common.NullLogger{}
+ f, err := os.Create(fmt.Sprintf("log.%d.log", i))
+ if err != nil {
+ panic(err)
+ }
+ logger := common.NewCustomLogger(log.New(f, "", log.LstdFlags|log.Lmicroseconds))
rEvt, err := utils.NewRoundEvent(context.Background(), gov, logger, 0,
0, core.ConfigRoundShift)
s.Require().NoError(err)
@@ -318,32 +324,24 @@ func (s *ConsensusTestSuite) TestSetSizeChange() {
test.StateChangeRoundLength, uint64(100)))
req.NoError(seedGov.State().RequestChange(
test.StateChangeNotarySetSize, uint32(4)))
- req.NoError(seedGov.State().RequestChange(
- test.StateChangeDKGSetSize, uint32(4)))
seedGov.CatchUpWithRound(0)
// Setup configuration for round 0 and round 1.
req.NoError(seedGov.State().RequestChange(
test.StateChangeRoundLength, uint64(100)))
req.NoError(seedGov.State().RequestChange(
test.StateChangeNotarySetSize, uint32(5)))
- req.NoError(seedGov.State().RequestChange(
- test.StateChangeDKGSetSize, uint32(6)))
seedGov.CatchUpWithRound(1)
// Setup configuration for round 2.
req.NoError(seedGov.State().RequestChange(
test.StateChangeRoundLength, uint64(100)))
req.NoError(seedGov.State().RequestChange(
test.StateChangeNotarySetSize, uint32(6)))
- req.NoError(seedGov.State().RequestChange(
- test.StateChangeDKGSetSize, uint32(5)))
seedGov.CatchUpWithRound(2)
// Setup configuration for round 3.
req.NoError(seedGov.State().RequestChange(
test.StateChangeRoundLength, uint64(100)))
req.NoError(seedGov.State().RequestChange(
test.StateChangeNotarySetSize, uint32(4)))
- req.NoError(seedGov.State().RequestChange(
- test.StateChangeDKGSetSize, uint32(4)))
seedGov.CatchUpWithRound(3)
// Setup nodes.
nodes := s.setupNodes(dMoment, prvKeys, seedGov)
@@ -357,8 +355,11 @@ func (s *ConsensusTestSuite) TestSetSizeChange() {
4, test.StateChangeRoundLength, uint64(100)))
req.NoError(pickedNode.gov.RegisterConfigChange(
4, test.StateChangeNotarySetSize, uint32(5)))
+ // Register configuration changes for round 5.
req.NoError(pickedNode.gov.RegisterConfigChange(
- 4, test.StateChangeDKGSetSize, uint32(5)))
+ 5, test.StateChangeRoundLength, uint64(60)))
+ req.NoError(pickedNode.gov.RegisterConfigChange(
+ 5, test.StateChangeNotarySetSize, uint32(4)))
// Run test.
for _, n := range nodes {
go n.con.Run()
@@ -463,6 +464,11 @@ ReachAlive:
// Initiate Syncer.
runnerCtx, runnerCtxCancel := context.WithCancel(context.Background())
defer runnerCtxCancel()
+ f, err := os.Create("log.sync.log")
+ if err != nil {
+ panic(err)
+ }
+ logger := common.NewCustomLogger(log.New(f, "", log.LstdFlags|log.Lmicroseconds))
syncerObj := syncer.NewConsensus(
dMoment,
syncNode.app,
@@ -470,7 +476,7 @@ ReachAlive:
syncNode.db,
syncNode.network,
prvKeys[0],
- &common.NullLogger{},
+ logger,
)
// Initialize communication channel, it's not recommended to assertion in
// another go routine.
@@ -620,7 +626,12 @@ ReachStop:
node.app.ClearUndeliveredBlocks()
}
syncerCon := make(map[types.NodeID]*syncer.Consensus, len(nodes))
- for _, prvKey := range prvKeys {
+ for i, prvKey := range prvKeys {
+ f, err := os.Create(fmt.Sprintf("log.sync.%d.log", i))
+ if err != nil {
+ panic(err)
+ }
+ logger := common.NewCustomLogger(log.New(f, "", log.LstdFlags|log.Lmicroseconds))
nID := types.NewNodeID(prvKey.PublicKey())
node := nodes[nID]
syncerCon[nID] = syncer.NewConsensus(
@@ -630,7 +641,7 @@ ReachStop:
node.db,
node.network,
prvKey,
- &common.NullLogger{},
+ logger,
)
}
targetNode := nodes[latestNodeID]
@@ -711,8 +722,6 @@ func (s *ConsensusTestSuite) TestResetDKG() {
test.StateChangeRoundLength, uint64(100)))
req.NoError(seedGov.State().RequestChange(
test.StateChangeNotarySetSize, uint32(4)))
- req.NoError(seedGov.State().RequestChange(
- test.StateChangeDKGSetSize, uint32(4)))
nodes := s.setupNodes(dMoment, prvKeys, seedGov)
for _, n := range nodes {
n.rEvt.Register(purgeHandlerGen(n.network))
diff --git a/simulation/config/utils.go b/simulation/config/utils.go
index 6e9024a..ade7471 100644
--- a/simulation/config/utils.go
+++ b/simulation/config/utils.go
@@ -37,8 +37,6 @@ func StateChangeTypeFromString(s string) test.StateChangeType {
return test.StateChangeMinBlockInterval
case "notary_set_size":
return test.StateChangeNotarySetSize
- case "dkg_set_size":
- return test.StateChangeDKGSetSize
}
panic(fmt.Errorf("unsupported state change type %s", s))
}
@@ -48,7 +46,7 @@ func StateChangeTypeFromString(s string) test.StateChangeType {
func StateChangeValueFromString(
t test.StateChangeType, v string) interface{} {
switch t {
- case test.StateChangeNotarySetSize, test.StateChangeDKGSetSize:
+ case test.StateChangeNotarySetSize:
ret, err := strconv.ParseUint(v, 10, 32)
if err != nil {
panic(err)
diff --git a/simulation/node.go b/simulation/node.go
index 5bd8ec1..ee2dd89 100644
--- a/simulation/node.go
+++ b/simulation/node.go
@@ -206,7 +206,6 @@ func (n *node) prepareConfigs() {
cConfig := n.cfg.Node.Consensus
n.gov.State().RequestChange(
test.StateChangeNotarySetSize, cConfig.NotarySetSize) // #nosec G104
- n.gov.State().RequestChange(test.StateChangeDKGSetSize, cConfig.DKGSetSize) // #nosec G104
n.gov.State().RequestChange(test.StateChangeLambdaBA, time.Duration(
cConfig.LambdaBA)*time.Millisecond) // #nosec G104
n.gov.State().RequestChange(test.StateChangeLambdaDKG, time.Duration(