protocol

package
v0.22.9-patch-1-epoch-... Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 21, 2021 License: AGPL-3.0 Imports: 8 Imported by: 55

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrNoPreviousEpoch is a sentinel error returned when a previous epoch is
	// queried from a snapshot within the first epoch after the root block.
	ErrNoPreviousEpoch = fmt.Errorf("no previous epoch exists")

	// ErrNextEpochNotSetup is a sentinel error returned when the next epoch
	// has not been set up yet.
	ErrNextEpochNotSetup = fmt.Errorf("next epoch has not yet been set up")

	// ErrEpochNotCommitted is a sentinel error returned when the epoch has
	// not been committed and information is queried that is only accessible
	// in the EpochCommitted phase.
	ErrEpochNotCommitted = fmt.Errorf("queried info from EpochCommit event before it was emitted")
)

Functions

func CheckNodeStatusAt added in v0.17.0

func CheckNodeStatusAt(snapshot Snapshot, id flow.Identifier, checks ...flow.IdentityFilter) (bool, error)

CheckNodeStatusAt returns whether or not the node with the given ID is a valid identity at the given state snapshot, and satisfies all checks.

func DKGPhaseViews added in v0.20.0

func DKGPhaseViews(epoch Epoch) (phase1FinalView uint64, phase2FinalView uint64, phase3FinalView uint64, err error)

DKGPhaseViews returns the DKG final phase views for an epoch.

func GetDKGParticipantKeys added in v0.17.0

func GetDKGParticipantKeys(dkg DKG, participants flow.IdentityList) ([]crypto.PublicKey, error)

GetDKGParticipantKeys retrieves the canonically ordered list of DKG participant keys from the DKG.

func IsIdentityNotFound

func IsIdentityNotFound(err error) bool

func IsInvalidBlockTimestampError added in v0.20.0

func IsInvalidBlockTimestampError(err error) bool

func IsNodeStakedAt added in v0.16.0

func IsNodeStakedAt(snapshot Snapshot, id flow.Identifier) (bool, error)

IsNodeStakedAt returns whether or not the node with the given ID is a valid staked, un-ejected node as of the given state snapshot.

func IsNodeStakedWithRoleAt added in v0.17.0

func IsNodeStakedWithRoleAt(snapshot Snapshot, id flow.Identifier, role flow.Role) (bool, error)

IsNodeStakedWithRoleAt returns whether or not the node with the given ID is a valid staked, un-ejected node with the specified role as of the given state snapshot.

func NewInvalidBlockTimestamp added in v0.20.0

func NewInvalidBlockTimestamp(msg string, args ...interface{}) error

func ToDKGParticipantLookup added in v0.15.0

func ToDKGParticipantLookup(dkg DKG, participants flow.IdentityList) (map[flow.Identifier]flow.DKGParticipant, error)

ToDKGParticipantLookup computes the nodeID -> DKGParticipant lookup for a DKG instance. The participants must exactly match the DKG instance configuration.

func ToEpochCommit added in v0.15.0

func ToEpochCommit(epoch Epoch) (*flow.EpochCommit, error)

ToEpochCommit converts an Epoch interface instance to the underlying concrete epoch commit service event. The epoch must have been committed.

func ToEpochSetup added in v0.15.0

func ToEpochSetup(epoch Epoch) (*flow.EpochSetup, error)

ToEpochSetup converts an Epoch interface instance to the underlying concrete epoch setup service event.

Types

type BlockTimer added in v0.20.0

type BlockTimer interface {
	// Build generates a timestamp based on definition of valid timestamp.
	Build(parentTimestamp time.Time) time.Time
	// Validate checks validity of a block's time stamp.
	// Error returns
	//  * `model.InvalidBlockTimestampError` if time stamp is invalid.
	//  * all other errors are unexpected and potentially symptoms of internal implementation bugs or state corruption (fatal).
	Validate(parentTimestamp, currentTimestamp time.Time) error
}

BlockTimer constructs and validates block timestamps.

type Cluster

type Cluster interface {

	// Index returns the index for this cluster.
	Index() uint

	// ChainID returns chain ID for the cluster's chain.
	ChainID() flow.ChainID

	// EpochCounter returns the epoch counter for this cluster.
	EpochCounter() uint64

	// Members returns the initial set of collector nodes in this cluster.
	Members() flow.IdentityList

	// RootBlock returns the root block for this cluster.
	RootBlock() *cluster.Block

	// RootQC returns the quorum certificate for this cluster.
	RootQC() *flow.QuorumCertificate
}

