diff options
author | haoping-ku <haoping.ku@dexon.org> | 2018-11-29 14:30:02 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-29 14:30:02 +0800 |
commit | daf3bab93c323b173345811adc9a334dad4a7094 (patch) | |
tree | 8a3957ec1f77262ce92c56f0384b0dedc307628c /core/test | |
parent | 8470ac070f097b261fddc42991a4d2e9ec998db6 (diff) | |
download | dexon-consensus-daf3bab93c323b173345811adc9a334dad4a7094.tar dexon-consensus-daf3bab93c323b173345811adc9a334dad4a7094.tar.gz dexon-consensus-daf3bab93c323b173345811adc9a334dad4a7094.tar.bz2 dexon-consensus-daf3bab93c323b173345811adc9a334dad4a7094.tar.lz dexon-consensus-daf3bab93c323b173345811adc9a334dad4a7094.tar.xz dexon-consensus-daf3bab93c323b173345811adc9a334dad4a7094.tar.zst dexon-consensus-daf3bab93c323b173345811adc9a334dad4a7094.zip |
core: syncer: add syncer (#346)
Diffstat (limited to 'core/test')
-rw-r--r-- | core/test/app.go | 6 | ||||
-rw-r--r-- | core/test/fake-transport.go | 17 | ||||
-rw-r--r-- | core/test/interface.go | 17 | ||||
-rw-r--r-- | core/test/network.go | 5 | ||||
-rw-r--r-- | core/test/revealer.go | 83 | ||||
-rw-r--r-- | core/test/revealer_test.go | 60 | ||||
-rw-r--r-- | core/test/stopper.go | 4 |
7 files changed, 136 insertions, 56 deletions
diff --git a/core/test/app.go b/core/test/app.go index 327555b..9f030e9 100644 --- a/core/test/app.go +++ b/core/test/app.go @@ -280,8 +280,8 @@ Loop: return nil } -// Check provides a backdoor to check status of App with reader lock. -func (app *App) Check(checker func(*App)) { +// WithLock provides a backdoor to check status of App with reader lock. +func (app *App) WithLock(function func(*App)) { app.confirmedLock.RLock() defer app.confirmedLock.RUnlock() app.totalOrderedLock.RLock() @@ -289,5 +289,5 @@ func (app *App) Check(checker func(*App)) { app.deliveredLock.RLock() defer app.deliveredLock.RUnlock() - checker(app) + function(app) } diff --git a/core/test/fake-transport.go b/core/test/fake-transport.go index a783ac9..388d0aa 100644 --- a/core/test/fake-transport.go +++ b/core/test/fake-transport.go @@ -15,23 +15,6 @@ // along with the dexon-consensus library. If not, see // <http://www.gnu.org/licenses/>. -// Copyright 2018 The dexon-consensus Authors -// This file is part of the dexon-consensus library. -// -// The dexon-consensus library is free software: you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation, either version 3 of the License, -// or (at your option) any later version. -// -// The dexon-consensus library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the dexon-consensus library. If not, see -// <http://www.gnu.org/licenses/>. - package test import ( diff --git a/core/test/interface.go b/core/test/interface.go index e7a8f70..dcecee8 100644 --- a/core/test/interface.go +++ b/core/test/interface.go @@ -15,23 +15,6 @@ // along with the dexon-consensus library. If not, see // <http://www.gnu.org/licenses/>. -// Copyright 2018 The dexon-consensus Authors -// This file is part of the dexon-consensus library. -// -// The dexon-consensus library is free software: you can redistribute it -// and/or modify it under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation, either version 3 of the License, -// or (at your option) any later version. -// -// The dexon-consensus library is distributed in the hope that it will be -// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the dexon-consensus library. If not, see -// <http://www.gnu.org/licenses/>. - package test import ( diff --git a/core/test/network.go b/core/test/network.go index 8bcb050..207d8a4 100644 --- a/core/test/network.go +++ b/core/test/network.go @@ -437,6 +437,11 @@ func (n *Network) Broadcast(msg interface{}) { } } +// Send exports 'Send' method of Transport. +func (n *Network) Send(nodeID types.NodeID, msg interface{}) error { + return n.trans.Send(nodeID, msg) +} + // ReceiveChanForNode returns a channel for messages not handled by // core.Consensus. func (n *Network) ReceiveChanForNode() <-chan interface{} { diff --git a/core/test/revealer.go b/core/test/revealer.go index b39a898..dcd75a5 100644 --- a/core/test/revealer.go +++ b/core/test/revealer.go @@ -15,26 +15,10 @@ // along with the dexon-consensus library. If not, see // <http://www.gnu.org/licenses/>. -// Copyright 2018 The dexon-consensus Authors -// This file is part of the dexon-consensus library. -// -// The dexon-consensus library is free software: you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation, either version 3 of the License, -// or (at your option) any later version. -// -// The dexon-consensus library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the dexon-consensus library. If not, see -// <http://www.gnu.org/licenses/>. - package test import ( + "errors" "math/rand" "sort" "time" @@ -44,6 +28,11 @@ import ( "github.com/dexon-foundation/dexon-consensus/core/types" ) +// Errors returns from revealer. +var ( + ErrNotValidCompactionChain = errors.New("not valid compaction chain") +) + // isAllAckingBlockRevealed is a helper to check if all acking blocks of // one block are revealed. func isAllAckingBlockRevealed( @@ -280,3 +269,63 @@ func (r *RandomTipRevealer) Reset() { r.chainTip[i] = 0 } } + +// CompactionChainRevealer implements Revealer interface, which would load +// all blocks from blockdb, reveal them in the order of compaction chain, from +// the genesis block to the latest one. +type CompactionChainRevealer struct { + blocks types.ByFinalizationHeight + nextRevealIndex int +} + +// NewCompactionChainRevealer constructs a revealer in the order of compaction +// chain. +func NewCompactionChainRevealer(iter blockdb.BlockIterator, + startHeight uint64) (r *CompactionChainRevealer, err error) { + blocksByHash, err := loadAllBlocks(iter) + if err != nil { + return + } + if startHeight == 0 { + startHeight = 1 + } + blocks := types.ByFinalizationHeight{} + for _, b := range blocksByHash { + if b.Finalization.Height < startHeight { + continue + } + blocks = append(blocks, b) + } + sort.Sort(types.ByFinalizationHeight(blocks)) + // Make sure the finalization height of blocks are incremental with step 1. + for idx, b := range blocks { + if idx == 0 { + continue + } + if b.Finalization.Height != blocks[idx-1].Finalization.Height+1 { + err = ErrNotValidCompactionChain + return + } + } + r = &CompactionChainRevealer{ + blocks: blocks, + } + r.Reset() + return +} + +// Next implements Revealer.Next method, which would reveal blocks in the order +// of compaction chain. +func (r *CompactionChainRevealer) Next() (types.Block, error) { + if r.nextRevealIndex == len(r.blocks) { + return types.Block{}, blockdb.ErrIterationFinished + } + b := r.blocks[r.nextRevealIndex] + r.nextRevealIndex++ + return *b, nil +} + +// Reset implement Revealer.Reset method, which would reset revealing. +func (r *CompactionChainRevealer) Reset() { + r.nextRevealIndex = 0 +} diff --git a/core/test/revealer_test.go b/core/test/revealer_test.go index d9920c7..5a1bc07 100644 --- a/core/test/revealer_test.go +++ b/core/test/revealer_test.go @@ -157,6 +157,66 @@ func (s *RevealerTestSuite) TestRandomTipReveal() { s.baseTest(revealer, 10, checkFunc) } +func (s *RevealerTestSuite) TestCompactionChainReveal() { + db, err := blockdb.NewMemBackedBlockDB() + s.Require().NoError(err) + // Put several blocks with finalization field ready. + b1 := &types.Block{ + Hash: common.NewRandomHash(), + Finalization: types.FinalizationResult{ + Height: 1, + }} + b2 := &types.Block{ + Hash: common.NewRandomHash(), + Finalization: types.FinalizationResult{ + ParentHash: b1.Hash, + Height: 2, + }} + b3 := &types.Block{ + Hash: common.NewRandomHash(), + Finalization: types.FinalizationResult{ + ParentHash: b2.Hash, + Height: 3, + }} + s.Require().NoError(db.Put(*b1)) + s.Require().NoError(db.Put(*b3)) + iter, err := db.GetAll() + s.Require().NoError(err) + // The compaction chain is not complete, we can't construct a revealer + // instance successfully. + r, err := NewCompactionChainRevealer(iter, 0) + s.Require().Nil(r) + s.Require().IsType(ErrNotValidCompactionChain, err) + // Put a block to make the compaction chain complete. + s.Require().NoError(db.Put(*b2)) + // We can construct that revealer now. + iter, err = db.GetAll() + s.Require().NoError(err) + r, err = NewCompactionChainRevealer(iter, 0) + s.Require().NotNil(r) + s.Require().NoError(err) + // The revealing order should be ok. + chk := func(h uint64) { + b, err := r.Next() + s.Require().NoError(err) + s.Require().Equal(b.Finalization.Height, h) + } + chk(1) + chk(2) + chk(3) + // Iteration should be finished + _, err = r.Next() + s.Require().IsType(blockdb.ErrIterationFinished, err) + // Test 'startHeight' parameter. + iter, err = db.GetAll() + s.Require().NoError(err) + r, err = NewCompactionChainRevealer(iter, 2) + s.Require().NotNil(r) + s.Require().NoError(err) + chk(2) + chk(3) +} + func TestRevealer(t *testing.T) { suite.Run(t, new(RevealerTestSuite)) } diff --git a/core/test/stopper.go b/core/test/stopper.go index abc93c3..40868d8 100644 --- a/core/test/stopper.go +++ b/core/test/stopper.go @@ -61,7 +61,7 @@ func (s *StopByConfirmedBlocks) ShouldStop(nID types.NodeID) bool { lastChecked := s.lastCheckDelivered[nID] currentConfirmedBlocks := s.confirmedBlocks[nID] db := s.dbs[nID] - s.apps[nID].Check(func(app *App) { + s.apps[nID].WithLock(func(app *App) { for _, h := range app.DeliverSequence[lastChecked:] { b, err := db.Get(h) if err != nil { @@ -116,7 +116,7 @@ func (s *StopByRound) ShouldStop(nID types.NodeID) bool { if curRound := s.currentRounds[nID]; curRound < s.untilRound { lastChecked := s.lastCheckDelivered[nID] db := s.dbs[nID] - s.apps[nID].Check(func(app *App) { + s.apps[nID].WithLock(func(app *App) { for _, h := range app.DeliverSequence[lastChecked:] { b, err := db.Get(h) if err != nil { |