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 /core/consensus.go | |
parent | a418ea95c0f5afb50cbb78aedecc68373353d06e (diff) | |
download | dexon-consensus-295c7b5efbc36f59e3ae8d10bc3abc3a5d17e785.tar dexon-consensus-295c7b5efbc36f59e3ae8d10bc3abc3a5d17e785.tar.gz dexon-consensus-295c7b5efbc36f59e3ae8d10bc3abc3a5d17e785.tar.bz2 dexon-consensus-295c7b5efbc36f59e3ae8d10bc3abc3a5d17e785.tar.lz dexon-consensus-295c7b5efbc36f59e3ae8d10bc3abc3a5d17e785.tar.xz 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 'core/consensus.go')
-rw-r--r-- | core/consensus.go | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/core/consensus.go b/core/consensus.go new file mode 100644 index 0000000..6a97e9e --- /dev/null +++ b/core/consensus.go @@ -0,0 +1,130 @@ +// 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 core + +import ( + "sync" + "time" + + "github.com/dexon-foundation/dexon-consensus-core/blockdb" + "github.com/dexon-foundation/dexon-consensus-core/core/types" +) + +// Consensus implements DEXON Consensus algorithm. +type Consensus struct { + app Application + gov Governance + rbModule *reliableBroadcast + toModule *totalOrdering + ctModule *consensusTimestamp + db blockdb.BlockDatabase + lock sync.RWMutex +} + +// NewConsensus construct an Consensus instance. +func NewConsensus( + app Application, + gov Governance, + db blockdb.BlockDatabase) *Consensus { + + validatorSet := gov.GetValidatorSet() + + // Setup acking by information returned from Governace. + rb := newReliableBroadcast() + for vID := range validatorSet { + rb.addValidator(vID) + } + + // Setup sequencer by information returned from Governace. + // TODO(mission): the value of 'K' should be in governace. + // TODO(mission): the ratio of 'phi' should be in governance. + to := newTotalOrdering( + 0, + uint64(2*(len(validatorSet)-1)/3+1), + uint64(len(validatorSet))) + + return &Consensus{ + rbModule: rb, + toModule: to, + ctModule: newConsensusTimestamp(), + app: app, + gov: gov, + db: db, + } +} + +// ProcessBlock is the entry point to submit one block to a Consensus instance. +func (con *Consensus) ProcessBlock(b *types.Block) (err error) { + var ( + deliveredBlocks []*types.Block + earlyDelivered bool + ) + // To avoid application layer modify the content of block during + // processing, we should always operate based on the cloned one. + b = b.Clone() + + con.lock.Lock() + defer con.lock.Unlock() + // Perform reliable broadcast checking. + if err = con.rbModule.processBlock(b); err != nil { + return err + } + for _, b := range con.rbModule.extractBlocks() { + // Notify application layer that some block is strongly acked. + con.app.StronglyAcked(b.Hash) + // Perform total ordering. + deliveredBlocks, earlyDelivered, err = con.toModule.processBlock(b) + if err != nil { + return + } + if len(deliveredBlocks) == 0 { + continue + } + for _, b := range deliveredBlocks { + if err = con.db.Put(*b); err != nil { + return + } + } + // TODO(mission): handle membership events here. + // TODO(mission): return block hash instead of whole block here. + con.app.TotalOrderingDeliver(deliveredBlocks, earlyDelivered) + // Perform timestamp generation. + deliveredBlocks, _, err = con.ctModule.processBlocks( + deliveredBlocks) + if err != nil { + return + } + for _, b := range deliveredBlocks { + if err = con.db.Update(*b); err != nil { + return + } + con.app.DeliverBlock(b.Hash, b.ConsensusInfo.Timestamp) + } + } + return +} + +// PrepareBlock would setup header fields of block based on its ProposerID. +func (con *Consensus) PrepareBlock(b *types.Block) (err error) { + con.lock.RLock() + defer con.lock.RUnlock() + + con.rbModule.prepareBlock(b) + b.Timestamps[b.ProposerID] = time.Now().UTC() + return +} |