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 }