diff options
-rw-r--r-- | cmd/dexcon-simulation-with-scheduler/main.go | 4 | ||||
-rw-r--r-- | cmd/dexcon-simulation/main.go | 3 | ||||
-rw-r--r-- | core/agreement-state.go | 16 | ||||
-rw-r--r-- | core/agreement-state_test.go | 6 | ||||
-rw-r--r-- | core/agreement.go | 28 | ||||
-rw-r--r-- | core/agreement_test.go | 6 | ||||
-rw-r--r-- | core/consensus.go | 11 | ||||
-rw-r--r-- | simulation/config/config.go | 27 | ||||
-rw-r--r-- | simulation/kubernetes/config.toml.in | 7 | ||||
-rw-r--r-- | simulation/simulation.go | 6 | ||||
-rw-r--r-- | simulation/validator.go | 26 |
11 files changed, 84 insertions, 56 deletions
diff --git a/cmd/dexcon-simulation-with-scheduler/main.go b/cmd/dexcon-simulation-with-scheduler/main.go index b9f5ec3..d1d815a 100644 --- a/cmd/dexcon-simulation-with-scheduler/main.go +++ b/cmd/dexcon-simulation-with-scheduler/main.go @@ -49,8 +49,8 @@ func main() { Mean: cfg.Networking.Mean, } proposingLatency := &integration.NormalLatencyModel{ - Sigma: cfg.Validator.ProposeIntervalSigma, - Mean: cfg.Validator.ProposeIntervalMean, + Sigma: cfg.Validator.Legacy.ProposeIntervalSigma, + Mean: cfg.Validator.Legacy.ProposeIntervalMean, } // Setup validators and other consensus related stuffs. apps, dbs, validators, err := integration.PrepareValidators( diff --git a/cmd/dexcon-simulation/main.go b/cmd/dexcon-simulation/main.go index def4ac9..017cca5 100644 --- a/cmd/dexcon-simulation/main.go +++ b/cmd/dexcon-simulation/main.go @@ -35,6 +35,7 @@ var initialize = flag.Bool("init", false, "initialize config file") var configFile = flag.String("config", "", "path to simulation config file") var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to `file`") var memprofile = flag.String("memprofile", "", "write memory profile to `file`") +var legacy = flag.Bool("legacy", false, "legacy consensus protocal") func main() { flag.Parse() @@ -65,7 +66,7 @@ func main() { defer pprof.StopCPUProfile() } - simulation.Run(*configFile) + simulation.Run(*configFile, *legacy) if *memprofile != "" { f, err := os.Create(*memprofile) diff --git a/core/agreement-state.go b/core/agreement-state.go index 33f86ce..b948417 100644 --- a/core/agreement-state.go +++ b/core/agreement-state.go @@ -81,7 +81,7 @@ func (s *prepareState) nextState() (agreementState, error) { delete(s.a.blocks, s.a.ID) } } - s.a.recv.proposeBlock(hash) + s.a.recv.ProposeBlock(hash) return newAckState(s.a), nil } func (s *prepareState) receiveVote() error { return nil } @@ -112,7 +112,7 @@ func (s *ackState) nextState() (agreementState, error) { if hash == nullBlockHash { hash = s.a.leader.leaderBlockHash() } - s.a.recv.proposeVote(&types.Vote{ + s.a.recv.ProposeVote(&types.Vote{ Type: types.VoteAck, BlockHash: hash, Period: s.a.period, @@ -151,7 +151,7 @@ func (s *confirmState) receiveVote() error { return nil } if hash != nullBlockHash { - s.a.recv.proposeVote(&types.Vote{ + s.a.recv.ProposeVote(&types.Vote{ Type: types.VoteConfirm, BlockHash: hash, Period: s.a.period, @@ -181,7 +181,7 @@ func (s *pass1State) nextState() (agreementState, error) { v, e := s.a.votes[s.a.period][types.VoteConfirm][s.a.ID] return v, e }(); exist { - s.a.recv.proposeVote(&types.Vote{ + s.a.recv.ProposeVote(&types.Vote{ Type: types.VotePass, BlockHash: vote.BlockHash, Period: s.a.period, @@ -192,7 +192,7 @@ func (s *pass1State) nextState() (agreementState, error) { hash, ok := s.a.countVote(s.a.period-1, types.VotePass) if ok { if hash == nullBlockHash { - s.a.recv.proposeVote(&types.Vote{ + s.a.recv.ProposeVote(&types.Vote{ Type: types.VotePass, BlockHash: hash, Period: s.a.period, @@ -205,7 +205,7 @@ func (s *pass1State) nextState() (agreementState, error) { } } if voteDefault { - s.a.recv.proposeVote(&types.Vote{ + s.a.recv.ProposeVote(&types.Vote{ Type: types.VotePass, BlockHash: s.a.defaultBlock, Period: s.a.period, @@ -261,7 +261,7 @@ func (s *pass2State) receiveVote() error { } ackHash, ok := s.a.countVote(s.a.period, types.VoteAck) if ok && ackHash != nullBlockHash { - s.a.recv.proposeVote(&types.Vote{ + s.a.recv.ProposeVote(&types.Vote{ Type: types.VotePass, BlockHash: ackHash, Period: s.a.period, @@ -272,7 +272,7 @@ func (s *pass2State) receiveVote() error { s.a.votes[s.a.period][types.VoteConfirm][s.a.ID]; !exist { hash, ok := s.a.countVote(s.a.period-1, types.VotePass) if ok && hash == nullBlockHash { - s.a.recv.proposeVote(&types.Vote{ + s.a.recv.ProposeVote(&types.Vote{ Type: types.VotePass, BlockHash: hash, Period: s.a.period, diff --git a/core/agreement-state_test.go b/core/agreement-state_test.go index a120965..1591625 100644 --- a/core/agreement-state_test.go +++ b/core/agreement-state_test.go @@ -43,15 +43,15 @@ type agreementStateTestReceiver struct { s *AgreementStateTestSuite } -func (r *agreementStateTestReceiver) proposeVote(vote *types.Vote) { +func (r *agreementStateTestReceiver) ProposeVote(vote *types.Vote) { r.s.voteChan <- vote } -func (r *agreementStateTestReceiver) proposeBlock(block common.Hash) { +func (r *agreementStateTestReceiver) ProposeBlock(block common.Hash) { r.s.blockChan <- block } -func (r *agreementStateTestReceiver) confirmBlock(block common.Hash) { +func (r *agreementStateTestReceiver) ConfirmBlock(block common.Hash) { r.s.confirmChan <- block } diff --git a/core/agreement.go b/core/agreement.go index 8fb2207..e741145 100644 --- a/core/agreement.go +++ b/core/agreement.go @@ -58,9 +58,9 @@ func newVoteListMap() []map[types.ValidatorID]*types.Vote { // agreementReceiver is the interface receiving agreement event. type agreementReceiver interface { - proposeVote(vote *types.Vote) - proposeBlock(common.Hash) - confirmBlock(common.Hash) + ProposeVote(vote *types.Vote) + ProposeBlock(common.Hash) + ConfirmBlock(common.Hash) } type pendingBlock struct { @@ -230,18 +230,20 @@ func (a *agreement) sanityCheck(vote *types.Vote) error { if !ok { return ErrIncorrectVoteSignature } - if exist := func() bool { + + if err := func() error { a.data.votesLock.RLock() defer a.data.votesLock.RUnlock() - _, exist := a.data.votes[vote.Period] - return exist - }(); exist { - if oldVote, exist := - a.data.votes[vote.Period][vote.Type][vote.ProposerID]; exist { - if vote.BlockHash != oldVote.BlockHash { - return ErrForkVote + if votes, exist := a.data.votes[vote.Period]; exist { + if oldVote, exist := votes[vote.Type][vote.ProposerID]; exist { + if vote.BlockHash != oldVote.BlockHash { + return ErrForkVote + } } } + return nil + }(); err != nil { + return err } return nil } @@ -262,6 +264,8 @@ func (a *agreement) processVote(vote *types.Vote) error { return err } if vote.Position != a.agreementID() { + a.lock.Lock() + defer a.lock.Unlock() a.pendingVote = append(a.pendingVote, pendingVote{ vote: vote, receivedTime: time.Now().UTC(), @@ -279,7 +283,7 @@ func (a *agreement) processVote(vote *types.Vote) error { if len(a.data.votes[vote.Period][types.VoteConfirm]) >= a.data.requiredVote { a.hasOutput = true - a.data.recv.confirmBlock(vote.BlockHash) + a.data.recv.ConfirmBlock(vote.BlockHash) } } return true diff --git a/core/agreement_test.go b/core/agreement_test.go index aafd1ed..4f6ec5b 100644 --- a/core/agreement_test.go +++ b/core/agreement_test.go @@ -32,15 +32,15 @@ type agreementTestReceiver struct { s *AgreementTestSuite } -func (r *agreementTestReceiver) proposeVote(vote *types.Vote) { +func (r *agreementTestReceiver) ProposeVote(vote *types.Vote) { r.s.voteChan <- vote } -func (r *agreementTestReceiver) proposeBlock(block common.Hash) { +func (r *agreementTestReceiver) ProposeBlock(block common.Hash) { r.s.blockChan <- block } -func (r *agreementTestReceiver) confirmBlock(block common.Hash) { +func (r *agreementTestReceiver) ConfirmBlock(block common.Hash) { r.s.confirmChan <- block } diff --git a/core/consensus.go b/core/consensus.go index 5b85fcb..6d74bd7 100644 --- a/core/consensus.go +++ b/core/consensus.go @@ -70,8 +70,7 @@ type consensusReceiver struct { restart chan struct{} } -func (recv *consensusReceiver) proposeVote(vote *types.Vote) { - // TODO(jimmy-dexon): move prepareVote() into agreement. +func (recv *consensusReceiver) ProposeVote(vote *types.Vote) { if err := recv.consensus.prepareVote(recv.chainID, vote); err != nil { fmt.Println(err) return @@ -84,7 +83,8 @@ func (recv *consensusReceiver) proposeVote(vote *types.Vote) { recv.consensus.network.BroadcastVote(vote) }() } -func (recv *consensusReceiver) proposeBlock(hash common.Hash) { + +func (recv *consensusReceiver) ProposeBlock(hash common.Hash) { block, exist := recv.consensus.baModules[recv.chainID].findCandidateBlock(hash) if !exist { fmt.Println(ErrUnknownBlockProposed) @@ -97,17 +97,18 @@ func (recv *consensusReceiver) proposeBlock(hash common.Hash) { } recv.consensus.network.BroadcastBlock(block) } -func (recv *consensusReceiver) confirmBlock(hash common.Hash) { + +func (recv *consensusReceiver) ConfirmBlock(hash common.Hash) { block, exist := recv.consensus.baModules[recv.chainID].findCandidateBlock(hash) if !exist { fmt.Println(ErrUnknownBlockConfirmed, hash) return } - recv.restart <- struct{}{} if err := recv.consensus.ProcessBlock(block); err != nil { fmt.Println(err) return } + recv.restart <- struct{}{} } // Consensus implements DEXON Consensus algorithm. diff --git a/simulation/config/config.go b/simulation/config/config.go index c59b663..2f03f85 100644 --- a/simulation/config/config.go +++ b/simulation/config/config.go @@ -41,13 +41,19 @@ type Consensus struct { GenesisCRS string `toml:"genesis_crs"` } -// Validator config for the simulation. -type Validator struct { - Consensus Consensus - Num int +// Legacy config. +type Legacy struct { ProposeIntervalMean float64 ProposeIntervalSigma float64 - MaxBlock uint64 +} + +// Validator config for the simulation. +type Validator struct { + Consensus Consensus + Legacy Legacy + Num int + Lambda int + MaxBlock uint64 } // Networking config. @@ -90,10 +96,13 @@ func GenerateDefault(path string) error { ChainNum: 7, GenesisCRS: "In DEXON we trust.", }, - Num: 7, - ProposeIntervalMean: 500, - ProposeIntervalSigma: 30, - MaxBlock: math.MaxUint64, + Legacy: Legacy{ + ProposeIntervalMean: 500, + ProposeIntervalSigma: 50, + }, + Num: 7, + Lambda: 250, + MaxBlock: math.MaxUint64, }, Networking: Networking{ Type: NetworkTypeTCPLocal, diff --git a/simulation/kubernetes/config.toml.in b/simulation/kubernetes/config.toml.in index 1cc18aa..2f12956 100644 --- a/simulation/kubernetes/config.toml.in +++ b/simulation/kubernetes/config.toml.in @@ -2,8 +2,7 @@ title = "DEXON Consensus Simulation Config" [validator] num = {{numValidators}} -propose_interval_mean = 5e+02 -propose_interval_sigma = 3e+01 +lambda = 250 max_block = 1000 [validator.consensus] @@ -12,6 +11,10 @@ k = 1 chain_num = 7 genesis_crs = "In DEXON we trust." +[validator.legacy] +propose_interval_mean = 5e+02 +propose_interval_sigma = 5e+01 + [networking] type = "tcp" peer_server = "peer-server-svc.default.svc.cluster.local" diff --git a/simulation/simulation.go b/simulation/simulation.go index 4cfc79c..978107a 100644 --- a/simulation/simulation.go +++ b/simulation/simulation.go @@ -26,7 +26,7 @@ import ( ) // Run starts the simulation. -func Run(configPath string) { +func Run(configPath string, legacy bool) { cfg, err := config.Read(configPath) if err != nil { panic(err) @@ -65,7 +65,7 @@ func Run(configPath string) { for i := 0; i < cfg.Validator.Num; i++ { fmt.Printf("Validator %d: %s\n", i, vs[i].ID) - go vs[i].Run() + go vs[i].Run(legacy) } } else if networkType == config.NetworkTypeTCP { prv, err := eth.NewPrivateKey() @@ -75,7 +75,7 @@ func Run(configPath string) { network := NewTCPNetwork(false, cfg.Networking.PeerServer, networkModel) network.Start() v := NewValidator(prv, eth.SigToPub, cfg.Validator, network) - go v.Run() + go v.Run(legacy) vs = append(vs, v) } diff --git a/simulation/validator.go b/simulation/validator.go index 6d73c50..21b9db6 100644 --- a/simulation/validator.go +++ b/simulation/validator.go @@ -83,7 +83,7 @@ func (v *Validator) GetID() types.ValidatorID { } // Run starts the validator. -func (v *Validator) Run() { +func (v *Validator) Run(legacy bool) { v.network.Join(v) v.msgChannel = v.network.ReceiveChan() @@ -99,13 +99,23 @@ func (v *Validator) Run() { break } } - v.consensus = core.NewConsensus( - v.app, v.gov, v.db, v.network, - time.NewTicker( - time.Duration(v.config.ProposeIntervalMean)*time.Millisecond), - v.prvKey, v.sigToPub) - - go v.consensus.Run() + if legacy { + v.consensus = core.NewConsensus( + v.app, v.gov, v.db, v.network, + time.NewTicker( + time.Duration(v.config.Legacy.ProposeIntervalMean)*time.Millisecond), + v.prvKey, v.sigToPub) + + go v.consensus.RunLegacy() + } else { + v.consensus = core.NewConsensus( + v.app, v.gov, v.db, v.network, + time.NewTicker( + time.Duration(v.config.Lambda)*time.Millisecond), + v.prvKey, v.sigToPub) + + go v.consensus.Run() + } isShutdown := make(chan struct{}) |