diff options
author | Mission Liao <mission.liao@dexon.org> | 2018-09-21 10:43:01 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-09-21 10:43:01 +0800 |
commit | 2afaae9935576049d6967ee8aca02e33ac14b229 (patch) | |
tree | 096ddb41ac69c0f5ea911d9eb9db1f2eee81c97c | |
parent | 441e7c082608f274a920eff64bc83ab27ab52ccb (diff) | |
download | dexon-consensus-2afaae9935576049d6967ee8aca02e33ac14b229.tar dexon-consensus-2afaae9935576049d6967ee8aca02e33ac14b229.tar.gz dexon-consensus-2afaae9935576049d6967ee8aca02e33ac14b229.tar.bz2 dexon-consensus-2afaae9935576049d6967ee8aca02e33ac14b229.tar.lz dexon-consensus-2afaae9935576049d6967ee8aca02e33ac14b229.tar.xz dexon-consensus-2afaae9935576049d6967ee8aca02e33ac14b229.tar.zst dexon-consensus-2afaae9935576049d6967ee8aca02e33ac14b229.zip |
test: fix block generator (#126)
* Generate correct hash/signature when generating blocks.
* Refine naming, types.
- type of chainNum should be uint32 by default
- rename blockCount to blockNum
- rename nodeCount to chainNum
-rw-r--r-- | core/blocklattice_test.go | 4 | ||||
-rw-r--r-- | core/reliable-broadcast_test.go | 10 | ||||
-rw-r--r-- | core/test/blocks-generator.go | 58 | ||||
-rw-r--r-- | core/test/blocks-generator_test.go | 43 | ||||
-rw-r--r-- | core/test/revealer_test.go | 11 | ||||
-rw-r--r-- | core/total-ordering_test.go | 49 |
6 files changed, 99 insertions, 76 deletions
diff --git a/core/blocklattice_test.go b/core/blocklattice_test.go index e0c9fb0..76e5129 100644 --- a/core/blocklattice_test.go +++ b/core/blocklattice_test.go @@ -400,7 +400,7 @@ func (s *BlockLatticeTest) TestRandomIntensiveAcking() { func (s *BlockLatticeTest) TestRandomlyGeneratedBlocks() { var ( chainNum uint32 = 19 - blockCount = 50 + blockNum = 50 repeat = 20 delivered []*types.Block err error @@ -412,7 +412,7 @@ func (s *BlockLatticeTest) TestRandomlyGeneratedBlocks() { db, err := blockdb.NewMemBackedBlockDB() req.Nil(err) gen := test.NewBlocksGenerator(nil, hashBlock) - _, err = gen.Generate(int(chainNum), blockCount, nil, db) + _, err = gen.Generate(chainNum, blockNum, nil, db) req.Nil(err) iter, err := db.GetAll() req.Nil(err) diff --git a/core/reliable-broadcast_test.go b/core/reliable-broadcast_test.go index cf82949..0e627d1 100644 --- a/core/reliable-broadcast_test.go +++ b/core/reliable-broadcast_test.go @@ -545,9 +545,9 @@ func (s *ReliableBroadcastTest) TestRandomIntensiveAcking() { func (s *ReliableBroadcastTest) TestRandomlyGeneratedBlocks() { var ( - nodeCount = 19 - blockCount = 50 - repeat = 20 + chainNum = uint32(19) + blockNum = 50 + repeat = 20 ) // Prepare a randomly generated blocks. @@ -560,7 +560,7 @@ func (s *ReliableBroadcastTest) TestRandomlyGeneratedBlocks() { } }() gen := test.NewBlocksGenerator(nil, hashBlock) - _, err = gen.Generate(nodeCount, blockCount, nil, db) + _, err = gen.Generate(chainNum, blockNum, nil, db) s.Require().Nil(err) iter, err := db.GetAll() s.Require().Nil(err) @@ -572,7 +572,7 @@ func (s *ReliableBroadcastTest) TestRandomlyGeneratedBlocks() { for i := 0; i < repeat; i++ { nodes := map[types.NodeID]struct{}{} rb := newReliableBroadcast() - rb.setChainNum(uint32(nodeCount)) + rb.setChainNum(chainNum) stronglyAckedHashes := common.Hashes{} revealer.Reset() diff --git a/core/test/blocks-generator.go b/core/test/blocks-generator.go index 759e3a6..4038450 100644 --- a/core/test/blocks-generator.go +++ b/core/test/blocks-generator.go @@ -26,6 +26,8 @@ import ( "github.com/dexon-foundation/dexon-consensus-core/common" "github.com/dexon-foundation/dexon-consensus-core/core/blockdb" "github.com/dexon-foundation/dexon-consensus-core/core/types" + "github.com/dexon-foundation/dexon-consensus-core/crypto" + "github.com/dexon-foundation/dexon-consensus-core/crypto/eth" ) // TODO(mission): blocks generator should generate blocks based on chain, @@ -81,7 +83,9 @@ type nodeSetStatus struct { hashBlock hashBlockFn } -func newNodeSetStatus(nIDs []types.NodeID, hashBlock hashBlockFn) *nodeSetStatus { +func newNodeSetStatus( + nIDs []types.NodeID, hashBlock hashBlockFn) *nodeSetStatus { + status := make(map[types.NodeID]*nodeStatus) timestamps := make([]time.Time, 0, len(nIDs)) proposerChain := make(map[types.NodeID]uint32) @@ -106,10 +110,10 @@ func newNodeSetStatus(nIDs []types.NodeID, hashBlock hashBlockFn) *nodeSetStatus // findIncompleteNodes is a helper to check which node // doesn't generate enough blocks. func (vs *nodeSetStatus) findIncompleteNodes( - blockCount int) (nIDs []types.NodeID) { + blockNum int) (nIDs []types.NodeID) { for nID, status := range vs.status { - if len(status.blocks) < blockCount { + if len(status.blocks) < blockNum { nIDs = append(nIDs, nID) } } @@ -154,6 +158,7 @@ func (vs *nodeSetStatus) prepareAcksForNewBlock( // proposeBlock propose new block and update node status. func (vs *nodeSetStatus) proposeBlock( proposerID types.NodeID, + prvKey crypto.PrivateKey, acks common.Hashes) (*types.Block, error) { status := vs.status[proposerID] @@ -184,6 +189,10 @@ func (vs *nodeSetStatus) proposeBlock( if err != nil { return nil, err } + newBlock.Signature, err = prvKey.Sign(newBlock.Hash) + if err != nil { + return nil, err + } status.blocks = append(status.blocks, newBlock) return newBlock, nil } @@ -191,13 +200,13 @@ func (vs *nodeSetStatus) proposeBlock( // normalAckingCountGenerator would randomly pick acking count // by a normal distribution. func normalAckingCountGenerator( - nodeCount int, mean, deviation float64) func() int { + chainNum uint32, mean, deviation float64) func() int { return func() int { var expected float64 for { expected = rand.NormFloat64()*deviation + mean - if expected >= 0 && expected <= float64(nodeCount) { + if expected >= 0 && expected <= float64(chainNum) { break } } @@ -207,8 +216,8 @@ func normalAckingCountGenerator( // MaxAckingCountGenerator return generator which returns // fixed maximum acking count. -func MaxAckingCountGenerator(count int) func() int { - return func() int { return count } +func MaxAckingCountGenerator(count uint32) func() int { + return func() int { return int(count) } } // generateNodePicker is a function generator, which would generate @@ -249,22 +258,30 @@ func NewBlocksGenerator(nodePicker func( // The default ackingCountGenerator would randomly pick a number based on // the nodeCount you provided with a normal distribution. func (gen *BlocksGenerator) Generate( - nodeCount int, - blockCount int, + chainNum uint32, + blockNum int, ackingCountGenerator func() int, writer blockdb.Writer) ( - nodes types.NodeIDs, err error) { + nodePrvKeys map[types.NodeID]crypto.PrivateKey, err error) { + var ( + prvKey crypto.PrivateKey + nodes = types.NodeIDs{} + ) if ackingCountGenerator == nil { ackingCountGenerator = normalAckingCountGenerator( - nodeCount, - float64(nodeCount/2), - float64(nodeCount/4+1)) + chainNum, + float64(chainNum/2), + float64(chainNum/4+1)) } - nodes = types.NodeIDs{} - for i := 0; i < nodeCount; i++ { - nodes = append( - nodes, types.NodeID{Hash: common.NewRandomHash()}) + nodePrvKeys = map[types.NodeID]crypto.PrivateKey{} + for i := uint32(0); i < chainNum; i++ { + if prvKey, err = eth.NewPrivateKey(); err != nil { + return + } + id := types.NewNodeID(prvKey.PublicKey()) + nodes = append(nodes, id) + nodePrvKeys[id] = prvKey } status := newNodeSetStatus(nodes, gen.hashBlock) @@ -278,7 +295,7 @@ func (gen *BlocksGenerator) Generate( for { // Find nodes that doesn't propose enough blocks and // pick one from them randomly. - notYet := status.findIncompleteNodes(blockCount) + notYet := status.findIncompleteNodes(blockNum) if len(notYet) == 0 { break } @@ -294,8 +311,9 @@ func (gen *BlocksGenerator) Generate( return } var newBlock *types.Block - newBlock, err = status.proposeBlock(proposerID, acks) - if err != nil { + if newBlock, err = status.proposeBlock( + proposerID, nodePrvKeys[proposerID], acks); err != nil { + return } diff --git a/core/test/blocks-generator_test.go b/core/test/blocks-generator_test.go index f8aa325..1baa9c5 100644 --- a/core/test/blocks-generator_test.go +++ b/core/test/blocks-generator_test.go @@ -33,16 +33,17 @@ type BlocksGeneratorTestCase struct { func (s *BlocksGeneratorTestCase) TestGenerate() { // This test case is to make sure the generated blocks are legimate. - nodeCount := 19 - blockCount := 50 + var ( + chainNum = uint32(19) + blockNum = 50 + ) gen := NewBlocksGenerator(nil, stableRandomHash) db, err := blockdb.NewMemBackedBlockDB() s.Require().Nil(err) - nodes, err := gen.Generate( - nodeCount, blockCount, nil, db) + keys, err := gen.Generate(chainNum, blockNum, nil, db) s.Require().Nil(err) - s.Require().Len(nodes, nodeCount) + s.Require().Len(keys, int(chainNum)) // Load all blocks in that database for further checking. iter, err := db.GetAll() @@ -56,6 +57,11 @@ func (s *BlocksGeneratorTestCase) TestGenerate() { } s.Nil(err) + // TODO(mission): Make sure each block is correctly signed once + // we have a way to access core.hashBlock. + s.Require().NotEqual(block.Hash, common.Hash{}) + s.Require().NotEmpty(block.Signature) + blocksByNode[block.ProposerID] = append(blocksByNode[block.ProposerID], &block) sort.Sort(types.ByHeight(blocksByNode[block.ProposerID])) @@ -106,19 +112,21 @@ func (s *BlocksGeneratorTestCase) TestGenerate() { func (s *BlocksGeneratorTestCase) TestGenerateWithMaxAckCount() { var ( - nodeCount = 13 - blockCount = 50 - gen = NewBlocksGenerator(nil, stableRandomHash) - req = s.Require() + chainNum = uint32(13) + blockNum = 50 + gen = NewBlocksGenerator(nil, stableRandomHash) + req = s.Require() + totalAckingCount = 0 + totalBlockCount = 0 ) // Generate with 0 acks. db, err := blockdb.NewMemBackedBlockDB() req.Nil(err) - nodes, err := gen.Generate( - nodeCount, blockCount, MaxAckingCountGenerator(0), db) + keys, err := gen.Generate( + chainNum, blockNum, MaxAckingCountGenerator(0), db) req.Nil(err) - req.Len(nodes, nodeCount) + req.Len(keys, int(chainNum)) // Load blocks to check their acking count. iter, err := db.GetAll() req.Nil(err) @@ -137,14 +145,11 @@ func (s *BlocksGeneratorTestCase) TestGenerateWithMaxAckCount() { // Generate with acks as many as possible. db, err = blockdb.NewMemBackedBlockDB() req.Nil(err) - nodes, err = gen.Generate( - nodeCount, blockCount, MaxAckingCountGenerator( - nodeCount), db) + keys, err = gen.Generate( + chainNum, blockNum, MaxAckingCountGenerator(chainNum), db) req.Nil(err) - req.Len(nodes, nodeCount) + req.Len(keys, int(chainNum)) // Load blocks to verify the average acking count. - totalAckingCount := 0 - totalBlockCount := 0 iter, err = db.GetAll() req.Nil(err) for { @@ -160,7 +165,7 @@ func (s *BlocksGeneratorTestCase) TestGenerateWithMaxAckCount() { totalBlockCount++ } req.NotZero(totalBlockCount) - req.True((totalAckingCount / totalBlockCount) >= (nodeCount / 2)) + req.True((totalAckingCount / totalBlockCount) >= int(chainNum/2)) } func TestBlocksGenerator(t *testing.T) { diff --git a/core/test/revealer_test.go b/core/test/revealer_test.go index 0c20520..859438c 100644 --- a/core/test/revealer_test.go +++ b/core/test/revealer_test.go @@ -35,9 +35,9 @@ type RevealerTestSuite struct { func (s *RevealerTestSuite) SetupSuite() { var ( - err error - nodeCount = 19 - blockCount = 50 + err error + chainNum = uint32(19) + blockNum = 50 ) // Setup block database. s.db, err = blockdb.NewMemBackedBlockDB() @@ -45,10 +45,9 @@ func (s *RevealerTestSuite) SetupSuite() { // Randomly generate blocks. gen := NewBlocksGenerator(nil, stableRandomHash) - nodes, err := gen.Generate( - nodeCount, blockCount, nil, s.db) + nodes, err := gen.Generate(chainNum, blockNum, nil, s.db) s.Require().Nil(err) - s.Require().Len(nodes, nodeCount) + s.Require().Len(nodes, int(chainNum)) // Cache the count of total generated block. iter, err := s.db.GetAll() diff --git a/core/total-ordering_test.go b/core/total-ordering_test.go index c9dd5a5..478697b 100644 --- a/core/total-ordering_test.go +++ b/core/total-ordering_test.go @@ -864,8 +864,9 @@ func (s *TotalOrderingTestSuite) TestBasicCaseForK0() { } func (s *TotalOrderingTestSuite) baseTestRandomlyGeneratedBlocks( - totalOrderingConstructor func(types.NodeIDs) *totalOrdering, - nodeCount, blockCount int, + totalOrderingConstructor func(chainNum uint32) *totalOrdering, + chainNum uint32, + blockNum int, ackingCountGenerator func() int, repeat int) { @@ -878,10 +879,10 @@ func (s *TotalOrderingTestSuite) baseTestRandomlyGeneratedBlocks( db, err := blockdb.NewMemBackedBlockDB() req.Nil(err) - nodes, err := gen.Generate( - nodeCount, blockCount, ackingCountGenerator, db) + nodePrvKeys, err := gen.Generate( + chainNum, blockNum, ackingCountGenerator, db) req.Nil(err) - req.Len(nodes, nodeCount) + req.Len(nodePrvKeys, int(chainNum)) iter, err := db.GetAll() req.Nil(err) // Setup a revealer that would reveal blocks forming @@ -894,7 +895,7 @@ func (s *TotalOrderingTestSuite) baseTestRandomlyGeneratedBlocks( revealed := "" ordered := "" revealer.Reset() - to := totalOrderingConstructor(nodes) + to := totalOrderingConstructor(chainNum) for { // Reveal next block. b, err := revealer.Next() @@ -937,44 +938,44 @@ func (s *TotalOrderingTestSuite) baseTestRandomlyGeneratedBlocks( func (s *TotalOrderingTestSuite) TestRandomlyGeneratedBlocks() { var ( - nodeCount = 13 - blockCount = 50 - phi uint64 = 10 - repeat = 8 + chainNum = uint32(13) + blockNum = 50 + phi uint64 = 10 + repeat = 8 ) ackingCountGenerators := []func() int{ nil, // Acking frequency with normal distribution. - test.MaxAckingCountGenerator(0), // Low acking frequency. - test.MaxAckingCountGenerator(nodeCount), // High acking frequency. + test.MaxAckingCountGenerator(0), // Low acking frequency. + test.MaxAckingCountGenerator(chainNum), // High acking frequency. } // Test based on different acking frequency. for _, gen := range ackingCountGenerators { // Test for K=0. - constructor := func(nodes types.NodeIDs) *totalOrdering { - return newTotalOrdering(0, phi, uint32(len(nodes))) + constructor := func(chainNum uint32) *totalOrdering { + return newTotalOrdering(0, phi, chainNum) } s.baseTestRandomlyGeneratedBlocks( - constructor, nodeCount, blockCount, gen, repeat) + constructor, chainNum, blockNum, gen, repeat) // Test for K=1, - constructor = func(nodes types.NodeIDs) *totalOrdering { - return newTotalOrdering(1, phi, uint32(len(nodes))) + constructor = func(chainNum uint32) *totalOrdering { + return newTotalOrdering(1, phi, chainNum) } s.baseTestRandomlyGeneratedBlocks( - constructor, nodeCount, blockCount, gen, repeat) + constructor, chainNum, blockNum, gen, repeat) // Test for K=2, - constructor = func(nodes types.NodeIDs) *totalOrdering { - return newTotalOrdering(2, phi, uint32(len(nodes))) + constructor = func(chainNum uint32) *totalOrdering { + return newTotalOrdering(2, phi, chainNum) } s.baseTestRandomlyGeneratedBlocks( - constructor, nodeCount, blockCount, gen, repeat) + constructor, chainNum, blockNum, gen, repeat) // Test for K=3, - constructor = func(nodes types.NodeIDs) *totalOrdering { - return newTotalOrdering(3, phi, uint32(len(nodes))) + constructor = func(chainNum uint32) *totalOrdering { + return newTotalOrdering(3, phi, chainNum) } s.baseTestRandomlyGeneratedBlocks( - constructor, nodeCount, blockCount, gen, repeat) + constructor, chainNum, blockNum, gen, repeat) } } |