feat: chain fork support as genesis ceremony extension#46
Merged
Conversation
Minimal ForkConfig on GenesisCeremonyConfig with just sourceChainId.
The genesis planner selects the assembler task based on which
condition is set:
- GenesisCeremonyNeeded → assemble-and-upload-genesis (existing)
- ForkGenesisCeremonyNeeded → assemble-fork-genesis (new)
No new planner — the existing genesisGroupPlanner handles both.
detectGenesisCeremonyNeeded sets the appropriate condition based
on whether genesis.Fork is configured.
The assembled fork genesis writes to the same platform S3 path
convention as any genesis: {chainId}/{groupName}/genesis.json.
The exported state is expected at {sourceChainId}/exported-state.json
in the platform genesis bucket.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
bdchatham
commented
Apr 1, 2026
…mplete - Rename task type from assemble-fork-genesis to assemble-genesis-fork to match seictl handler registration - Set GenesisCeremonyComplete condition in completePlan for genesis/fork plans to prevent infinite plan rebuild loop Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extends the fork flow with automated state export: - ForkConfig gains SourceImage and ExportHeight fields - reconcileSeiNodes creates a temporary exporter SeiNode (plain FullNode with BootstrapImage + TargetHeight, same config pattern as replayers) - Exporter bootstraps through the standard SeiNode pipeline - Group plan prepends: await-exporter-running → submit-export-state → teardown-exporter before assemble-genesis-fork The exporter is excluded from IncumbentNodes (filtered by sei.io/role label). seid export --height N reads committed state at exactly that height, making the export deterministic regardless of node progress. Also fixes SnapshotUploadTask field removal for seictl v0.0.27 compat. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
bdchatham
added a commit
to sei-protocol/seictl
that referenced
this pull request
Apr 2, 2026
## Summary
New sidecar task `assemble-genesis-fork` that assembles genesis from an
existing chain's exported state.
### Flow
1. Download exported state from `{sourceChainId}/exported-state.json` in
platform genesis bucket
2. Rewrite chain_id, initial_height, genesis_time; clear validators
3. Strip old validator state (staking/slashing/distribution/evidence)
4. Download new validator gentxs, add missing accounts
5. Run collect-gentxs
6. Upload genesis.json + peers.json to `{newChainId}/`
### Design
Follows the same patterns as the existing `GenesisAssembler` — same S3
conventions, same collect-gentxs flow, same marker file idempotency. The
only difference is the starting point: exported state instead of fresh
genesis.
### Companion
Controller: sei-protocol/sei-k8s-controller#46
### Note
Controller PR uses task type `assemble-fork-genesis` — needs renaming to
`assemble-genesis-fork` to match this PR.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace string literals with sidecar.TaskTypeAssembleGenesisFork and sidecar.TaskTypeExportState from the seictl client package. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
bdchatham
commented
Apr 2, 2026
…rter to plan task Address PR feedback: - Replace 31-case switch statement in Deserialize with a map-based registry. New sidecarTask[T] generic helper creates deserializers for sidecar-backed tasks. Eliminates cyclomatic complexity issue. - Move exporter SeiNode creation from reconcileSeiNodes into a create-exporter plan task. The group plan now owns the full exporter lifecycle: create → await → export → teardown. reconcileSeiNodes stays focused on the N validator nodes. - Fix submit-export-state to use real sidecar client (sidecarClientForNode) instead of TODO placeholders. - Remove unnecessary "sidecar task" comment in Deserialize. - Improve completePlan comment explaining genesis completion detection. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The genesis ceremony completion check read group.Status.Deployment == nil after the deployment finalization block had already set it to nil, causing deployment plan completions to spuriously set GenesisCeremonyComplete. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Bump seictl to v0.0.29
- Fix awaitExporterRunning: NotFound returns Running (cache lag), not Complete
- Fix submitExportState: recompute sidecar taskID deterministically in
Status() so it survives re-deserialization across reconcile boundaries
- Fix createExporter: delete Failed exporter so next reconcile can
create a fresh one (prevents infinite plan-fail loop)
- Fix peer DNS: use {name}-0.{name}.{ns}.svc.cluster.local to match
StatefulSet headless Service pod DNS
- Add nil guard in group planner for Fork spec
- Add 6-hour timeout on export-state via exporter CreationTimestamp
- Add fork plan test (7-task plan with correct types and ordering)
- Add fork task execution tests (create, await, submit, teardown)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
bdchatham
commented
Apr 2, 2026
The create-exporter task has already completed by this point, so the exporter should exist. NotFound means something is genuinely wrong, not cache lag. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Minimal fork support for SeiNodeGroup — fork an existing chain's state into a private network.
Design
Fork is an extension of the existing genesis ceremony, not a separate flow. The genesis planner selects the assembler task based on which condition is set:
GenesisCeremonyNeeded→assemble-and-upload-genesis(existing)ForkGenesisCeremonyNeeded→assemble-fork-genesis(new sidecar task)CRD
Added as
Fork *ForkConfigonGenesisCeremonyConfig. That's it — the exported state location and assembled genesis output use the existing platform S3 conventions.Example
Changes
ForkConfigtype +Forkfield onGenesisCeremonyConfigGenesisCeremonyNeededandForkGenesisCeremonyNeededconditionsdetectGenesisCeremonyNeededreplaces separate detection methodsgenesisGroupPlannerbranches on condition to select assembler taskAssembleForkGenesisParams+ Deserialize registrationCompanion
Seictl
assemble-fork-genesishandler (PR coming)🤖 Generated with Claude Code