Cluster represents the detailed information for a particular cluster, for a given epoch. This information represents the INITIAL state of the cluster, as defined by the Epoch Preparation Protocol. It DOES NOT take into account state changes over the course of the epoch (ie. slashing).

type Consumer

type Consumer interface {

	// BlockFinalized is called when a block is finalized.
	// Formally, this callback is informationally idempotent. I.e. the consumer
	// of this callback must handle repeated calls for the same block.
	BlockFinalized(block *flow.Header)

	// BlockProcessable is called when a correct block is encountered
	// that is ready to be processed (i.e. it is connected to the finalized
	// chain and its source of randomness is available).
	// Formally, this callback is informationally idempotent. I.e. the consumer
	// of this callback must handle repeated calls for the same block.
	BlockProcessable(block *flow.Header)

	// EpochTransition is called when we transition to a new epoch. This is
	// equivalent to the beginning of the new epoch's staking phase and the end
	// of the previous epoch's epoch committed phase.
	//
	// The block parameter is the first block of the new epoch.
	//
	// NOTE: Only called once the transition has been finalized.
	EpochTransition(newEpochCounter uint64, first *flow.Header)

	// EpochSetupPhaseStarted is called when we begin the epoch setup phase for
	// the current epoch. This is equivalent to the end of the epoch staking
	// phase for the current epoch.
	//
	// Referencing the diagram below, the event is emitted when block c is incorporated.
	// The block parameter is the first block of the epoch setup phase (block c).
	//
	// |<-- Epoch N ------------------------------------------------->|
	// |<-- StakingPhase -->|<-- SetupPhase -->|<-- CommittedPhase -->|
	//                    ^--- block A - this block's execution result contains an EpochSetup event
	//                      ^--- block b - contains seal for block A
	//                         ^--- block c - contains qc for block b, first block of Setup phase
	//                           ^--- block d - finalizes block c, triggers EpochSetupPhaseStarted event
	//
	// NOTE: Only called once the phase transition has been finalized.
	EpochSetupPhaseStarted(currentEpochCounter uint64, first *flow.Header)

	// EpochCommittedPhaseStarted is called when we begin the epoch committed phase
	// for the current epoch. This is equivalent to the end of the epoch setup
	// phase for the current epoch.
	//
	// Referencing the diagram below, the event is emitted when block f is received.
	// The block parameter is the first block of the epoch committed phase (block f).
	//
	// |<-- Epoch N ------------------------------------------------->|
	// |<-- StakingPhase -->|<-- SetupPhase -->|<-- CommittedPhase -->|
	//                                       ^--- block D - this block's execution result contains an EpochCommit event
	//                                         ^--- block e - contains seal for block D
	//                                            ^--- block f - contains qc for block e, first block of Committed phase
	//                                              ^--- block g - finalizes block f, triggers EpochCommittedPhaseStarted event
	///
	//
	// NOTE: Only called once the phase transition has been finalized.
	EpochCommittedPhaseStarted(currentEpochCounter uint64, first *flow.Header)
}

Consumer defines a set of events that occur within the protocol state, that can be propagated to other components via an implementation of this interface. Consumer implementations must be non-blocking.

NOTE: the epoch-related callbacks are only called once the fork containing the relevant event has been finalized.

type DKG

type DKG interface {

	// Size is the number of members in the DKG.
	Size() uint

	// GroupKey is the group public key.
	GroupKey() crypto.PublicKey

	// Index returns the index for the given node.
	Index(nodeID flow.Identifier) (uint, error)

	// KeyShare returns the public key share for the given node.
	KeyShare(nodeID flow.Identifier) (crypto.PublicKey, error)
}

DKG represents the result of running the distributed key generation procedure for the random beacon.

type Epoch

type Epoch interface {

	// Counter returns the Epoch's counter.
	Counter() (uint64, error)

	// FirstView returns the first view of this epoch.
	FirstView() (uint64, error)

	// DKGPhase1FinalView returns the final view of DKG phase 1
	DKGPhase1FinalView() (uint64, error)

	// DKGPhase2FinalView returns the final view of DKG phase 2
	DKGPhase2FinalView() (uint64, error)

	// DKGPhase3FinalView returns the final view of DKG phase 3
	DKGPhase3FinalView() (uint64, error)

	// FinalView returns the largest view number which still belongs to this epoch.
	FinalView() (uint64, error)

	// RandomSource returns the underlying random source of this epoch.
	RandomSource() ([]byte, error)

	// Seed generates a random seed using the source of randomness for this
	// epoch, specified in the EpochSetup service event.
	Seed(indices ...uint32) ([]byte, error)

	// InitialIdentities returns the identities for this epoch as they were
	// specified in the EpochSetup service event.
	InitialIdentities() (flow.IdentityList, error)

	// Clustering returns the cluster assignment for this epoch.
	Clustering() (flow.ClusterList, error)

	// Cluster returns the detailed cluster information for the cluster with the
	// given index, in this epoch.
	Cluster(index uint) (Cluster, error)

	// DKG returns the result of the distributed key generation procedure.
	DKG() (DKG, error)
}

