diff options
author | Mission Liao <mission.liao@dexon.org> | 2018-11-01 14:53:31 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-01 14:53:31 +0800 |
commit | ebfa4a6164dab7db29859538c1aa0e9659bd951a (patch) | |
tree | 317ee8ee45194ec63b4475565bf91cc7862494db /core | |
parent | 56fe2ee9435a89a46c0f3d527580aac43c85dc65 (diff) | |
download | dexon-consensus-ebfa4a6164dab7db29859538c1aa0e9659bd951a.tar dexon-consensus-ebfa4a6164dab7db29859538c1aa0e9659bd951a.tar.gz dexon-consensus-ebfa4a6164dab7db29859538c1aa0e9659bd951a.tar.bz2 dexon-consensus-ebfa4a6164dab7db29859538c1aa0e9659bd951a.tar.lz dexon-consensus-ebfa4a6164dab7db29859538c1aa0e9659bd951a.tar.xz dexon-consensus-ebfa4a6164dab7db29859538c1aa0e9659bd951a.tar.zst dexon-consensus-ebfa4a6164dab7db29859538c1aa0e9659bd951a.zip |
core: core.Lattice supports config change (#276)
Besides making core.Lattice supports config change,
This PR also include the first test for below scenario:
- Configuration changes are registered before test
running
- Those changes are carried/broadcasted as payload
of blocks
- Only one node would initiate these changes, however,
all nodes would finally receive/apply those changes
to their own test.Governance instance.
Diffstat (limited to 'core')
-rw-r--r-- | core/consensus_test.go | 2 | ||||
-rw-r--r-- | core/lattice.go | 4 | ||||
-rw-r--r-- | core/lattice_test.go | 4 | ||||
-rw-r--r-- | core/test/app.go | 50 | ||||
-rw-r--r-- | core/test/app_test.go | 20 | ||||
-rw-r--r-- | core/test/stopper_test.go | 4 |
6 files changed, 54 insertions, 30 deletions
diff --git a/core/consensus_test.go b/core/consensus_test.go index 1ba9fa0..40fad9b 100644 --- a/core/consensus_test.go +++ b/core/consensus_test.go @@ -178,7 +178,7 @@ func (s *ConsensusTestSuite) prepareConsensus( conn *networkConnection) ( *test.App, *Consensus) { - app := test.NewApp() + app := test.NewApp(nil) db, err := blockdb.NewMemBackedBlockDB() s.Require().NoError(err) nID := types.NewNodeID(prvKey.PublicKey()) diff --git a/core/lattice.go b/core/lattice.go index 68b05c2..c1339be 100644 --- a/core/lattice.go +++ b/core/lattice.go @@ -36,7 +36,6 @@ var ( type Lattice struct { lock sync.RWMutex authModule *Authenticator - chainNum uint32 app Application debug Debug pool blockPool @@ -61,7 +60,6 @@ func NewLattice( toConfig := newGenesisTotalOrderingConfig(dMoment, cfg) s = &Lattice{ authModule: authModule, - chainNum: cfg.NumChains, app: app, debug: debug, pool: newBlockPool(cfg.NumChains), @@ -180,7 +178,7 @@ func (s *Lattice) addBlockToLattice( // Replay tips in pool to check their validity. for { hasOutput := false - for i := uint32(0); i < s.chainNum; i++ { + for i := uint32(0); i < uint32(len(s.pool)); i++ { var tip *types.Block if tip = s.pool.tip(i); tip == nil { continue diff --git a/core/lattice_test.go b/core/lattice_test.go index ec40d05..bace8a2 100644 --- a/core/lattice_test.go +++ b/core/lattice_test.go @@ -101,13 +101,13 @@ func (s *LatticeTestSuite) newTestLatticeMgr( // Setup blockdb. db, err := blockdb.NewMemBackedBlockDB() req.NoError(err) - // Setup application. - app := test.NewApp() // Setup governance. _, pubKeys, err := test.NewKeys(int(cfg.NotarySetSize)) req.NoError(err) gov, err := test.NewGovernance(pubKeys, cfg.LambdaBA) req.NoError(err) + // Setup application. + app := test.NewApp(gov.State()) // Setup compaction chain. cc := newCompactionChain(gov) cc.init(&types.Block{}) diff --git a/core/test/app.go b/core/test/app.go index 546c9e5..4976ae0 100644 --- a/core/test/app.go +++ b/core/test/app.go @@ -88,22 +88,30 @@ type App struct { Delivered map[common.Hash]*AppDeliveredRecord DeliverSequence common.Hashes deliveredLock sync.RWMutex + blocks map[common.Hash]*types.Block + blocksLock sync.Mutex + state *State } // NewApp constructs a TestApp instance. -func NewApp() *App { +func NewApp(state *State) *App { return &App{ Acked: make(map[common.Hash]*AppAckedRecord), TotalOrdered: []*AppTotalOrderRecord{}, TotalOrderedByHash: make(map[common.Hash]*AppTotalOrderRecord), Delivered: make(map[common.Hash]*AppDeliveredRecord), DeliverSequence: common.Hashes{}, + blocks: make(map[common.Hash]*types.Block), + state: state, } } // PreparePayload implements Application interface. func (app *App) PreparePayload(position types.Position) ([]byte, error) { - return []byte{}, nil + if app.state == nil { + return []byte{}, nil + } + return app.state.PackRequests() } // PrepareWitness implements Application interface. @@ -119,7 +127,10 @@ func (app *App) VerifyBlock(block *types.Block) types.BlockVerifyStatus { } // BlockConfirmed implements Application interface. -func (app *App) BlockConfirmed(_ types.Block) { +func (app *App) BlockConfirmed(b types.Block) { + app.blocksLock.Lock() + defer app.blocksLock.Unlock() + app.blocks[b.Hash] = &b } // StronglyAcked implements Application interface. @@ -152,15 +163,30 @@ func (app *App) TotalOrderingDelivered(blockHashes common.Hashes, mode uint32) { // BlockDelivered implements Application interface. func (app *App) BlockDelivered( blockHash common.Hash, result types.FinalizationResult) { - app.deliveredLock.Lock() - defer app.deliveredLock.Unlock() - - app.Delivered[blockHash] = &AppDeliveredRecord{ - ConsensusTime: result.Timestamp, - ConsensusHeight: result.Height, - When: time.Now().UTC(), - } - app.DeliverSequence = append(app.DeliverSequence, blockHash) + func() { + app.deliveredLock.Lock() + defer app.deliveredLock.Unlock() + app.Delivered[blockHash] = &AppDeliveredRecord{ + ConsensusTime: result.Timestamp, + ConsensusHeight: result.Height, + When: time.Now().UTC(), + } + app.DeliverSequence = append(app.DeliverSequence, blockHash) + }() + // Apply packed state change requests in payload. + func() { + if app.state == nil { + return + } + app.blocksLock.Lock() + defer app.blocksLock.Unlock() + b := app.blocks[blockHash] + if err := app.state.Apply(b.Payload); err != nil { + if err != ErrDuplicatedChange { + panic(err) + } + } + }() } // Compare performs these checks against another App instance diff --git a/core/test/app_test.go b/core/test/app_test.go index 823bde0..933343f 100644 --- a/core/test/app_test.go +++ b/core/test/app_test.go @@ -91,12 +91,12 @@ func (s *AppTestSuite) deliverBlock( func (s *AppTestSuite) TestCompare() { req := s.Require() - app1 := NewApp() + app1 := NewApp(nil) s.setupAppByTotalOrderDeliver(app1, s.to1) s.setupAppByTotalOrderDeliver(app1, s.to2) s.setupAppByTotalOrderDeliver(app1, s.to3) // An App with different deliver sequence. - app2 := NewApp() + app2 := NewApp(nil) s.setupAppByTotalOrderDeliver(app2, s.to1) s.setupAppByTotalOrderDeliver(app2, s.to2) hash := common.NewRandomHash() @@ -105,7 +105,7 @@ func (s *AppTestSuite) TestCompare() { s.deliverBlockWithTimeFromSequenceLength(app2, hash) req.Equal(ErrMismatchBlockHashSequence, app1.Compare(app2)) // An App with different consensus time for the same block. - app3 := NewApp() + app3 := NewApp(nil) s.setupAppByTotalOrderDeliver(app3, s.to1) s.setupAppByTotalOrderDeliver(app3, s.to2) for _, h := range s.to3.BlockHashes { @@ -120,7 +120,7 @@ func (s *AppTestSuite) TestCompare() { req.Equal(ErrMismatchConsensusTime, app1.Compare(app3)) req.Equal(ErrMismatchConsensusTime, app3.Compare(app1)) // An App without any delivered blocks. - app4 := NewApp() + app4 := NewApp(nil) req.Equal(ErrEmptyDeliverSequence, app4.Compare(app1)) req.Equal(ErrEmptyDeliverSequence, app1.Compare(app4)) } @@ -129,7 +129,7 @@ func (s *AppTestSuite) TestVerify() { req := s.Require() // An OK App instance. - app1 := NewApp() + app1 := NewApp(nil) s.setupAppByTotalOrderDeliver(app1, s.to1) s.setupAppByTotalOrderDeliver(app1, s.to2) s.setupAppByTotalOrderDeliver(app1, s.to3) @@ -139,7 +139,7 @@ func (s *AppTestSuite) TestVerify() { uint64(len(app1.DeliverSequence))) req.Equal(ErrDeliveredBlockNotAcked, app1.Verify()) // The consensus time is out of order. - app2 := NewApp() + app2 := NewApp(nil) s.setupAppByTotalOrderDeliver(app2, s.to1) for _, h := range s.to2.BlockHashes { app2.StronglyAcked(h) @@ -149,14 +149,14 @@ func (s *AppTestSuite) TestVerify() { uint64(len(app2.DeliverSequence)+1)) req.Equal(ErrConsensusTimestampOutOfOrder, app2.Verify()) // A delivered block is not found in total ordering delivers. - app3 := NewApp() + app3 := NewApp(nil) s.setupAppByTotalOrderDeliver(app3, s.to1) hash := common.NewRandomHash() app3.StronglyAcked(hash) s.deliverBlockWithTimeFromSequenceLength(app3, hash) req.Equal(ErrMismatchTotalOrderingAndDelivered, app3.Verify()) // A delivered block is not found in total ordering delivers. - app4 := NewApp() + app4 := NewApp(nil) s.setupAppByTotalOrderDeliver(app4, s.to1) for _, h := range s.to2.BlockHashes { app4.StronglyAcked(h) @@ -167,10 +167,10 @@ func (s *AppTestSuite) TestVerify() { app4.TotalOrderingDelivered(common.Hashes{hash}, core.TotalOrderingModeNormal) s.deliverBlockWithTimeFromSequenceLength(app4, hash) // Witness ack on unknown block. - app5 := NewApp() + app5 := NewApp(nil) s.setupAppByTotalOrderDeliver(app5, s.to1) // The conensus height is out of order. - app6 := NewApp() + app6 := NewApp(nil) s.setupAppByTotalOrderDeliver(app6, s.to1) for _, h := range s.to2.BlockHashes { app6.StronglyAcked(h) diff --git a/core/test/stopper_test.go b/core/test/stopper_test.go index 23c0137..f54c2d1 100644 --- a/core/test/stopper_test.go +++ b/core/test/stopper_test.go @@ -70,7 +70,7 @@ func (s *StopperTestSuite) TestStopByConfirmedBlocks() { nodes = GenerateRandomNodeIDs(2) ) for _, nID := range nodes { - apps[nID] = NewApp() + apps[nID] = NewApp(nil) db, err := blockdb.NewMemBackedBlockDB() req.NoError(err) dbs[nID] = db @@ -118,7 +118,7 @@ func (s *StopperTestSuite) TestStopByRound() { nodes = GenerateRandomNodeIDs(2) ) for _, nID := range nodes { - apps[nID] = NewApp() + apps[nID] = NewApp(nil) db, err := blockdb.NewMemBackedBlockDB() req.NoError(err) dbs[nID] = db |