diff options
author | Haoping Ku <haoping.ku@dexon.org> | 2018-10-22 18:22:05 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-10-22 18:22:05 +0800 |
commit | 3f8770e5f3338802f7f9839e3ecbcc701e67ed31 (patch) | |
tree | cb00a34f0003d40925ab7afa710ee24e6deed802 | |
parent | 6615245b8098daf39be250698e9ff90e0a72936b (diff) | |
download | dexon-consensus-3f8770e5f3338802f7f9839e3ecbcc701e67ed31.tar dexon-consensus-3f8770e5f3338802f7f9839e3ecbcc701e67ed31.tar.gz dexon-consensus-3f8770e5f3338802f7f9839e3ecbcc701e67ed31.tar.bz2 dexon-consensus-3f8770e5f3338802f7f9839e3ecbcc701e67ed31.tar.lz dexon-consensus-3f8770e5f3338802f7f9839e3ecbcc701e67ed31.tar.xz dexon-consensus-3f8770e5f3338802f7f9839e3ecbcc701e67ed31.tar.zst dexon-consensus-3f8770e5f3338802f7f9839e3ecbcc701e67ed31.zip |
core: total-ordering: add test TestRunFromNonGenesis (#226)
* core: total-ordering: add test TestRunFromNonGenesis
-rw-r--r-- | core/test/blocks-generator.go | 4 | ||||
-rw-r--r-- | core/total-ordering.go | 35 | ||||
-rw-r--r-- | core/total-ordering_test.go | 79 |
3 files changed, 96 insertions, 22 deletions
diff --git a/core/test/blocks-generator.go b/core/test/blocks-generator.go index 0203a19..393e3a3 100644 --- a/core/test/blocks-generator.go +++ b/core/test/blocks-generator.go @@ -297,8 +297,8 @@ func NewBlocksGenerator( if ackingCountGenerator == nil { ackingCountGenerator = normalAckingCountGenerator( config.NumChains, - float64(config.NumChains/2), - float64(config.NumChains/4+1)) + float64(config.NumChains/5), + float64(config.NumChains/7+1)) } timePicker := generateTimePicker( config.MinBlockTimeInterval, config.MaxBlockTimeInterval) diff --git a/core/total-ordering.go b/core/total-ordering.go index a1c190f..ec9e643 100644 --- a/core/total-ordering.go +++ b/core/total-ordering.go @@ -688,13 +688,6 @@ func (global *totalOrderingGlobalVector) addBlock( } } } else { - // Assume we run from round 0 (genesis round). Newly added chains - // would go into this case. Make sure blocks from those chains - // are safe to use. - if curPosition.Height != 0 { - err = ErrNotValidDAG - return - } if curPosition.Round < global.curRound { err = ErrBlockFromPastRound return @@ -829,21 +822,22 @@ type totalOrdering struct { } // newTotalOrdering constructs an totalOrdering instance. -func newTotalOrdering(genesisConfig *totalOrderingConfig) *totalOrdering { - globalVector := newTotalOrderingGlobalVector(genesisConfig.numChains) - objCache := newTotalOrderingObjectCache(genesisConfig.numChains) - candidates := make([]*totalOrderingCandidateInfo, genesisConfig.numChains) +func newTotalOrdering(config *totalOrderingConfig) *totalOrdering { + globalVector := newTotalOrderingGlobalVector(config.numChains) + objCache := newTotalOrderingObjectCache(config.numChains) + candidates := make([]*totalOrderingCandidateInfo, config.numChains) to := &totalOrdering{ pendings: make(map[common.Hash]*types.Block), globalVector: globalVector, - dirtyChainIDs: make([]int, 0, genesisConfig.numChains), + dirtyChainIDs: make([]int, 0, config.numChains), acked: make(map[common.Hash]map[common.Hash]struct{}), objCache: objCache, candidateChainMapping: make(map[uint32]common.Hash), candidates: candidates, - candidateChainIDs: make([]uint32, 0, genesisConfig.numChains), + candidateChainIDs: make([]uint32, 0, config.numChains), + curRound: config.roundID, } - to.configs = []*totalOrderingConfig{genesisConfig} + to.configs = []*totalOrderingConfig{config} return to } @@ -851,7 +845,7 @@ func newTotalOrdering(genesisConfig *totalOrderingConfig) *totalOrdering { // round R, next time you can only add the config for round R+1. func (to *totalOrdering) appendConfig( round uint64, config *types.Config) error { - if round != uint64(len(to.configs)) { + if round != uint64(len(to.configs))+to.configs[0].roundID { return ErrRoundNotIncreasing } to.configs = append( @@ -1056,7 +1050,7 @@ func (to *totalOrdering) generateDeliverSet() ( chainID, otherChainID uint32 info, otherInfo *totalOrderingCandidateInfo precedings = make(map[uint32]struct{}) - cfg = to.configs[to.curRound] + cfg = to.configs[to.curRound-to.configs[0].roundID] ) mode = TotalOrderingModeNormal to.globalVector.updateCandidateInfo(to.dirtyChainIDs, to.objCache) @@ -1200,7 +1194,7 @@ CheckNextCandidateLoop: // flushBlocks flushes blocks. func (to *totalOrdering) flushBlocks( b *types.Block) (flushed []*types.Block, mode uint32, err error) { - cfg := to.configs[to.curRound] + cfg := to.configs[to.curRound-to.configs[0].roundID] mode = TotalOrderingModeFlush if cfg.isValidLastBlock(b) { to.flushReadyChains[b.Position.ChainID] = struct{}{} @@ -1259,7 +1253,8 @@ func (to *totalOrdering) flushBlocks( to.globalVector.cachedCandidateInfo = nil to.switchRound() // Force to pick new candidates. - to.output(map[common.Hash]struct{}{}, to.configs[to.curRound].numChains) + numChains := to.configs[to.curRound-to.configs[0].roundID].numChains + to.output(map[common.Hash]struct{}{}, numChains) return } @@ -1267,7 +1262,7 @@ func (to *totalOrdering) flushBlocks( func (to *totalOrdering) deliverBlocks() ( delivered []*types.Block, mode uint32, err error) { hashes, mode := to.generateDeliverSet() - cfg := to.configs[to.curRound] + cfg := to.configs[to.curRound-to.configs[0].roundID] // output precedings delivered = to.output(hashes, cfg.numChains) // Check if any block in delivered set are the last block in this round @@ -1310,7 +1305,7 @@ func (to *totalOrdering) processBlock( // NOTE: I assume the block 'b' is already safe for total ordering. // That means, all its acking blocks are during/after // total ordering stage. - cfg := to.configs[to.curRound] + cfg := to.configs[to.curRound-to.configs[0].roundID] to.pendings[b.Hash] = b to.buildBlockRelation(b) pos, err := to.updateVectors(b) diff --git a/core/total-ordering_test.go b/core/total-ordering_test.go index 94fc619..315326e 100644 --- a/core/total-ordering_test.go +++ b/core/total-ordering_test.go @@ -1202,6 +1202,85 @@ func (s *TotalOrderingTestSuite) TestRoundChanged() { s.baseTestForRoundChange(repeat, configs) } +func (s *TotalOrderingTestSuite) TestRunFromNonGenesis() { + var ( + req = s.Require() + numChains = uint32(19) + genesisTime = time.Now().UTC() + ) + gen := test.NewBlocksGenerator(&test.BlocksGeneratorConfig{ + NumChains: numChains, + MinBlockTimeInterval: 0, + MaxBlockTimeInterval: 500 * time.Millisecond, + }, nil, hashBlock) + db, err := blockdb.NewMemBackedBlockDB() + req.NoError(err) + err = gen.Generate(0, genesisTime, genesisTime.Add(20*time.Second), db) + req.NoError(err) + iter, err := db.GetAll() + req.NoError(err) + + revealer, err := test.NewRandomDAGRevealer(iter) + req.NoError(err) + + genesisConfig := &totalOrderingConfig{ + roundBasedConfig: roundBasedConfig{ + roundInterval: 1000 * time.Second, + }, + k: 0, + phi: uint64(numChains * 2 / 3), + numChains: numChains, + } + genesisConfig.setRoundBeginTime(genesisTime) + to1 := newTotalOrdering(genesisConfig) + s.Require().NoError(to1.appendConfig(1, &types.Config{ + K: 0, + PhiRatio: 0.5, + NumChains: numChains, + })) + deliveredBlocks1 := [][]*types.Block{} + for { + b, err := revealer.Next() + if err != nil { + if err == blockdb.ErrIterationFinished { + err = nil + break + } + } + s.Require().NoError(err) + bs, _, err := to1.processBlock(&b) + s.Require().Nil(err) + if len(bs) > 0 { + deliveredBlocks1 = append(deliveredBlocks1, bs) + } + } + // Run new total ordering again. + offset := len(deliveredBlocks1) / 2 + to2 := newTotalOrdering(genesisConfig) + s.Require().NoError(to2.appendConfig(1, &types.Config{ + K: 0, + PhiRatio: 0.5, + NumChains: numChains, + })) + deliveredBlocks2 := [][]*types.Block{} + for i := offset; i < len(deliveredBlocks1); i++ { + for _, b := range deliveredBlocks1[i] { + bs, _, err := to2.processBlock(b) + req.NoError(err) + if len(bs) > 0 { + deliveredBlocks2 = append(deliveredBlocks2, bs) + } + } + } + // Check deliver1 and deliver2. + for i := 0; i < len(deliveredBlocks2); i++ { + req.Equal(len(deliveredBlocks1[offset+i]), len(deliveredBlocks2[i])) + for j := 0; j < len(deliveredBlocks2[i]); j++ { + req.Equal(deliveredBlocks1[offset+i][j], deliveredBlocks2[i][j]) + } + } +} + func TestTotalOrdering(t *testing.T) { suite.Run(t, new(TotalOrderingTestSuite)) } |