The epoch contract stores a lot of different state, and the state is constantly changing. As an external party, there are two ways to keep track of these state changes. You can either use Cadence scripts to query the state of the contract at any given time, or you can monitor events that are emitted by the epoch contract to be notified of any important occurances.
These events can be queried using the Go or JavaScript SDKs to extract useful notifications and information about the state of the epoch preparation protocol.
Service events are special messages that are generated by smart contracts and included in execution results. They enable communication between system smart contracts and the Flow protocol. In other words, they serve as a communication mechanism between the execution state and the protocol state.
Concretely, service events are defined and emitted as events like any other in Cadence. An event is considered a service event when it is:
- emitted within the service chunk
- emitted from a smart contract deployed to the service account
- conformant to an event allowlist
Each block contains a system chunk. For each system chunk, all service events emitted are included in the corresponding execution result.
When verifying the system chunk, verifier nodes will only produce result approvals when the system chunks included in the execution result are correct. Thus, the security of this communication mechanism is enforced by the verification system.
When sealing a block containing a service event, the consensus committee will update the protocol state accordingly, depending on the semantics of the event.
For example, a service event may indicate that a node's stake has diminished to the point where they should be ejected, in which case the consensus committee would mark that node as ejected in the protocol state.
Service events are fundamentally asynchronous, due the lag between block execution and sealing. Consequently they are handled slightly differently than other protocol state updates.
The diagram below illustrates the steps each service event goes through to be included in the protocol state.
For conciseness, we say a service event is sealed
when the block in which it was emitted is sealed,
and we say a service event is finalized
when the block containing the seal is finalized.
The Epoch Setup service event is emitted by FlowEpoch.startEpochSetup()
when the staking auction phase ends and the Epoch Smart Contracts transition to the Epoch Setup phase.
It contains the finalized identity table for the upcoming epoch,
as well as timing information for phase changes.
1pub event EpochSetup (23/// The counter for the upcoming epoch. Must be one greater than the4/// counter for the current epoch.5counter: UInt64,67/// Identity table for the upcoming epoch with all node information.8/// Includes:9/// nodeID, staking key, networking key, networking address, role,10/// staking information, weight, and more.11nodeInfo: [FlowIDTableStaking.NodeInfo],1213/// The first view (inclusive) of the upcoming epoch.14firstView: UInt64,1516/// The last view (inclusive) of the upcoming epoch.17finalView: UInt64,1819/// The cluster assignment for the upcoming epoch. Each element in the list20/// represents one cluster and contains all the node IDs assigned to that21/// cluster, with their weights and votes22collectorClusters: [FlowClusterQC.Cluster],2324/// The source of randomness to seed the leader selection algorithm with25/// for the upcoming epoch.26randomSource: String,2728/// The deadlines of each phase in the DKG protocol to be completed in the upcoming29/// EpochSetup phase. Deadlines are specified in terms of a consensus view number.30/// When a DKG participant observes a finalized and sealed block with view greater31/// than the given deadline, it can safely transition to the next phase.32DKGPhase1FinalView: UInt64,33DKGPhase2FinalView: UInt64,34DKGPhase3FinalView: UInt6435)
The EpochCommit
service event is emitted when the Epoch Smart Contracts transition
from the Epoch Setup phase to the Epoch Commit phase.
It is emitted only when all preparation for the upcoming epoch (QC and DKG) has been completed.
1pub event EpochCommit (23/// The counter for the upcoming epoch. Must be equal to the counter in the4/// previous EpochSetup event.5counter: UInt64,67/// The result of the QC aggregation process. Each element contains8/// all the nodes and votes received for a particular cluster9/// QC stands for quorum certificate that each cluster generates.10clusterQCs: [FlowClusterQC.ClusterQC],1112/// The resulting public keys from the DKG process, encoded as by the flow-go13/// crypto library, then hex-encoded.14/// Group public key is the first element, followed by the individual keys15dkgPubKeys: [String],16)
The FlowEpoch
smart contract stores important metadata about the current, proposed,
and previous epochs. Metadata for all historical epochs is stored permenantely
in the Epoch Smart Contract's storage.
1pub struct EpochMetadata {23/// The identifier for the epoch4pub let counter: UInt6456/// The seed used for generating the epoch setup7pub let seed: String89/// The first view of this epoch10pub let startView: UInt641112/// The last view of this epoch13pub let endView: UInt641415/// The last view of the staking auction16pub let stakingEndView: UInt641718/// The total rewards that are paid out for the epoch19pub var totalRewards: UFix642021/// The reward amounts that are paid to each individual node and its delegators22pub var rewardAmounts: [FlowIDTableStaking.RewardsBreakdown]2324/// Tracks if rewards have been paid for this epoch25pub var rewardsPaid: Bool2627/// The organization of collector node IDs into clusters28/// determined by a round robin sorting algorithm29pub let collectorClusters: [FlowClusterQC.Cluster]3031/// The Quorum Certificates from the ClusterQC contract32pub var clusterQCs: [FlowClusterQC.ClusterQC]3334/// The public keys associated with the Distributed Key Generation35/// process that consensus nodes participate in36/// Group key is the last element at index: length - 137pub var dkgKeys: [String]38}
The FlowEpoch
smart contract provides a public function, FlowEpoch.getEpochMetadata()
to query the metadata for a particular epoch.
You can use the Get Epoch Metadata(EP.01) script with the following arguments:
Argument | Type | Description |
---|---|---|
epochCounter | UInt64 | The counter of the epoch to get metadata for. |
The FlowEpoch
smart contract also has a set of metadata that is configurable by the admin
for phase lengths, number of collector clusters, and inflation percentage.
1pub struct Config {2/// The number of views in an entire epoch3pub(set) var numViewsInEpoch: UInt6445/// The number of views in the staking auction6pub(set) var numViewsInStakingAuction: UInt6478/// The number of views in each dkg phase9pub(set) var numViewsInDKGPhase: UInt641011/// The number of collector clusters in each epoch12pub(set) var numCollectorClusters: UInt161314/// Tracks the annualized percentage of FLOW total supply that is minted as rewards at the end of an epoch15/// Calculation for a single epoch would be (totalSupply * FLOWsupplyIncreasePercentage) / 5216pub(set) var FLOWsupplyIncreasePercentage: UFix6417}
You can use the Get Configurable Metadata(EP.02) script to get the list of configurable metadata:
This script does not require any arguments.
The FlowEpoch
smart contract always tracks the counter of the current epoch.
You can use the Get Epoch Counter(EP.03) script to get the current epoch counter.
This script does not require any arguments.
The FlowEpoch
smart contract always tracks the active phase of the current epoch.
1pub enum EpochPhase: UInt8 {2pub case STAKINGAUCTION3pub case EPOCHSETUP4pub case EPOCHCOMMIT5}
You can use the Get Epoch Phase(EP.04) script to get the current epoch phase.
This script does not require any arguments.