protocol

package
v0.27.6 Latest Latest
Warning

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

Go to latest
Published: Sep 9, 2022 License: AGPL-3.0 Imports: 10 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")

	// ErrSealingSegmentBelowRootBlock is a sentinel error returned for queries
	// for a sealing segment below the root block.
	ErrSealingSegmentBelowRootBlock = fmt.Errorf("cannot query sealing segment below root block")

	// ErrClusterNotFound is a sentinel error returns for queries for a cluster
	ErrClusterNotFound = fmt.Errorf("could not find cluster")
)

Functions

func CheckNodeStatusAt added in v0.17.0

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

CheckNodeStatusAt returns whether the node with the given ID is a valid identity at the given state snapshot, and satisfies all checks. Expected errors during normal operations:

  • storage.ErrNotFound if snapshot references an unknown block

All other errors are unexpected and potential symptoms of internal state corruption.

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 FindGuarantors added in v0.26.1

func FindGuarantors(state State, guarantee *flow.CollectionGuarantee) ([]flow.Identifier, error)

FindGuarantors decodes the signer indices from the guarantee, and finds the guarantor identifiers from protocol state Expected Error returns during normal operations:

  • signature.InvalidSignerIndicesError if `signerIndices` does not encode a valid set of collection guarantors
  • storage.ErrNotFound if the guarantee's ReferenceBlockID is not found
  • protocol.ErrEpochNotCommitted if epoch has not been committed yet
  • protocol.ErrClusterNotFound if cluster is not found by the given chainID

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 IsInvalidServiceEventError added in v0.23.2

func IsInvalidServiceEventError(err error) bool

func IsNodeAuthorizedAt added in v0.25.0

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

IsNodeAuthorizedAt returns whether the node with the given ID is a valid un-ejected network participant as of the given state snapshot.

func IsNodeAuthorizedWithRoleAt added in v0.25.0

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

IsNodeAuthorizedWithRoleAt returns whether the node with the given ID is a valid un-ejected network participant with the specified role as of the given state snapshot. Expected errors during normal operations:

  • storage.ErrNotFound if snapshot references an unknown block

All other errors are unexpected and potential symptoms of internal state corruption.

func IsSporkRootSnapshot added in v0.23.9

func IsSporkRootSnapshot(snapshot Snapshot) (bool, error)

IsSporkRootSnapshot returns whether the given snapshot is the state snapshot representing the initial state for a spork.

func NewInvalidBlockTimestamp added in v0.20.0

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

func NewInvalidServiceEventError added in v0.23.2

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

NewInvalidServiceEventError returns an invalid service event error. Since all invalid service events indicate an invalid extension, the service event error is wrapped in the invalid extension error at construction.

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. Collectively, these are referred to as "Protocol Events".

Protocol events are guaranteed to be delivered at least once. Subscribers must handle multiple deliveries.

CAUTION: Protocol event subscriber callbacks are invoked synchronously in the critical path of protocol state mutations. Most subscribers should immediately spawn a goroutine to handle the notification to avoid blocking protocol state progression, especially for frequent protocol events (eg. BlockFinalized).

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. Error Returns:
	// protocol.IdentityNotFoundError if nodeID is not a valid DKG participant.
	Index(nodeID flow.Identifier) (uint, error)

	// KeyShare returns the public key share for the given node. Error Returns:
	// protocol.IdentityNotFoundError if nodeID is not a valid DKG participant.
	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.
	// This source is currently generated by an on-chain contract using the
	// UnsafeRandom() Cadence function.
	RandomSource() ([]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)

	// ClusterByChainID returns the detailed cluster information for the cluster with
	// the given chain ID, in this epoch
	// Expected Error returns during normal operations:
	//  * protocol.ErrEpochNotCommitted if epoch has not been committed yet
	//  * protocol.ErrClusterNotFound if cluster is not found by the given chainID
	ClusterByChainID(chainID flow.ChainID) (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 GlobalParams added in v0.23.2

type GlobalParams interface {

	// ChainID returns the chain ID for the current Flow network. The chain ID
	// uniquely identifies a Flow network in perpetuity across epochs and sporks.
	ChainID() (flow.ChainID, error)

	// SporkID returns the unique identifier for this network within the current spork.
	// This ID is determined at the beginning of a spork during bootstrapping and is
	// part of the root protocol state snapshot.
	SporkID() (flow.Identifier, error)

	// ProtocolVersion returns the protocol version, the major software version
	// of the protocol software.
	ProtocolVersion() (uint, error)
}

GlobalParams represents protocol state parameters that do not vary between instances. Any nodes running in the same spork, on the same network (same chain ID) must have the same global params.

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 InstanceParams added in v0.23.2

type InstanceParams interface {

	// Root returns the root header of the current protocol state. This will be
	// the head of the protocol state snapshot used to bootstrap this state and
	// may differ from node to node for the same protocol state.
	Root() (*flow.Header, error)

	// Seal returns the root block seal of the current protocol state. This will be
	// the seal for the root block used to bootstrap this state and may differ from
	// node to node for the same protocol state.
	Seal() (*flow.Seal, error)
}

InstanceParams represents protocol state parameters that vary between instances. For example, two nodes both running in the same spork on Flow Mainnet may have different instance params.

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 InvalidServiceEventError added in v0.23.2

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

InvalidServiceEventError indicates an invalid service event was processed.

func (InvalidServiceEventError) Error added in v0.23.2

func (e InvalidServiceEventError) Error() string

func (InvalidServiceEventError) Unwrap added in v0.23.2

func (e InvalidServiceEventError) 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.
	// Expected errors during normal operations:
	//  * state.OutdatedExtensionError if the candidate block is outdated (e.g. orphaned)
	//  * state.InvalidExtensionError if the candidate block is invalid
	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 {
	InstanceParams
	GlobalParams
}

Params are parameters of the protocol state, divided into parameters of this specific instance of the state (varies from node to node) and global parameters of the state.

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 highest block
	// is this snapshot's reference block and the lowest block
	// 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.
	//
	// NOTE 3: It is often the case that a block inside the segment will contain
	// an execution receipt in it's payload that references an execution result
	// missing from the payload. These missing execution results are stored on the
	// flow.SealingSegment.ExecutionResults field.
	SealingSegment() (*flow.SealingSegment, 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)

	// RandomSource returns the source of randomness derived from the
	// Head block.
	// 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
	RandomSource() ([]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

	// Params returns global parameters of the state this snapshot is taken from.
	Params() GlobalParams
}

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