diff options
author | Mission Liao <mission.liao@dexon.org> | 2018-08-08 19:32:20 +0800 |
---|---|---|
committer | Wei-Ning Huang <aitjcize@gmail.com> | 2018-08-08 19:32:20 +0800 |
commit | 295c7b5efbc36f59e3ae8d10bc3abc3a5d17e785 (patch) | |
tree | bdb93aaa638ec890596a18490505a45204dc2cc7 /simulation | |
parent | a418ea95c0f5afb50cbb78aedecc68373353d06e (diff) | |
download | dexon-consensus-295c7b5efbc36f59e3ae8d10bc3abc3a5d17e785.tar.gz dexon-consensus-295c7b5efbc36f59e3ae8d10bc3abc3a5d17e785.tar.zst dexon-consensus-295c7b5efbc36f59e3ae8d10bc3abc3a5d17e785.zip |
core: Add Consensus to replace core.Blocklattice (#35)
* Make Sequencer return slice of blocks.
* Fix naming issue
The function 'getHeightVecto' would return ackingStatusVector.
* Fix comment error.
* Add methods to collect info when proposing blocks.
* Add test.App
* Add test.Gov
* Move this type to core.types to avoid cyclic import.
* Add core.Consensus
* Move getMedianTime, interpoTime to util
These functions are not depending on members of core.consensusTimestamp and
is required when testing core.Consensus.
* Make sure types.Block.Clone would copy critical fields.
* Remove core.blocklattice
* Define 'infinity' in core/total-ordering
This definition is defined in core/blocklattice originally.
* Fix a bug when processing the same block twice.
* Integrate simulation with core.Consensus
core.Consensus is a replacement of core.Blocklattice
* Fix the comment to use sigular form.
* Move lock mechanism to sub modules.
* phi should be 2*fmax+1
* Fixup: should aborting when the validator is added
* Fix for new block fields
* Fix the bug that the total ordering sequence is wrong.
Diffstat (limited to 'simulation')
-rw-r--r-- | simulation/app.go | 5 | ||||
-rw-r--r-- | simulation/gov.go | 74 | ||||
-rw-r--r-- | simulation/network-model.go | 17 | ||||
-rw-r--r-- | simulation/network-model_test.go | 17 | ||||
-rw-r--r-- | simulation/validator.go | 94 |
5 files changed, 171 insertions, 36 deletions
diff --git a/simulation/app.go b/simulation/app.go index 5533abb..797ab91 100644 --- a/simulation/app.go +++ b/simulation/app.go @@ -77,6 +77,11 @@ func (a *SimApp) getAckedBlocks(ackHash common.Hash) (output common.Hashes) { return } +// StronglyAcked is called when a block is strongly acked by DEXON +// Reliabe Broadcast algorithm. +func (a *SimApp) StronglyAcked(blockHash common.Hash) { +} + // TotalOrderingDeliver is called when blocks are delivered by the total // ordering algorithm. func (a *SimApp) TotalOrderingDeliver(blocks []*types.Block, early bool) { diff --git a/simulation/gov.go b/simulation/gov.go new file mode 100644 index 0000000..ddba949 --- /dev/null +++ b/simulation/gov.go @@ -0,0 +1,74 @@ +// Copyright 2018 The dexon-consensus-core Authors +// This file is part of the dexon-consensus-core library. +// +// The dexon-consensus-core 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-core 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-core library. If not, see +// <http://www.gnu.org/licenses/>. + +package simulation + +import ( + "fmt" + "sync" + + "github.com/dexon-foundation/dexon-consensus-core/core/types" + "github.com/shopspring/decimal" +) + +type simGov struct { + lock sync.RWMutex + validatorSet map[types.ValidatorID]decimal.Decimal + expectedNumValidators int +} + +func newSimGov(numValidators int) *simGov { + return &simGov{ + validatorSet: make(map[types.ValidatorID]decimal.Decimal), + expectedNumValidators: numValidators, + } +} + +func (gov *simGov) GetValidatorSet() ( + ret map[types.ValidatorID]decimal.Decimal) { + + gov.lock.RLock() + defer gov.lock.RUnlock() + + // Return the cloned validatorSet. + ret = make(map[types.ValidatorID]decimal.Decimal) + for k, v := range gov.validatorSet { + ret[k] = v + } + return +} + +func (gov *simGov) GetBlockProposingInterval() int { + return 0 +} + +func (gov *simGov) GetMembershipEvents(epoch int) []types.MembershipEvent { + return nil +} + +func (gov *simGov) addValidator(vID types.ValidatorID) { + gov.lock.Lock() + defer gov.lock.Unlock() + + if _, exists := gov.validatorSet[vID]; exists { + return + } + if len(gov.validatorSet) == gov.expectedNumValidators { + panic(fmt.Errorf("attempt to add validator when ready")) + } + gov.validatorSet[vID] = decimal.NewFromFloat(0) +} diff --git a/simulation/network-model.go b/simulation/network-model.go index 041bd12..01704e7 100644 --- a/simulation/network-model.go +++ b/simulation/network-model.go @@ -1,3 +1,20 @@ +// Copyright 2018 The dexon-consensus-core Authors +// This file is part of the dexon-consensus-core library. +// +// The dexon-consensus-core 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-core 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-core library. If not, see +// <http://www.gnu.org/licenses/>. + package simulation import ( diff --git a/simulation/network-model_test.go b/simulation/network-model_test.go index aefa3c6..a9de462 100644 --- a/simulation/network-model_test.go +++ b/simulation/network-model_test.go @@ -1,3 +1,20 @@ +// Copyright 2018 The dexon-consensus-core Authors +// This file is part of the dexon-consensus-core library. +// +// The dexon-consensus-core 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-core 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-core library. If not, see +// <http://www.gnu.org/licenses/>. + package simulation import ( diff --git a/simulation/validator.go b/simulation/validator.go index 7397284..69ee317 100644 --- a/simulation/validator.go +++ b/simulation/validator.go @@ -18,6 +18,7 @@ package simulation import ( + "fmt" "time" "github.com/dexon-foundation/dexon-consensus-core/blockdb" @@ -31,13 +32,15 @@ import ( type Validator struct { network Network app *SimApp + gov *simGov + db blockdb.BlockDatabase config config.Validator msgChannel chan interface{} isFinished chan struct{} ID types.ValidatorID - lattice *core.BlockLattice + consensus *core.Consensus compactionChain *core.BlockChain genesis *types.Block @@ -49,18 +52,19 @@ func NewValidator( id types.ValidatorID, config config.Validator, network Network) *Validator { - app := NewSimApp(id, network) - db, err := blockdb.NewMemBackedBlockDB() + + db, err := blockdb.NewMemBackedBlockDB( + id.String() + ".blockdb") if err != nil { panic(err) } - lattice := core.NewBlockLattice(db, app) return &Validator{ ID: id, config: config, network: network, - app: app, - lattice: lattice, + app: NewSimApp(id, network), + gov: newSimGov(config.Num), + db: db, isFinished: make(chan struct{}), } } @@ -84,6 +88,9 @@ func (v *Validator) Run() { // Blocks forever. <-isStopped + if err := v.db.Close(); err != nil { + fmt.Println(err) + } v.network.NotifyServer(Message{ Type: shutdownAck, }) @@ -110,15 +117,36 @@ func (v *Validator) CheckServerInfo(isShutdown chan struct{}) { // MsgServer listen to the network channel for message and handle it. func (v *Validator) MsgServer() { + var pendingBlocks []*types.Block for { msg := <-v.msgChannel switch val := msg.(type) { case *types.Block: - //if val.ProposerID.Equal(v.ID) { - // continue - //} - v.lattice.ProcessBlock(val, true) + if v.consensus != nil { + if err := v.consensus.ProcessBlock(val); err != nil { + fmt.Println(err) + //panic(err) + } + } else { + pendingBlocks = append(pendingBlocks, val) + if val.ParentHash == val.Hash { + v.gov.addValidator(val.ProposerID) + } + validatorSet := v.gov.GetValidatorSet() + if len(validatorSet) != v.config.Num { + // We don't collect all validators yet. + break + } + v.consensus = core.NewConsensus(v.app, v.gov, v.db) + for _, b := range pendingBlocks { + if err := v.consensus.ProcessBlock(b); err != nil { + fmt.Println(err) + //panic(err) + } + } + pendingBlocks = pendingBlocks[:0] + } } } } @@ -129,34 +157,26 @@ func (v *Validator) BroadcastGenesisBlock() { for v.network.NumPeers() != v.config.Num { time.Sleep(time.Second) } - - if v.genesis == nil { - hash := common.NewRandomHash() - b := &types.Block{ - ProposerID: v.ID, - ParentHash: hash, - Hash: hash, - Height: 0, - Acks: map[common.Hash]struct{}{}, - } - v.genesis = b - v.current = b - - v.lattice.AddValidator(v.ID, b) - v.lattice.SetOwner(v.ID) - - v.lattice.PrepareBlock(b) - v.network.BroadcastBlock(b) + hash := common.NewRandomHash() + b := &types.Block{ + ProposerID: v.ID, + ParentHash: hash, + Hash: hash, + Height: 0, + Acks: map[common.Hash]struct{}{}, + Timestamps: map[types.ValidatorID]time.Time{ + v.ID: time.Now().UTC(), + }, } + v.network.BroadcastBlock(b) } // BlockProposer propose blocks to be send to the DEXON network. func (v *Validator) BlockProposer(isStopped, isShutdown chan struct{}) { - // Wait until all peer knows each other. - for len(v.lattice.ValidatorSet) != v.config.Num { + // Wait until all genesis blocks are received. + for v.consensus == nil { time.Sleep(time.Second) } - model := &NormalNetwork{ Sigma: v.config.ProposeIntervalSigma, Mean: v.config.ProposeIntervalMean, @@ -167,13 +187,15 @@ ProposingBlockLoop: block := &types.Block{ ProposerID: v.ID, - ParentHash: v.current.Hash, Hash: common.NewRandomHash(), - Height: v.current.Height + 1., - Acks: map[common.Hash]struct{}{}, } - v.current = block - v.lattice.PrepareBlock(block) + if err := v.consensus.PrepareBlock(block); err != nil { + panic(err) + } + if err := v.consensus.ProcessBlock(block); err != nil { + fmt.Println(err) + //panic(err) + } v.network.BroadcastBlock(block) select { case <-isShutdown: |