Epoch Module
Time-based hooks and epoch lifecycle management for coordinating periodic chain operations.
paxeer-network/modules/epoch/Overview
The epoch module manages fixed time periods (epochs) and triggers registered hooks when each epoch begins or ends. An epoch defaults to 60 seconds relative to genesis time. This enables time-coordinated actions like validator set updates, reward distributions, and parameter adjustments.
Other modules register hooks via a simple interface, and the epoch module calls those hooks at the start and end of each epoch during BeginBlock.
State
The epoch module maintains a single state object:
> paxd q epoch epoch --output json
{
"epoch": {
"genesis_time": "2023-04-27T19:08:11.958027Z",
"epoch_duration": "60s",
"current_epoch": "0",
"current_epoch_start_time": "2023-04-27T19:08:11.958027Z",
"current_epoch_height": "0"
}
}- genesis_time: Chain genesis time (fixed)
- epoch_duration: Duration of each epoch in seconds (default 60s)
- current_epoch: Current epoch number (increments at each epoch boundary)
- current_epoch_start_time: Timestamp when the current epoch started
- current_epoch_height: Block height at which the current epoch started
Epoch Boundaries
Epochs are defined by wall-clock time, not block height. The module checks the block timestamp in BeginBlock. If blockTime - current_epoch_start_time ≥ epoch_duration, a new epoch begins.
This time-based approach ensures epochs occur at predictable intervals even if block times vary.
Hooks
Other modules implement the epoch hooks interface to execute logic at epoch boundaries:
BeforeEpochStart
func (k Keeper) BeforeEpochStart(ctx sdk.Context, epoch epochTypes.Epoch) {
// Execute logic at the start of each epoch
}Called when a new epoch begins, before any other epoch processing.
AfterEpochEnd
func (k Keeper) AfterEpochEnd(ctx sdk.Context, epoch epochTypes.Epoch) {
// Execute logic at the end of each epoch
}Called when an epoch ends, after all epoch processing is complete.
Example: Mint Module
The mint module (modules/mint/keeper) implements epoch hooks to distribute inflation rewards daily. It registers its hooks in node/app.go:
app.EpochKeeper = *epochmodulekeeper.NewKeeper(
appCodec,
keys[epochmoduletypes.StoreKey],
keys[epochmoduletypes.MemStoreKey],
app.GetSubspace(epochmoduletypes.ModuleName),
).SetHooks(epochmoduletypes.NewMultiEpochHooks(
app.MintKeeper.Hooks()))Events
The epoch module emits a new_epoch event at each epoch boundary:
- epoch_number: The new epoch's epoch number
- epoch_time: The new epoch's start time
- epoch_height: The block height at which the new epoch started
Messages
The epoch module does not expose any transactions. All interactions happen via hooks and events. Only the module itself updates epoch state during BeginBlock.
Parameters
The epoch module has no runtime parameters. The epoch duration is fixed at genesis and cannot be changed without a chain upgrade.
Use Cases
- Mint module: Distribute inflation rewards once per epoch (daily)
- Validator updates: Apply validator set changes at epoch boundaries
- Parameter changes: Activate governance-approved parameter updates
- Periodic cleanup: Prune expired state or cache entries