aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHaoping Ku <haoping.ku@dexon.org>2018-10-22 18:22:05 +0800
committerGitHub <noreply@github.com>2018-10-22 18:22:05 +0800
commit3f8770e5f3338802f7f9839e3ecbcc701e67ed31 (patch)
treecb00a34f0003d40925ab7afa710ee24e6deed802
parent6615245b8098daf39be250698e9ff90e0a72936b (diff)
downloadtangerine-consensus-3f8770e5f3338802f7f9839e3ecbcc701e67ed31.tar
tangerine-consensus-3f8770e5f3338802f7f9839e3ecbcc701e67ed31.tar.gz
tangerine-consensus-3f8770e5f3338802f7f9839e3ecbcc701e67ed31.tar.bz2
tangerine-consensus-3f8770e5f3338802f7f9839e3ecbcc701e67ed31.tar.lz
tangerine-consensus-3f8770e5f3338802f7f9839e3ecbcc701e67ed31.tar.xz
tangerine-consensus-3f8770e5f3338802f7f9839e3ecbcc701e67ed31.tar.zst
tangerine-consensus-3f8770e5f3338802f7f9839e3ecbcc701e67ed31.zip
core: total-ordering: add test TestRunFromNonGenesis (#226)
* core: total-ordering: add test TestRunFromNonGenesis
-rw-r--r--core/test/blocks-generator.go4
-rw-r--r--core/total-ordering.go35
-rw-r--r--core/total-ordering_test.go79
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))
}