aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/dexon-foundation/dexon-consensus/core/lattice.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/dexon-foundation/dexon-consensus/core/lattice.go')
-rw-r--r--vendor/github.com/dexon-foundation/dexon-consensus/core/lattice.go363
1 files changed, 0 insertions, 363 deletions
diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/lattice.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/lattice.go
deleted file mode 100644
index de0e54910..000000000
--- a/vendor/github.com/dexon-foundation/dexon-consensus/core/lattice.go
+++ /dev/null
@@ -1,363 +0,0 @@
-// 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 core
-
-import (
- "fmt"
- "sync"
- "time"
-
- "github.com/dexon-foundation/dexon-consensus/common"
- "github.com/dexon-foundation/dexon-consensus/core/db"
- "github.com/dexon-foundation/dexon-consensus/core/types"
- "github.com/dexon-foundation/dexon-consensus/core/utils"
-)
-
-// Errors for sanity check error.
-var (
- ErrRetrySanityCheckLater = fmt.Errorf("retry sanity check later")
-)
-
-// Lattice represents a unit to produce a global ordering from multiple chains.
-type Lattice struct {
- lock sync.RWMutex
- signer *utils.Signer
- app Application
- debug Debug
- pool blockPool
- data *latticeData
- toModule *totalOrdering
- ctModule *consensusTimestamp
- logger common.Logger
-}
-
-// NewLattice constructs an Lattice instance.
-func NewLattice(
- dMoment time.Time,
- round uint64,
- cfg *types.Config,
- signer *utils.Signer,
- app Application,
- debug Debug,
- db db.Database,
- logger common.Logger) *Lattice {
-
- // Create genesis latticeDataConfig.
- return &Lattice{
- signer: signer,
- app: app,
- debug: debug,
- pool: newBlockPool(cfg.NumChains),
- data: newLatticeData(db, dMoment, round, cfg),
- toModule: newTotalOrdering(dMoment, round, cfg),
- ctModule: newConsensusTimestamp(dMoment, round, cfg.NumChains),
- logger: logger,
- }
-}
-
-// PrepareBlock setups block's fields based on current status.
-func (l *Lattice) PrepareBlock(
- b *types.Block, proposeTime time.Time) (err error) {
-
- l.lock.RLock()
- defer l.lock.RUnlock()
-
- b.Timestamp = proposeTime
- if err = l.data.prepareBlock(b); err != nil {
- return
- }
- l.logger.Debug("Calling Application.PreparePayload", "position", &b.Position)
- if b.Payload, err = l.app.PreparePayload(b.Position); err != nil {
- return
- }
- l.logger.Debug("Calling Application.PrepareWitness",
- "height", b.Witness.Height)
- if b.Witness, err = l.app.PrepareWitness(b.Witness.Height); err != nil {
- return
- }
- err = l.signer.SignBlock(b)
- return
-}
-
-// PrepareEmptyBlock setups block's fields based on current lattice status.
-func (l *Lattice) PrepareEmptyBlock(b *types.Block) (err error) {
- l.lock.RLock()
- defer l.lock.RUnlock()
- if err = l.data.prepareEmptyBlock(b); err != nil {
- return
- }
- b.Hash, err = utils.HashBlock(b)
- return
-}
-
-// AddShallowBlock adds a hash of a block that is confirmed by other nodes but
-// the content is not arrived yet.
-func (l *Lattice) AddShallowBlock(hash common.Hash, pos types.Position) {
- l.lock.Lock()
- defer l.lock.Unlock()
- l.data.addShallowBlock(hash, pos)
-}
-
-// SanityCheck checks the validity of a block.
-//
-// If any acking block of this block does not exist, Lattice caches this block
-// and retries when Lattice.ProcessBlock is called.
-func (l *Lattice) SanityCheck(b *types.Block, allowShallow bool) (err error) {
- if b.IsEmpty() {
- // Only need to verify block's hash.
- var hash common.Hash
- if hash, err = utils.HashBlock(b); err != nil {
- return
- }
- if b.Hash != hash {
- return ErrInvalidBlock
- }
- } else {
- // Verify block's signature.
- if err = utils.VerifyBlockSignature(b); err != nil {
- return
- }
- }
- // Make sure acks are sorted.
- for i := range b.Acks {
- if i == 0 {
- continue
- }
- if !b.Acks[i-1].Less(b.Acks[i]) {
- err = ErrAcksNotSorted
- return
- }
- }
- l.lock.RLock()
- defer l.lock.RUnlock()
- if err = l.data.sanityCheck(b, allowShallow); err != nil {
- if _, ok := err.(*ErrAckingBlockNotExists); ok {
- err = ErrRetrySanityCheckLater
- }
- return
- }
- return
-}
-
-// Exist checks if the block is known to lattice.
-func (l *Lattice) Exist(hash common.Hash) bool {
- l.lock.RLock()
- defer l.lock.RUnlock()
- _, err := l.data.findBlock(hash)
- return err == nil
-}
-
-// addBlockToLattice adds a block into lattice, and delivers blocks with the
-// acks already delivered.
-//
-// NOTE: input block should pass sanity check.
-func (l *Lattice) addBlockToLattice(
- input *types.Block) (outputBlocks []*types.Block, err error) {
-
- if tip := l.data.chains[input.Position.ChainID].tip; tip != nil {
- if !input.Position.Newer(&tip.Position) {
- l.logger.Warn("Dropping block: older than tip",
- "block", input, "tip", tip)
- return
- }
- }
- l.pool.addBlock(input)
- // Check tips in pool to check their validity for moving blocks from pool
- // to lattice.
- for {
- hasOutput := false
- for i := uint32(0); i < uint32(len(l.pool)); i++ {
- var tip *types.Block
- if tip = l.pool.tip(i); tip == nil {
- continue
- }
- err = l.data.sanityCheck(tip, false)
- if err == nil {
- var output []*types.Block
- if output, err = l.data.addBlock(tip); err != nil {
- // We should be able to add this block once sanity check
- // passed.
- l.logger.Error("Failed to add sanity-checked block",
- "block", tip, "error", err)
- panic(err)
- }
- delete(l.data.shallowBlocks, tip.Hash)
- hasOutput = true
- outputBlocks = append(outputBlocks, output...)
- l.pool.removeTip(i)
- continue
- }
- if _, ok := err.(*ErrAckingBlockNotExists); ok {
- l.logger.Debug("Pending block for lattice",
- "pending", tip,
- "err", err,
- "last", l.data.chains[tip.Position.ChainID].tip)
- err = nil
- continue
- } else {
- l.logger.Error("Unexpected sanity check error",
- "block", tip, "error", err)
- panic(err)
- }
- }
- if !hasOutput {
- break
- }
- }
-
- for _, b := range outputBlocks {
- l.logger.Debug("Calling Application.BlockConfirmed", "block", b)
- l.app.BlockConfirmed(*b.Clone())
- // Purge blocks in pool with the same chainID and lower height.
- l.pool.purgeBlocks(b.Position.ChainID, b.Position.Height)
- }
-
- return
-}
-
-// ProcessBlock adds a block into lattice, and deliver ordered blocks.
-// If any block pass sanity check after this block add into lattice, they
-// would be returned, too.
-//
-// NOTE: assume the block passed sanity check.
-func (l *Lattice) ProcessBlock(
- input *types.Block) (delivered []*types.Block, err error) {
- var (
- b *types.Block
- inLattice []*types.Block
- toDelivered []*types.Block
- deliveredMode uint32
- )
- l.lock.Lock()
- defer l.lock.Unlock()
- if inLattice, err = l.addBlockToLattice(input); err != nil {
- return
- }
- if len(inLattice) == 0 {
- return
- }
- for _, b = range inLattice {
- if err = l.toModule.addBlock(b); err != nil {
- // All errors from total ordering is serious, should panic.
- panic(err)
- }
- }
- for {
- toDelivered, deliveredMode, err = l.toModule.extractBlocks()
- if err != nil {
- panic(err)
- }
- if len(toDelivered) == 0 {
- break
- }
- if l.debug != nil {
- hashes := make(common.Hashes, len(toDelivered))
- for idx := range toDelivered {
- hashes[idx] = toDelivered[idx].Hash
- }
- l.debug.TotalOrderingDelivered(hashes, deliveredMode)
- }
- // Perform consensus timestamp module.
- if err = l.ctModule.processBlocks(toDelivered); err != nil {
- break
- }
- delivered = append(delivered, toDelivered...)
- }
- return
-}
-
-// NextBlock returns expected height and timestamp of incoming block for
-// specified chain and given round.
-func (l *Lattice) NextBlock(round uint64, chainID uint32) (
- uint64, time.Time, error) {
- l.lock.RLock()
- defer l.lock.RUnlock()
- return l.data.nextBlock(round, chainID)
-}
-
-// TipRound returns the round of the tip of given chain.
-func (l *Lattice) TipRound(chainID uint32) uint64 {
- l.lock.RLock()
- defer l.lock.RUnlock()
- return l.data.tipRound(chainID)
-}
-
-// PurgeBlocks purges blocks' cache in memory, this is called when the caller
-// makes sure those blocks are already saved in db.
-func (l *Lattice) PurgeBlocks(blocks []*types.Block) error {
- l.lock.Lock()
- defer l.lock.Unlock()
- return l.data.purgeBlocks(blocks)
-}
-
-// AppendConfig adds a new config for upcoming rounds. If a config of round r is
-// added, only config in round r + 1 is allowed next.
-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
- }
- if err = l.toModule.appendConfig(round, config); err != nil {
- return
- }
- if err = l.ctModule.appendConfig(round, config); err != nil {
- return
- }
- return
-}
-
-// ProcessFinalizedBlock is used for syncing lattice data.
-func (l *Lattice) ProcessFinalizedBlock(
- b *types.Block) (delivered []*types.Block, err error) {
- var (
- toDelivered []*types.Block
- deliveredMode uint32
- )
- l.lock.Lock()
- defer l.lock.Unlock()
- // Syncing state for core.latticeData module.
- if err = l.data.addFinalizedBlock(b); err != nil {
- return
- }
- l.pool.purgeBlocks(b.Position.ChainID, b.Position.Height)
- // Syncing state for core.totalOrdering module.
- if err = l.toModule.addBlock(b); err != nil {
- return
- }
- for {
- toDelivered, deliveredMode, err = l.toModule.extractBlocks()
- if err != nil || len(toDelivered) == 0 {
- break
- }
- hashes := make(common.Hashes, len(toDelivered))
- for idx := range toDelivered {
- hashes[idx] = toDelivered[idx].Hash
- }
- if l.debug != nil {
- l.debug.TotalOrderingDelivered(hashes, deliveredMode)
- }
- // Sync core.consensusTimestamp module.
- if err = l.ctModule.processBlocks(toDelivered); err != nil {
- break
- }
- delivered = append(delivered, toDelivered...)
- }
- return
-}