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

     1  package protocol
     2  
     3  import (
     4  	"github.com/onflow/flow-go/model/flow"
     5  	"github.com/onflow/flow-go/storage/badger/transaction"
     6  )
     7  
     8  // InitialProtocolState returns constant data for given epoch.
     9  // This interface can be only obtained for epochs that have progressed to epoch commit event.
    10  type InitialProtocolState interface {
    11  	// Epoch returns counter of epoch.
    12  	Epoch() uint64
    13  	// Clustering returns initial clustering from epoch setup.
    14  	// No errors are expected during normal operations.
    15  	Clustering() (flow.ClusterList, error)
    16  	// EpochSetup returns original epoch setup event that was used to initialize the protocol state.
    17  	EpochSetup() *flow.EpochSetup
    18  	// EpochCommit returns original epoch commit event that was used to update the protocol state.
    19  	EpochCommit() *flow.EpochCommit
    20  	// DKG returns information about DKG that was obtained from EpochCommit event.
    21  	// No errors are expected during normal operations.
    22  	DKG() (DKG, error)
    23  	// Entry Returns low-level protocol state entry that was used to initialize this object.
    24  	// It shouldn't be used by high-level logic, it is useful for some cases such as bootstrapping.
    25  	// Prefer using other methods to access protocol state.
    26  	Entry() *flow.RichProtocolStateEntry
    27  }
    28  
    29  // DynamicProtocolState extends the InitialProtocolState with data that can change from block to block.
    30  // It can be used to access the identity table at given block.
    31  type DynamicProtocolState interface {
    32  	InitialProtocolState
    33  
    34  	// InvalidEpochTransitionAttempted denotes whether an invalid epoch state transition was attempted
    35  	// on the fork ending this block. Once the first block where this flag is true is finalized, epoch
    36  	// fallback mode is triggered.
    37  	// TODO for 'leaving Epoch Fallback via special service event': at the moment, this is a one-way transition and requires a spork to recover - need to revisit for sporkless EFM recovery
    38  	InvalidEpochTransitionAttempted() bool
    39  	// PreviousEpochExists returns true if a previous epoch exists. This is true for all epoch
    40  	// except those immediately following a spork.
    41  	PreviousEpochExists() bool
    42  	// EpochPhase returns the epoch phase for the current epoch.
    43  	EpochPhase() flow.EpochPhase
    44  
    45  	// Identities returns identities (in canonical ordering) that can participate in the current or previous
    46  	// or next epochs. Let P be the set of identities in the previous epoch, C be the set of identities in
    47  	// the current epoch, and N be the set of identities in the next epoch.
    48  	// The set of authorized identities this function returns is different depending on epoch state:
    49  	// EpochStaking phase:
    50  	//   - nodes in C with status `flow.EpochParticipationStatusActive`
    51  	//   - nodes in P-C with status `flow.EpochParticipationStatusLeaving`
    52  	// EpochSetup/EpochCommitted phase:
    53  	//   - nodes in C with status `flow.EpochParticipationStatusActive`
    54  	//   - nodes in N-C with status `flow.EpochParticipationStatusJoining`
    55  	Identities() flow.IdentityList
    56  	// GlobalParams returns params that are same for all nodes in the network.
    57  	GlobalParams() GlobalParams
    58  }
    59  
    60  // ProtocolState is the read-only interface for protocol state, it allows to query information
    61  // on a per-block and per-epoch basis.
    62  type ProtocolState interface {
    63  	// ByEpoch returns an object with static protocol state information by epoch number.
    64  	// To be able to use this interface we need to observe both epoch setup and commit events.
    65  	// Not available for next epoch unless we have observed an EpochCommit event.
    66  	// No errors are expected during normal operations.
    67  	// TODO(yuraolex): check return types
    68  	// TODO(yuraolex): decide if we really need this approach. It's unclear if it's useful to query
    69  	//  by epoch counter. To implement it we need an additional index by epoch counter. Alternatively we need a way to map
    70  	//  epoch counter -> block ID. It gets worse if we consider that we need a way to get the epoch counter itself at caller side.
    71  	//ByEpoch(epoch uint64) (InitialProtocolState, error)
    72  
    73  	// AtBlockID returns epoch protocol state at block ID.
    74  	// The resulting epoch protocol state is returned AFTER applying updates that are contained in block.
    75  	// Can be queried for any block that has been added to the block tree.
    76  	// Returns:
    77  	// - (DynamicProtocolState, nil) - if there is an epoch protocol state associated with given block ID.
    78  	// - (nil, storage.ErrNotFound) - if there is no epoch protocol state associated with given block ID.
    79  	// - (nil, exception) - any other error should be treated as exception.
    80  	AtBlockID(blockID flow.Identifier) (DynamicProtocolState, error)
    81  
    82  	// KVStoreAtBlockID returns protocol state at block ID.
    83  	// The resulting protocol state is returned AFTER applying updates that are contained in block.
    84  	// Can be queried for any block that has been added to the block tree.
    85  	// Returns:
    86  	// - (KVStoreReader, nil) - if there is a protocol state associated with given block ID.
    87  	// - (nil, storage.ErrNotFound) - if there is no protocol state associated with given block ID.
    88  	// - (nil, exception) - any other error should be treated as exception.
    89  	KVStoreAtBlockID(blockID flow.Identifier) (KVStoreReader, error)
    90  
    91  	// GlobalParams returns params that are the same for all nodes in the network.
    92  	GlobalParams() GlobalParams
    93  }
    94  
    95  // MutableProtocolState is the read-write interface for protocol state. It allows evolving the protocol
    96  // state by calling `EvolveState` for each block with arguments that might trigger state changes.
    97  type MutableProtocolState interface {
    98  	ProtocolState
    99  
   100  	// EvolveState updates the overall Protocol State based on information in the candidate block
   101  	// (potentially still under construction). Information that may change the state is:
   102  	//   - the candidate block's view
   103  	//   - Service Events from execution results sealed in the candidate block
   104  	//
   105  	// EvolveState is compatible with speculative processing: it evolves an *in-memory copy* of the parent state
   106  	// and collects *deferred database updates* for persisting the resulting Protocol State, including all of its
   107  	// dependencies and respective indices. Though, the resulting batch of deferred database updates still depends
   108  	// on the candidate block's ID, which is still unknown at the time of block construction. Executing the deferred
   109  	// database updates is the caller's responsibility.
   110  	//
   111  	// SAFETY REQUIREMENTS:
   112  	//  1. The seals must be a protocol-compliant extension of the parent block. Intuitively, we require that the
   113  	//     seals follow the ancestry of this fork without gaps. The Consensus Participant's Compliance Layer enforces
   114  	//     the necessary constrains. Analogously, the block building logic should always produce protocol-compliant
   115  	//     seals.
   116  	//     The seals guarantee correctness of the sealed execution result, including the contained service events.
   117  	//     This is actively checked by the verification node, whose aggregated approvals in the form of a seal attest
   118  	//     to the correctness of the sealed execution result (specifically the Service Events contained in the result
   119  	//     and their order).
   120  	//  2. For Consensus Participants that are replicas, the calling code must check that the returned `stateID` matches
   121  	//     the commitment in the block proposal! If they don't match, the proposer is byzantine and should be slashed.
   122  	//
   123  	// Consensus nodes actively verify protocol compliance for any block proposal they receive, including integrity of
   124  	// each seal individually as well as the seals continuously following the fork. Light clients only process certified
   125  	// blocks, which guarantees that consensus nodes already ran those checks and found the proposal to be valid.
   126  	//
   127  	// SERVICE EVENTS form an order-preserving, asynchronous, one-way message bus from the System Smart Contracts
   128  	// (verified honest execution) to the Protocol State. For example, consider a fork where a service event is
   129  	// emitted during execution of block A. Block B contains an execution receipt `RA` for A. Block C holds a
   130  	// seal `SA` for A's execution result.
   131  	//
   132  	//    A ← … ← B(RA) ← … ← C(SA)
   133  	//
   134  	// Service Events are included within execution results, which are stored opaquely as part of the block payload
   135  	// (block B in our example). Though, to ensure correctness of the service events, we only process them upon sealing.
   136  	// There is some non-deterministic delay when the Protocol State observes the Service Events from block A.
   137  	// In our example, any change to the protocol state requested by the system smart contracts in block A, would only
   138  	// become visible in block C's Protocol State (and descendants).
   139  	//
   140  	// Error returns:
   141  	// [TLDR] All error returns indicate potential state corruption and should therefore be treated as fatal.
   142  	//   - Per convention, the input seals from the block payload have already been confirmed to be protocol compliant.
   143  	//     Hence, the service events in the sealed execution results represent the honest execution path.
   144  	//     Therefore, the sealed service events should encode a valid evolution of the protocol state -- provided
   145  	//     the system smart contracts are correct.
   146  	//   - As we can rule out byzantine attacks as the source of failures, the only remaining sources of problems
   147  	//     can be (a) bugs in the system smart contracts or (b) bugs in the node implementation. A service event
   148  	//     not representing a valid state transition despite all consistency checks passing is interpreted as
   149  	//     case (a) and _should be_ handled internally by the respective state machine. Otherwise, any bug or
   150  	//     unforeseen edge cases in the system smart contracts would result in consensus halt, due to errors while
   151  	//     evolving the protocol state.
   152  	//   - A consistency or sanity check failing within the StateMutator is likely the symptom of an internal bug
   153  	//     in the node software or state corruption, i.e. case (b). This is the only scenario where the error return
   154  	//     of this function is not nil. If such an exception is returned, continuing is not an option.
   155  	EvolveState(parentBlockID flow.Identifier, candidateView uint64, candidateSeals []*flow.Seal) (stateID flow.Identifier, dbUpdates *transaction.DeferredBlockPersist, err error)
   156  }