Epoch contains the information specific to a certain Epoch (defined by the epoch Counter). Note that the Epoch preparation can differ along different forks, since the emission of service events is fork-dependent. Therefore, an epoch exists RELATIVE to the snapshot from which it was queried.

CAUTION: Clients must ensure to query epochs only for finalized blocks to ensure they query finalized epoch information.

An Epoch instance is constant and reports the identical information even if progress is made later and more information becomes available in subsequent blocks.

Methods error if epoch preparation has not progressed far enough for this information to be determined by a finalized block.

type EpochQuery

type EpochQuery interface {

	// Current returns the current epoch as of this snapshot. All valid snapshots
	// have a current epoch.
	Current() Epoch

	// Next returns the next epoch as of this snapshot. Valid snapshots must
	// have a next epoch available after the transition to epoch setup phase.
	Next() Epoch

	// Previous returns the previous epoch as of this snapshot. Valid snapshots
	// must have a previous epoch for all epochs except that immediately after
	// the root block - in other words, if a previous epoch exists, implementations
	// must arrange to expose it here.
	//
	// Returns ErrNoPreviousEpoch in the case that this method is queried w.r.t.
	// a snapshot from the first epoch after the root block.
	Previous() Epoch
}

EpochQuery defines the different ways to query for epoch information given a Snapshot. It only exists to simplify the main Snapshot interface.

type IdentityNotFoundError added in v0.13.0

type IdentityNotFoundError struct {
	NodeID flow.Identifier
}

func (IdentityNotFoundError) Error added in v0.13.0

func (e IdentityNotFoundError) Error() string

type InvalidBlockTimestampError added in v0.20.0

type InvalidBlockTimestampError struct {
	// contains filtered or unexported fields
}

func (InvalidBlockTimestampError) Error added in v0.20.0

func (InvalidBlockTimestampError) Unwrap added in v0.20.0

func (e InvalidBlockTimestampError) Unwrap() error

type MutableState added in v0.14.0

type MutableState interface {
	State
	// Extend introduces the block with the given ID into the persistent
	// protocol state without modifying the current finalized state. It allows
	// us to execute fork-aware queries against ambiguous protocol state, while
	// still checking that the given block is a valid extension of the protocol
	// state. Depending on implementation it might be a lighter version that checks only
	// block header.
	Extend(ctx context.Context, candidate *flow.Block) error

	// Finalize finalizes the block with the given hash.
	// At this level, we can only finalize one block at a time. This implies
	// that the parent of the pending block that is to be finalized has
	// to be the last finalized block.
	// It modifies the persistent immutable protocol state accordingly and
	// forwards the pointer to the latest finalized state.
	Finalize(ctx context.Context, blockID flow.Identifier) error

	// MarkValid marks the block header with the given block hash as valid.
	// At this level, we can only mark one block at a time as valid. This
	// implies that the parent of the block to be marked as valid
	// has to be already valid.
	// It modifies the persistent immutable protocol state accordingly.
	MarkValid(blockID flow.Identifier) error
}

type Params

type Params interface {

	// ChainID returns the chain ID for the current consensus state.
	ChainID() (flow.ChainID, error)

	// Root returns the root header of the current consensus state.
	Root() (*flow.Header, error)

	// Seal returns the root block seal of the current consensus state.
	Seal() (*flow.Seal, error)
}

type Snapshot

