diff options
author | Mission Liao <mission.liao@dexon.org> | 2018-11-13 16:28:24 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-13 16:28:24 +0800 |
commit | 01642721a7768218e7f9a5be8f0829eb8ae7c7b1 (patch) | |
tree | a8ebe89570de317d7be047f32c8c35334e78c919 | |
parent | 86838fe70789292de0851f82426e5241c0f0cc96 (diff) | |
download | tangerine-consensus-01642721a7768218e7f9a5be8f0829eb8ae7c7b1.tar.gz tangerine-consensus-01642721a7768218e7f9a5be8f0829eb8ae7c7b1.tar.zst tangerine-consensus-01642721a7768218e7f9a5be8f0829eb8ae7c7b1.zip |
core: expose implicit round shift (#321)
-rw-r--r-- | cmd/dexcon-simulation-with-scheduler/main.go | 5 | ||||
-rw-r--r-- | core/compaction-chain_test.go | 3 | ||||
-rw-r--r-- | core/configuration-chain_test.go | 2 | ||||
-rw-r--r-- | core/consensus.go | 15 | ||||
-rw-r--r-- | core/consensus_test.go | 10 | ||||
-rw-r--r-- | core/constant.go | 6 | ||||
-rw-r--r-- | core/dkg-tsig-protocol_test.go | 16 | ||||
-rw-r--r-- | core/interfaces.go | 4 | ||||
-rw-r--r-- | core/lattice.go | 1 | ||||
-rw-r--r-- | core/lattice_test.go | 2 | ||||
-rw-r--r-- | core/nodeset-cache_test.go | 2 | ||||
-rw-r--r-- | core/test/governance.go | 20 | ||||
-rw-r--r-- | core/test/governance_test.go | 17 | ||||
-rw-r--r-- | core/utils.go | 11 | ||||
-rw-r--r-- | integration_test/consensus_test.go | 4 | ||||
-rw-r--r-- | integration_test/stats_test.go | 4 | ||||
-rw-r--r-- | integration_test/with_scheduler_test.go | 7 | ||||
-rw-r--r-- | simulation/node.go | 3 |
18 files changed, 71 insertions, 61 deletions
diff --git a/cmd/dexcon-simulation-with-scheduler/main.go b/cmd/dexcon-simulation-with-scheduler/main.go index 8b7c252..bf0708b 100644 --- a/cmd/dexcon-simulation-with-scheduler/main.go +++ b/cmd/dexcon-simulation-with-scheduler/main.go @@ -29,6 +29,7 @@ import ( "runtime/pprof" "time" + "github.com/dexon-foundation/dexon-consensus/core" "github.com/dexon-foundation/dexon-consensus/core/test" integration "github.com/dexon-foundation/dexon-consensus/integration_test" "github.com/dexon-foundation/dexon-consensus/simulation/config" @@ -81,7 +82,9 @@ func main() { } // Setup governance instance. gov, err := test.NewGovernance( - pubKeys, time.Duration(cfg.Networking.Mean)*time.Millisecond) + pubKeys, + time.Duration(cfg.Networking.Mean)*time.Millisecond, + core.ConfigRoundShift) if err != nil { log.Fatal("could not setup governance: ", err) } diff --git a/core/compaction-chain_test.go b/core/compaction-chain_test.go index a511dc8..2767d2d 100644 --- a/core/compaction-chain_test.go +++ b/core/compaction-chain_test.go @@ -38,7 +38,8 @@ func (s *CompactionChainTestSuite) SetupTest() { func (s *CompactionChainTestSuite) newCompactionChain() *compactionChain { _, pubKeys, err := test.NewKeys(4) s.Require().NoError(err) - gov, err := test.NewGovernance(pubKeys, 100*time.Millisecond) + gov, err := test.NewGovernance( + pubKeys, 100*time.Millisecond, ConfigRoundShift) s.Require().NoError(err) cc := newCompactionChain(gov) cc.init(&types.Block{}) diff --git a/core/configuration-chain_test.go b/core/configuration-chain_test.go index 11e5eca..b3d8ff4 100644 --- a/core/configuration-chain_test.go +++ b/core/configuration-chain_test.go @@ -172,7 +172,7 @@ func (s *ConfigurationChainTestSuite) runDKG( } for _, nID := range s.nIDs { - gov, err := test.NewGovernance(pks, 50*time.Millisecond) + gov, err := test.NewGovernance(pks, 50*time.Millisecond, ConfigRoundShift) s.Require().NoError(err) cache := NewNodeSetCache(gov) cfgChains[nID] = newConfigurationChain( diff --git a/core/consensus.go b/core/consensus.go index d12d30a..3d46c5c 100644 --- a/core/consensus.go +++ b/core/consensus.go @@ -315,11 +315,7 @@ func NewConsensus( logger common.Logger) *Consensus { // TODO(w): load latest blockHeight from DB, and use config at that height. - var ( - round uint64 - // round 0 and 1 are decided at beginning. - roundToNotify = round + 2 - ) + var round uint64 logger.Debug("Calling Governance.Configuration", "round", round) config := gov.Configuration(round) nodeSetCache := NewNodeSetCache(gov) @@ -366,7 +362,6 @@ func NewConsensus( authModule: authModule, event: common.NewEvent(), logger: logger, - roundToNotify: roundToNotify, } validLeader := func(block *types.Block) (bool, error) { @@ -416,9 +411,9 @@ func NewConsensus( // Run starts running DEXON Consensus. func (con *Consensus) Run(initBlock *types.Block) { - con.logger.Debug("Calling Governance.NotifyRoundHeight for genesis rounds", - "block", initBlock) - notifyGenesisRounds(initBlock, con.gov) + // The block past from full node should be delivered already or known by + // full node. We don't have to notify it. + con.roundToNotify = initBlock.Position.Round + 1 initRound := initBlock.Position.Round con.logger.Debug("Calling Governance.Configuration", "round", initRound) initConfig := con.gov.Configuration(initRound) @@ -1004,7 +999,7 @@ func (con *Consensus) preProcessBlock(b *types.Block) (err error) { func (con *Consensus) deliverBlock(b *types.Block) { con.logger.Debug("Calling Application.BlockDelivered", "block", b) con.app.BlockDelivered(b.Hash, b.Position, b.Finalization.Clone()) - if b.Position.Round+roundShift == con.roundToNotify { + if b.Position.Round == con.roundToNotify { // Only the first block delivered of that round would // trigger this noitification. con.logger.Debug("Calling Governance.NotifyRoundHeight", diff --git a/core/consensus_test.go b/core/consensus_test.go index 176cceb..a55d708 100644 --- a/core/consensus_test.go +++ b/core/consensus_test.go @@ -226,7 +226,7 @@ func (s *ConsensusTestSuite) TestSimpleDeliverBlock() { ) prvKeys, pubKeys, err := test.NewKeys(4) s.Require().NoError(err) - gov, err := test.NewGovernance(pubKeys, time.Second) + gov, err := test.NewGovernance(pubKeys, time.Second, ConfigRoundShift) s.Require().NoError(err) minInterval := gov.Configuration(0).MinBlockInterval // Setup core.Consensus and test.App. @@ -446,7 +446,7 @@ func (s *ConsensusTestSuite) TestPrepareBlock() { ) prvKeys, pubKeys, err := test.NewKeys(4) s.Require().NoError(err) - gov, err := test.NewGovernance(pubKeys, time.Second) + gov, err := test.NewGovernance(pubKeys, time.Second, ConfigRoundShift) s.Require().NoError(err) dMoment := time.Now().UTC() // Setup core.Consensus and test.App. @@ -488,7 +488,7 @@ func (s *ConsensusTestSuite) TestPrepareGenesisBlock() { conn := s.newNetworkConnection() prvKeys, pubKeys, err := test.NewKeys(4) s.Require().NoError(err) - gov, err := test.NewGovernance(pubKeys, time.Second) + gov, err := test.NewGovernance(pubKeys, time.Second, ConfigRoundShift) s.Require().NoError(err) prvKey := prvKeys[0] _, con := s.prepareConsensus(time.Now().UTC(), gov, prvKey, conn) @@ -510,7 +510,7 @@ func (s *ConsensusTestSuite) TestDKGCRS() { conn := s.newNetworkConnection() prvKeys, pubKeys, err := test.NewKeys(n) s.Require().NoError(err) - gov, err := test.NewGovernance(pubKeys, lambda) + gov, err := test.NewGovernance(pubKeys, lambda, ConfigRoundShift) s.Require().NoError(err) gov.State().RequestChange(test.StateChangeRoundInterval, 200*lambda) cons := map[types.NodeID]*Consensus{} @@ -550,7 +550,7 @@ func (s *ConsensusTestSuite) TestSyncBA() { conn := s.newNetworkConnection() prvKeys, pubKeys, err := test.NewKeys(4) s.Require().NoError(err) - gov, err := test.NewGovernance(pubKeys, time.Second) + gov, err := test.NewGovernance(pubKeys, time.Second, ConfigRoundShift) s.Require().NoError(err) prvKey := prvKeys[0] _, con := s.prepareConsensus(time.Now().UTC(), gov, prvKey, conn) diff --git a/core/constant.go b/core/constant.go index 9a61c0a..563a321 100644 --- a/core/constant.go +++ b/core/constant.go @@ -17,9 +17,9 @@ package core -// round shift refers to the difference between block's round and config round -// derived from its state. +// ConfigRoundShift refers to the difference between block's round and config +// round derived from its state. // // For example, when round shift is 2, a block in round 0 should derive config // for round 2. -const roundShift uint64 = 2 +const ConfigRoundShift uint64 = 2 diff --git a/core/dkg-tsig-protocol_test.go b/core/dkg-tsig-protocol_test.go index 27799d2..282dc0f 100644 --- a/core/dkg-tsig-protocol_test.go +++ b/core/dkg-tsig-protocol_test.go @@ -142,7 +142,7 @@ func (s *DKGTSIGProtocolTestSuite) TestDKGTSIGProtocol() { round := uint64(1) _, pubKeys, err := test.NewKeys(5) s.Require().NoError(err) - gov, err := test.NewGovernance(pubKeys, 100) + gov, err := test.NewGovernance(pubKeys, 100, ConfigRoundShift) s.Require().NoError(err) receivers, protocols := s.newProtocols(k, n, round) @@ -247,7 +247,7 @@ func (s *DKGTSIGProtocolTestSuite) TestNackComplaint() { round := uint64(1) _, pubKeys, err := test.NewKeys(5) s.Require().NoError(err) - gov, err := test.NewGovernance(pubKeys, 100) + gov, err := test.NewGovernance(pubKeys, 100, ConfigRoundShift) s.Require().NoError(err) receivers, protocols := s.newProtocols(k, n, round) @@ -293,7 +293,7 @@ func (s *DKGTSIGProtocolTestSuite) TestComplaint() { round := uint64(1) _, pubKeys, err := test.NewKeys(5) s.Require().NoError(err) - gov, err := test.NewGovernance(pubKeys, 100) + gov, err := test.NewGovernance(pubKeys, 100, ConfigRoundShift) s.Require().NoError(err) receivers, protocols := s.newProtocols(k, n, round) @@ -358,7 +358,7 @@ func (s *DKGTSIGProtocolTestSuite) TestAntiComplaint() { round := uint64(1) _, pubKeys, err := test.NewKeys(5) s.Require().NoError(err) - gov, err := test.NewGovernance(pubKeys, 100) + gov, err := test.NewGovernance(pubKeys, 100, ConfigRoundShift) s.Require().NoError(err) receivers, protocols := s.newProtocols(k, n, round) @@ -415,7 +415,7 @@ func (s *DKGTSIGProtocolTestSuite) TestEncorceNackComplaint() { round := uint64(1) _, pubKeys, err := test.NewKeys(5) s.Require().NoError(err) - gov, err := test.NewGovernance(pubKeys, 100) + gov, err := test.NewGovernance(pubKeys, 100, ConfigRoundShift) s.Require().NoError(err) receivers, protocols := s.newProtocols(k, n, round) @@ -469,7 +469,7 @@ func (s *DKGTSIGProtocolTestSuite) TestQualifyIDs() { round := uint64(1) _, pubKeys, err := test.NewKeys(5) s.Require().NoError(err) - gov, err := test.NewGovernance(pubKeys, 100) + gov, err := test.NewGovernance(pubKeys, 100, ConfigRoundShift) s.Require().NoError(err) receivers, _ := s.newProtocols(k, n, round) @@ -534,7 +534,7 @@ func (s *DKGTSIGProtocolTestSuite) TestPartialSignature() { round := uint64(1) _, pubKeys, err := test.NewKeys(5) s.Require().NoError(err) - gov, err := test.NewGovernance(pubKeys, 100) + gov, err := test.NewGovernance(pubKeys, 100, ConfigRoundShift) s.Require().NoError(err) receivers, protocols := s.newProtocols(k, n, round) @@ -656,7 +656,7 @@ func (s *DKGTSIGProtocolTestSuite) TestTSigVerifierCache() { n := 10 _, pubKeys, err := test.NewKeys(n) s.Require().NoError(err) - gov, err := test.NewGovernance(pubKeys, 100) + gov, err := test.NewGovernance(pubKeys, 100, ConfigRoundShift) s.Require().NoError(err) gov.CatchUpWithRound(10) for i := 0; i < 10; i++ { diff --git a/core/interfaces.go b/core/interfaces.go index 3a9c075..e07476d 100644 --- a/core/interfaces.go +++ b/core/interfaces.go @@ -111,8 +111,8 @@ type Governance interface { // Return the genesis node set if round == 0. NodeSet(round uint64) []crypto.PublicKey - // NotifyRoundHeight notifies governance contract to generate configuration - // for that round with the block on that consensus height. + // NotifyRoundHeight notifies governance contract the consensus height of + // the first block of the given round. NotifyRoundHeight(targetRound, consensusHeight uint64) //// DKG-related methods. diff --git a/core/lattice.go b/core/lattice.go index dcb3368..108f288 100644 --- a/core/lattice.go +++ b/core/lattice.go @@ -282,7 +282,6 @@ func (l *Lattice) PurgeBlocks(blocks []*types.Block) error { func (l *Lattice) AppendConfig(round uint64, config *types.Config) (err error) { l.lock.Lock() defer l.lock.Unlock() - l.pool.resize(config.NumChains) if err = l.data.appendConfig(round, config); err != nil { return diff --git a/core/lattice_test.go b/core/lattice_test.go index b5df1ec..5c5a667 100644 --- a/core/lattice_test.go +++ b/core/lattice_test.go @@ -104,7 +104,7 @@ func (s *LatticeTestSuite) newTestLatticeMgr( // Setup governance. _, pubKeys, err := test.NewKeys(int(cfg.NotarySetSize)) req.NoError(err) - gov, err := test.NewGovernance(pubKeys, cfg.LambdaBA) + gov, err := test.NewGovernance(pubKeys, cfg.LambdaBA, ConfigRoundShift) req.NoError(err) // Setup application. app := test.NewApp(gov.State()) diff --git a/core/nodeset-cache_test.go b/core/nodeset-cache_test.go index 3a50613..828ef49 100644 --- a/core/nodeset-cache_test.go +++ b/core/nodeset-cache_test.go @@ -63,7 +63,7 @@ func (s *NodeSetCacheTestSuite) TestGovernanceIntf() { var gov Governance _, pubKeys, err := test.NewKeys(7) s.Require().NoError(err) - gov, err = test.NewGovernance(pubKeys, 250*time.Millisecond) + gov, err = test.NewGovernance(pubKeys, 250*time.Millisecond, ConfigRoundShift) s.Require().NoError(err) _, ok := gov.(NodeSetCacheInterface) s.True(ok) diff --git a/core/test/governance.go b/core/test/governance.go index f27139f..58b773a 100644 --- a/core/test/governance.go +++ b/core/test/governance.go @@ -35,6 +35,7 @@ import ( // Governance is an implementation of Goverance for testing purpose. type Governance struct { + roundShift uint64 configs []*types.Config nodeSets [][]crypto.PublicKey stateModule *State @@ -44,13 +45,14 @@ type Governance struct { } // NewGovernance constructs a Governance instance. -func NewGovernance(genesisNodes []crypto.PublicKey, - lambda time.Duration) (g *Governance, err error) { +func NewGovernance(genesisNodes []crypto.PublicKey, lambda time.Duration, + roundShift uint64) (g *Governance, err error) { // Setup a State instance. // TODO(mission): it's not a good idea to embed initialization of one // public class in another, I did this to make the range of // modification smaller. g = &Governance{ + roundShift: roundShift, pendingConfigChanges: make(map[uint64]map[StateChangeType]interface{}), stateModule: NewState(genesisNodes, lambda, true), } @@ -95,17 +97,20 @@ func (g *Governance) CRS(round uint64) common.Hash { // NotifyRoundHeight notifies governace contract to snapshot config. func (g *Governance) NotifyRoundHeight(round, height uint64) { - g.CatchUpWithRound(round) + // Snapshot configuration for the shifted round, this behavior is synced with + // full node's implementation. + shiftedRound := round + g.roundShift + g.CatchUpWithRound(shiftedRound) // Apply change request for next round. func() { g.lock.Lock() defer g.lock.Unlock() - for t, v := range g.pendingConfigChanges[round+1] { + for t, v := range g.pendingConfigChanges[shiftedRound+1] { if err := g.stateModule.RequestChange(t, v); err != nil { panic(err) } } - delete(g.pendingConfigChanges, round+1) + delete(g.pendingConfigChanges, shiftedRound+1) g.broadcastPendingStateChanges() }() } @@ -280,6 +285,7 @@ func (g *Governance) Clone() *Governance { } // Clone pending changes. return &Governance{ + roundShift: g.roundShift, configs: copiedConfigs, stateModule: copiedState, nodeSets: copiedNodeSets, @@ -289,6 +295,10 @@ func (g *Governance) Clone() *Governance { // Equal checks equality between two Governance instances. func (g *Governance) Equal(other *Governance, checkState bool) bool { + // Check roundShift. + if g.roundShift != other.roundShift { + return false + } // Check configs. if !reflect.DeepEqual(g.configs, other.configs) { return false diff --git a/core/test/governance_test.go b/core/test/governance_test.go index 1c6dbd2..07b0d46 100644 --- a/core/test/governance_test.go +++ b/core/test/governance_test.go @@ -33,10 +33,10 @@ func (s *GovernanceTestSuite) TestEqual() { // Setup a base governance. _, genesisNodes, err := NewKeys(20) req.NoError(err) - g1, err := NewGovernance(genesisNodes, 100*time.Millisecond) + g1, err := NewGovernance(genesisNodes, 100*time.Millisecond, 2) req.NoError(err) // Create a governance with different lambda. - g2, err := NewGovernance(genesisNodes, 50*time.Millisecond) + g2, err := NewGovernance(genesisNodes, 50*time.Millisecond, 2) req.NoError(err) req.False(g1.Equal(g2, true)) // Create configs for 3 rounds for g1. @@ -57,13 +57,18 @@ func (s *GovernanceTestSuite) TestEqual() { g1.CatchUpWithRound(5) g4.CatchUpWithRound(5) req.False(g1.Equal(g4, true)) + // Make a clone. + g5 := g1.Clone() + // Change its roundShift + g5.roundShift = 3 + req.False(g1.Equal(g5, true)) } func (s *GovernanceTestSuite) TestRegisterChange() { req := s.Require() _, genesisNodes, err := NewKeys(20) req.NoError(err) - g, err := NewGovernance(genesisNodes, 100*time.Millisecond) + g, err := NewGovernance(genesisNodes, 100*time.Millisecond, 2) req.NoError(err) // Unable to register change for genesis round. req.Error(g.RegisterConfigChange(0, StateChangeNumChains, uint32(32))) @@ -79,12 +84,12 @@ func (s *GovernanceTestSuite) TestRegisterChange() { req.NoError(g.RegisterConfigChange(7, StateChangeNumChains, uint32(40))) // In local mode, state for round 6 would be ready after notified with // round 5. - g.NotifyRoundHeight(5, 0) + g.NotifyRoundHeight(3, 0) // In local mode, state for round 7 would be ready after notified with // round 6. - g.NotifyRoundHeight(6, 0) + g.NotifyRoundHeight(4, 0) // Notify governance to take a snapshot for round 7's configuration. - g.NotifyRoundHeight(7, 0) + g.NotifyRoundHeight(5, 0) req.Equal(g.Configuration(6).NumChains, uint32(32)) req.Equal(g.Configuration(7).NumChains, uint32(40)) } diff --git a/core/utils.go b/core/utils.go index 9159be8..6b9ce63 100644 --- a/core/utils.go +++ b/core/utils.go @@ -159,14 +159,3 @@ func DiffUint64(a, b uint64) uint64 { } return b - a } - -// notifyGenesisRounds notifies governance to generate configs based on genesis -// state. -func notifyGenesisRounds(initBlock *types.Block, gov Governance) { - if initBlock.Position.Round != 0 || !initBlock.IsGenesis() { - return - } - for round := uint64(0); round < roundShift; round++ { - gov.NotifyRoundHeight(round, 0) - } -} diff --git a/integration_test/consensus_test.go b/integration_test/consensus_test.go index 52f7f9f..356efb1 100644 --- a/integration_test/consensus_test.go +++ b/integration_test/consensus_test.go @@ -109,10 +109,12 @@ func (s *ConsensusTestSuite) TestSimple() { req.NoError(err) // Setup seed governance instance. Give a short latency to make this test // run faster. - seedGov, err := test.NewGovernance(pubKeys, 30*time.Millisecond) + seedGov, err := test.NewGovernance( + pubKeys, 30*time.Millisecond, core.ConfigRoundShift) req.NoError(err) req.NoError(seedGov.State().RequestChange( test.StateChangeRoundInterval, 25*time.Second)) + seedGov.NotifyRoundHeight(0, 0) // A short round interval. nodes := s.setupNodes(dMoment, prvKeys, seedGov) for _, n := range nodes { diff --git a/integration_test/stats_test.go b/integration_test/stats_test.go index 4a618bc..1830501 100644 --- a/integration_test/stats_test.go +++ b/integration_test/stats_test.go @@ -4,6 +4,7 @@ import ( "testing" "time" + "github.com/dexon-foundation/dexon-consensus/core" "github.com/dexon-foundation/dexon-consensus/core/test" "github.com/stretchr/testify/suite" ) @@ -22,7 +23,8 @@ func (s *EventStatsTestSuite) TestCalculate() { ) prvKeys, pubKeys, err := test.NewKeys(7) req.NoError(err) - gov, err := test.NewGovernance(pubKeys, 100*time.Millisecond) + gov, err := test.NewGovernance( + pubKeys, 100*time.Millisecond, core.ConfigRoundShift) req.NoError(err) nodes, err := PrepareNodes( gov, prvKeys, 7, networkLatency, proposingLatency) diff --git a/integration_test/with_scheduler_test.go b/integration_test/with_scheduler_test.go index 1105805..a9f229a 100644 --- a/integration_test/with_scheduler_test.go +++ b/integration_test/with_scheduler_test.go @@ -21,6 +21,7 @@ import ( "testing" "time" + "github.com/dexon-foundation/dexon-consensus/core" "github.com/dexon-foundation/dexon-consensus/core/test" "github.com/stretchr/testify/suite" ) @@ -49,7 +50,8 @@ func (s *WithSchedulerTestSuite) TestNonByzantine() { prvKeys, pubKeys, err := test.NewKeys(numNodes) req.NoError(err) // Setup governance. - gov, err := test.NewGovernance(pubKeys, 250*time.Millisecond) + gov, err := test.NewGovernance( + pubKeys, 250*time.Millisecond, core.ConfigRoundShift) req.NoError(err) // Setup nodes. nodes, err := PrepareNodes( @@ -89,7 +91,8 @@ func (s *WithSchedulerTestSuite) TestConfigurationChange() { prvKeys, pubKeys, err := test.NewKeys(numNodes) req.NoError(err) // Setup governance. - gov, err := test.NewGovernance(pubKeys, 250*time.Millisecond) + gov, err := test.NewGovernance( + pubKeys, 250*time.Millisecond, core.ConfigRoundShift) req.NoError(err) // Change default round interval, expect 1 round produce 30 blocks. gov.State().RequestChange(test.StateChangeRoundInterval, 15*time.Second) diff --git a/simulation/node.go b/simulation/node.go index 1127f5a..8c398cf 100644 --- a/simulation/node.go +++ b/simulation/node.go @@ -87,7 +87,8 @@ func newNode( } // Sync config to state in governance. cConfig := config.Node.Consensus - gov, err := test.NewGovernance([]crypto.PublicKey{pubKey}, time.Millisecond) + gov, err := test.NewGovernance( + []crypto.PublicKey{pubKey}, time.Millisecond, core.ConfigRoundShift) if err != nil { panic(err) } |