github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/state/protocol/snapshot.go (about)

     1  package protocol
     2  
     3  import (
     4  	"github.com/onflow/flow-go/model/flow"
     5  )
     6  
     7  // Snapshot represents an immutable snapshot of the protocol state
     8  // at a specific block, denoted as the Head block.
     9  // The Snapshot is fork-specific and only accounts for the information contained
    10  // in blocks along this fork up to (including) Head.
    11  // It allows us to read the parameters at the selected block in a deterministic manner.
    12  //
    13  // TODO Epoch / Snapshot API Structure:  Currently Epoch and Snapshot APIs
    14  // are structured to allow chained queries to be used without error checking
    15  // at each call where errors might occur. Instead, errors are cached in the
    16  // resulting struct (eg. invalid.Epoch) until the query chain ends with a
    17  // function which can return an error. This has some negative effects:
    18  //  1. Cached intermediary errors result in more complex error handling
    19  //     a) each final call of the chained query needs to handle all intermediary errors, every time
    20  //     b) intermediary errors must be handled by dependencies on the final call of the query chain (eg. conversion functions)
    21  //  2. The error caching pattern encourages potentially dangerous snapshot query patterns
    22  //
    23  // See https://github.com/dapperlabs/flow-go/issues/6368 for details and proposal
    24  //
    25  // A snapshot with an unknown reference block will return state.ErrUnknownSnapshotReference for all methods.
    26  //
    27  // TODO document error returns
    28  type Snapshot interface {
    29  
    30  	// Head returns the latest block at the selected point of the protocol state
    31  	// history. It can represent either a finalized or ambiguous block,
    32  	// depending on our selection criteria. Either way, it's the block on which
    33  	// we should build the next block in the context of the selected state.
    34  	// TODO document error returns
    35  	Head() (*flow.Header, error)
    36  
    37  	// QuorumCertificate returns a valid quorum certificate for the header at
    38  	// this snapshot, if one exists.
    39  	// Expected error returns:
    40  	//   - storage.ErrNotFound is returned if the QC is unknown.
    41  	//   - state.ErrUnknownSnapshotReference if the snapshot reference block is unknown
    42  	// All other errors should be treated as exceptions.
    43  	QuorumCertificate() (*flow.QuorumCertificate, error)
    44  
    45  	// Identities returns a list of identities at the selected point of the
    46  	// protocol state history. At the beginning of an epoch, this list includes
    47  	// identities from the previous epoch that are un-staking during the current
    48  	// epoch. At the end of an epoch, this includes identities scheduled to join
    49  	// in the next epoch but are not active yet.
    50  	//
    51  	// Identities are guaranteed to be returned in canonical order (flow.Canonical[flow.Identity]).
    52  	//
    53  	// It allows us to provide optional upfront filters which can be used by the
    54  	// implementation to speed up database lookups.
    55  	// TODO document error returns
    56  	Identities(selector flow.IdentityFilter[flow.Identity]) (flow.IdentityList, error)
    57  
    58  	// Identity attempts to retrieve the node with the given identifier at the
    59  	// selected point of the protocol state history. It will error if it doesn't exist.
    60  	// TODO document error returns
    61  	Identity(nodeID flow.Identifier) (*flow.Identity, error)
    62  
    63  	// SealedResult returns the most recent included seal as of this block and
    64  	// the corresponding execution result. The seal may have been included in a
    65  	// parent block, if this block is empty. If this block contains multiple
    66  	// seals, this returns the seal for the block with the greatest height.
    67  	// TODO document error returns
    68  	SealedResult() (*flow.ExecutionResult, *flow.Seal, error)
    69  
    70  	// Commit returns the state commitment of the most recently included seal
    71  	// as of this block. It represents the sealed state.
    72  	// TODO document error returns
    73  	Commit() (flow.StateCommitment, error)
    74  
    75  	// SealingSegment returns the chain segment such that the highest block
    76  	// is this snapshot's reference block and the lowest block
    77  	// is the most recently sealed block as of this snapshot (ie. the block
    78  	// referenced by LatestSeal). The segment is in ascending height order.
    79  	//
    80  	// TAIL <- B1 <- ... <- BN <- HEAD
    81  	//
    82  	// NOTE 1: TAIL is not always sealed by HEAD. In the case that the head of
    83  	// the snapshot contains no seals, TAIL must be sealed by the first ancestor
    84  	// of HEAD which contains any seal.
    85  	//
    86  	// NOTE 2: In the special case of a root snapshot generated for a spork,
    87  	// the sealing segment has exactly one block (the root block for the spork).
    88  	// For all other snapshots, the sealing segment contains at least 2 blocks.
    89  	//
    90  	// NOTE 3: It is often the case that a block inside the segment will contain
    91  	// an execution receipt in its payload that references an execution result
    92  	// missing from the payload. These missing execution results are stored on the
    93  	// flow.SealingSegment.ExecutionResults field.
    94  	// Expected errors during normal operations:
    95  	//  - protocol.ErrSealingSegmentBelowRootBlock if sealing segment would stretch beyond the node's local history cut-off
    96  	//  - protocol.UnfinalizedSealingSegmentError if sealing segment would contain unfinalized blocks (including orphaned blocks)
    97  	//  - state.ErrUnknownSnapshotReference if the snapshot reference block is unknown
    98  	SealingSegment() (*flow.SealingSegment, error)
    99  
   100  	// Descendants returns the IDs of all descendants of the Head block.
   101  	// The IDs are ordered such that parents are included before their children.
   102  	// Since all blocks are fully validated before being inserted to the state,
   103  	// all returned blocks are validated.
   104  	// No errors are expected under normal operation.
   105  	Descendants() ([]flow.Identifier, error)
   106  
   107  	// RandomSource returns the source of randomness _for_ the snapshot's Head block.
   108  	// Note that the source of randomness for a block `H`, is contained in the
   109  	// QuorumCertificate [QC] for block `H` (QCs for H are distributed as part of child
   110  	// blocks, timeout messages or timeout certificates). While there might be different
   111  	// QCs for block H, they all yield exactly the same source of randomness (feature of
   112  	// threshold signatures used here). Therefore, it is a possibility that there is no
   113  	// QC known (yet) for the head block.
   114  	// NOTE: not to be confused with the epoch source of randomness!
   115  	// Expected error returns:
   116  	//  - storage.ErrNotFound is returned if the QC is unknown.
   117  	//  - state.ErrUnknownSnapshotReference if the snapshot reference block is unknown
   118  	// All other errors should be treated as exceptions.
   119  	RandomSource() ([]byte, error)
   120  
   121  	// Phase returns the epoch phase for the current epoch, as of the Head block.
   122  	// TODO document error returns
   123  	Phase() (flow.EpochPhase, error)
   124  
   125  	// Epochs returns a query object enabling querying detailed information about
   126  	// various epochs.
   127  	//
   128  	// For epochs that are in the future w.r.t. the Head block, some of Epoch's
   129  	// methods may return errors, since the Epoch Preparation Protocol may be
   130  	// in-progress and incomplete for the epoch.
   131  	// Returns invalid.Epoch with state.ErrUnknownSnapshotReference if snapshot reference block is unknown.
   132  	Epochs() EpochQuery
   133  
   134  	// Params returns global parameters of the state this snapshot is taken from.
   135  	// Returns invalid.Params with state.ErrUnknownSnapshotReference if snapshot reference block is unknown.
   136  	Params() GlobalParams
   137  
   138  	// EpochProtocolState returns the epoch part of dynamic protocol state that the Head block commits to.
   139  	// The compliance layer guarantees that only valid blocks are appended to the protocol state.
   140  	// Returns state.ErrUnknownSnapshotReference if snapshot reference block is unknown.
   141  	// All other errors should be treated as exceptions.
   142  	EpochProtocolState() (DynamicProtocolState, error)
   143  
   144  	// ProtocolState returns the dynamic protocol state that the Head block commits to.
   145  	// The compliance layer guarantees that only valid blocks are appended to the protocol state.
   146  	// Returns state.ErrUnknownSnapshotReference if snapshot reference block is unknown.
   147  	// All other errors should be treated as exceptions.
   148  	ProtocolState() (KVStoreReader, error)
   149  
   150  	// VersionBeacon returns the latest sealed version beacon.
   151  	// If no version beacon has been sealed so far during the current spork, returns nil.
   152  	// The latest VersionBeacon is only updated for finalized blocks. This means that, when
   153  	// querying an un-finalized fork, `VersionBeacon` will have the same value as querying
   154  	// the snapshot for the latest finalized block, even if a newer version beacon is included
   155  	// in a seal along the un-finalized fork.
   156  	VersionBeacon() (*flow.SealedVersionBeacon, error)
   157  }