type Snapshot interface {

	// Head returns the latest block at the selected point of the protocol state
	// history. It can represent either a finalized or ambiguous block,
	// depending on our selection criteria. Either way, it's the block on which
	// we should build the next block in the context of the selected state.
	Head() (*flow.Header, error)

	// QuorumCertificate returns a valid quorum certificate for the header at
	// this snapshot, if one exists.
	QuorumCertificate() (*flow.QuorumCertificate, error)

	// Identities returns a list of identities at the selected point of the
	// protocol state history. At the beginning of an epoch, this list includes
	// identities from the previous epoch that are un-staking during the current
	// epoch. At the end of an epoch, this includes identities scheduled to join
	// in the next epoch but are not active yet.
	//
	// Identities are guaranteed to be returned in canonical order (order.Canonical).
	//
	// It allows us to provide optional upfront filters which can be used by the
	// implementation to speed up database lookups.
	Identities(selector flow.IdentityFilter) (flow.IdentityList, error)

	// Identity attempts to retrieve the node with the given identifier at the
	// selected point of the protocol state history. It will error if it doesn't exist.
	Identity(nodeID flow.Identifier) (*flow.Identity, error)

	// SealedResult returns the most recent included seal as of this block and
	// the corresponding execution result. The seal may have been included in a
	// parent block, if this block is empty. If this block contains multiple
	// seals, this returns the seal for the block with the greatest height.
	SealedResult() (*flow.ExecutionResult, *flow.Seal, error)

	// Commit returns the state commitment of the most recently included seal
	// as of this block. It represents the sealed state.
	Commit() (flow.StateCommitment, error)

	// SealingSegment returns the chain segment such that the head (greatest
	// height) is this snapshot's reference block and the tail (least height)
	// is the most recently sealed block as of this snapshot (ie. the block
	// referenced by LatestSeal). The segment is in ascending height order.
	//
	// TAIL <- B1 <- ... <- BN <- HEAD
	//
	// NOTE 1: TAIL is not always sealed by HEAD. In the case that the head of
	// the snapshot contains no seals, TAIL must be sealed by the first ancestor
	// of HEAD which contains any seal.
	//
	// NOTE 2: In the special case of a root snapshot generated for a spork,
	// the sealing segment has exactly one block (the root block for the spork).
	// For all other snapshots, the sealing segment contains at least 2 blocks.
	//
	SealingSegment() ([]*flow.Block, error)

	// Descendants returns the IDs of all descendants of the Head block. The IDs
	// are ordered such that parents are included before their children. These
	// are NOT guaranteed to have been validated by HotStuff.
	Descendants() ([]flow.Identifier, error)

	// ValidDescendants returns the IDs of all descendants of the Head block.
	// The IDs are ordered such that parents are included before their children. Includes
	// only blocks that have been validated by HotStuff.
	ValidDescendants() ([]flow.Identifier, error)

	// Seed returns a deterministic seed for a pseudo random number generator.
	// The seed is derived from the source of randomness for the Head block.
	// In order to deterministically derive task specific seeds, indices must
	// be specified. Refer to module/indices/rand.go for different indices.
	// NOTE: not to be confused with the epoch source of randomness!
	// error returns:
	//  * NoValidChildBlockError indicates that no valid child block is known
	//    (which contains the block's source of randomness)
	//  * unexpected errors should be considered symptoms of internal bugs
	Seed(indices ...uint32) ([]byte, error)

	// Phase returns the epoch phase for the current epoch, as of the Head block.
	Phase() (flow.EpochPhase, error)

	// Epochs returns a query object enabling querying detailed information about
	// various epochs.
	//
	// For epochs that are in the future w.r.t. the Head block, some of Epoch's
	// methods may return errors, since the Epoch Preparation Protocol may be
	// in-progress and incomplete for the epoch.
	Epochs() EpochQuery
}

Snapshot represents an immutable snapshot of the protocol state at a specific block, denoted as the Head block. The Snapshot is fork-specific and only accounts for the information contained in blocks along this fork up to (including) Head. It allows us to read the parameters at the selected block in a deterministic manner.

type State

type State interface {

	// Params gives access to a number of stable parameters of the protocol state.
	Params() Params

	// Final returns the snapshot of the persistent protocol state at the latest
	// finalized block, and the returned snapshot is therefore immutable over
	// time.
	Final() Snapshot

	// Sealed returns the snapshot of the persistent protocol state at the
	// latest sealed block, and the returned snapshot is therefore immutable
	// over time.
	Sealed() Snapshot

	// AtHeight returns the snapshot of the persistent protocol state at the
	// given block number. It is only available for finalized blocks and the
	// returned snapshot is therefore immutable over time.
	AtHeight(height uint64) Snapshot

	// AtBlockID returns the snapshot of the persistent protocol state at the
	// given block ID. It is available for any block that was introduced into
	// the protocol state, and can thus represent an ambiguous state that was or
	// will never be finalized.
	AtBlockID(blockID flow.Identifier) Snapshot
}

State represents the full protocol state of the local node. It allows us to obtain snapshots of the state at any point of the protocol state history.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL