Skip to content

feat: epoch fsm implementation#906

Draft
amimart wants to merge 15 commits into
arnaud/engn-4254-exposes-rpc-queries-on-xschedulerfrom
arnaud/engn-4950-epoch-fsm-implementation
Draft

feat: epoch fsm implementation#906
amimart wants to merge 15 commits into
arnaud/engn-4254-exposes-rpc-queries-on-xschedulerfrom
arnaud/engn-4950-epoch-fsm-implementation

Conversation

@amimart

@amimart amimart commented Jan 29, 2026

Copy link
Copy Markdown
Contributor

Purpose of Changes and their Description

This PR aims to set the base structure of the integration of epoch lifecycle with the x/scheduler module. It is not functional but will serve as a base to iterate upon in the integration.

♻️ Epoch Lifecycle

The Epoch type has been designed as a state machine whose lifecycle is explicitly defined as a set of states and transitions, the core logic related to each transitions is not in the scope of this PR.

To ease its management a Finite State Machine abstraction is implemented under the fsm package. The emissions Keeper holds the FSMEngine instance carrying the epoch's state machine definition, in order to perform a transition on an epoch the Keeper#applyEpochTransition will be used leveraging the dedicated fsm engine.

Changes in the API are additive only as a temporary measure in order to make this PR more readable, next changes should be introduced in v10.

⏰ Epoch Scheduling

Wiring of the x/scheduler has been setup in the x/emissions module, which now exposes task handlers related to epoch lifecycle transitions:

  • emissions:open_epoch_worker_window: Open worker window;
  • emissions:close_epoch_worker_window: Close worker window and compute network inference;
  • emissions:open_epoch_reputer_window: Open reputer window;
  • emissions:close_epoch_reputer_window: Close reputer window;
  • emissions:complete_epoch: Compute loss, distribute rewards, and prune epoch data;

Each handler has the previous handler as a dependency to ensure execution order in case of execution in the same block.

The Keeper#StartEpoch public func allows the creation and scheduling of a new epoch for a topic.

💾 Epoch Storage

A new Nonce format has been introduced has a uint64 type alias whose first byte contains the nonce version, making it retro-compatible with block height based nonces. This new type is currently named NonceV2 to avoid the large API refactor but will replace the current type.

An Epoch is identified in a Topic by its Nonce, and uniquely identified by the [TopicId; Nonce] pair. It is stored as an IndexedMap, whose underlying map store epochs by their unique keys: [TopicId; Nonce] => Epoch. It exposes the following indexes:

  • ByState: Allows to filter epochs by a specific state (e.g. WORKER_SUBMISSION, REPUTER_SUBMISSION, etc...);
  • ByStateAndTopic: Allows to filter epochs by both state and topic id;

This way we can easily query global or per topic opened worker/reputer submission windows, and expose these capabilities through a single rpc query, maximising the system's observability.

Are these changes tested and documented?

  • If tested, please describe how. If not, why tests are not needed.
  • If documented, please describe where. If not, describe why docs are not needed.
  • Added to Unreleased section of CHANGELOG.md?

@amimart amimart changed the base branch from dev to arnaud/engn-4254-exposes-rpc-queries-on-xscheduler January 29, 2026 15:18
@github-actions

Copy link
Copy Markdown

The latest Buf updates on your PR. Results from workflow Buf Linter / buf (pull_request).

BuildFormatLintBreakingUpdated (UTC)
✅ passed❌ failed (2)❌ failed (8)⏩ skippedJan 29, 2026, 3:19 PM

@guilherme-brandao

Copy link
Copy Markdown
Contributor

The epoch lifecycle as defined here is a linear pipeline, each state has exactly one forward transition, and x/scheduler task dependencies already enforce execution order. It seems like simple conditionals (like x/gov) does would achieve the same result. What's the reasoning behind adding the FSM engine? Is there a plan for a more complex epoch lifecycle?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants