Skip to content

fix: assemble genesis with the canonical Genesis type#433

Open
samlaf wants to merge 1 commit into
mainfrom
fix-genesis-canonical-type
Open

fix: assemble genesis with the canonical Genesis type#433
samlaf wants to merge 1 commit into
mainfrom
fix-genesis-canonical-type

Conversation

@samlaf

@samlaf samlaf commented Jul 1, 2026

Copy link
Copy Markdown

The genesis binary defined its own GenesisConfig — a partial copy of summit_types::Genesis that predated the staking fields. With no deny_unknown_fields, deserializing the template into it silently dropped validator_minimum_stake / validator_maximum_stake, so the emitted genesis.toml was missing fields the node's runtime loader requires and summit run panicked at startup ("missing field validator_minimum_stake").

Load and serialize the template as summit_types::Genesis directly and drop the local struct, so there is a single genesis schema the binary can't drift from.

Context: this surfaced in the Seismic deploy flow, whose operator CLI shells out to this genesis binary to build a network's genesis. A few rough edges there: it has to be built and installed via cargo; it's named just genesis, which collides easily on PATH and doesn't read as part of summit; and (as above) it's a separately-built, independently-versioned copy of the node's genesis logic, with nothing guaranteeing it matches the summit running on the node.

Proposed alternative designs

  • Move assembly into the node: have sendGenesis take the template + validator set rather than a pre-built genesis.toml, and let each node build its own genesis with its own Genesis type and sort — e.g. a shared assemble_genesis(template, validators) backing both this binary and the RPC handler. The node could also fill eth_genesis_hash from its own reth, which would remove the external binary and the version-skew question altogether.
  • Or, if a standalone tool is preferred, fold this into the summit binary as a summit genesis subcommand (alongside run/keys), so it shares the genesis types and isn't a stray genesis on PATH.

The `genesis` binary defined its own `GenesisConfig` — a partial copy of
`summit_types::Genesis` that predated the staking fields. With no
`deny_unknown_fields`, deserializing the template into it silently dropped
`validator_minimum_stake` / `validator_maximum_stake`, so the emitted
genesis.toml was missing fields the node's runtime loader requires and
`summit run` panicked at startup ("missing field `validator_minimum_stake`").

Load and serialize the template as `summit_types::Genesis` directly and drop
the local struct, so there is a single genesis schema the binary can't drift
from.

Context: this surfaced in the Seismic deploy flow, whose operator CLI shells
out to this `genesis` binary to build a network's genesis. A few rough edges
there: it has to be built and installed via cargo; it's named just `genesis`,
which collides easily on PATH and doesn't read as part of summit; and (as
above) it's a separately-built, independently-versioned copy of the node's
genesis logic, with nothing guaranteeing it matches the summit running on the
node.

Proposed directions (just ideas, not part of this change):
  - Move assembly into the node: have `sendGenesis` take the template +
    validator set rather than a pre-built genesis.toml, and let each node
    build its own genesis with its own `Genesis` type and sort — e.g. a
    shared `assemble_genesis(template, validators)` backing both this binary
    and the RPC handler. The node could also fill `eth_genesis_hash` from its
    own reth, which would remove the external binary and the version-skew
    question altogether.
  - Or, if a standalone tool is preferred, fold this into the `summit` binary
    as a `summit genesis` subcommand (alongside `run`/`keys`), so it shares
    the genesis types and isn't a stray `genesis` on PATH.
@samlaf samlaf requested a review from matthias-wright July 1, 2026 06:43
samlaf added a commit to SeismicSystems/deploy that referenced this pull request Jul 1, 2026
…rogress (#47)

## Summary

Fixes the operator-side `seismic-tee-bootstrap genesis` ceremony — which
had
never actually run end-to-end against a real node — and labels the
first-boot
disk-provisioning progress bar. Surfaced while bringing up the first
single-node TEE network to a live chain; with these changes (plus a
companion
`summit` fix, see below) a node reaches a live chain (reth producing,
summit
finalizing).

## Changes

### 1. `summit_client` speaks JSON-RPC, not REST (`fix`)
summit's RPC is jsonrpsee (JSON-RPC 2.0, POST-only, camelCase methods —
see
`summit/rpc/src/api.rs`), but `summit_client` did `GET /<path>` and
`text/plain` POSTs with snake_case paths. So `getPublicKeys` /
`sendGenesis`
never worked against a real node.

Rewrote it as a JSON-RPC client: one `_rpc(method, params)` that POSTs
the
envelope to the `/summit` base (nginx strips the prefix) and returns
`result`,
using the real method names. Dropped the dead REST helpers and
`send_share`
(no such endpoint, no caller). Added mocked tests for the envelope +
error path.

### 2. Run the `genesis` binary from PATH with an explicit template
(`feat!`)
`genesis.py` assumed a dev checkout — it shelled out to
`~/summit/target/debug/genesis` and `~/summit/example_genesis.toml`.

Now it takes the `genesis` binary from **PATH** (the pattern summit uses
for
`reth`), with a clear error if it's missing, and the template via
**`--summit-template`**. Dropped `--code-path` (its only job was
locating
`~/summit`). Also logs the built genesis's path and each node it's sent
to
before delivery (paths only, not contents), mirroring how `configure`
logs
the config it POSTs.

**Breaking:** `--summit-template` is now required; `--code-path` is
removed.

### 3. Label first-boot disk-provisioning progress (`feat`)
The progress bar showed bytes / % / eta but never said what it was
doing.
Added an `encrypting disk` label and a one-time line when provisioning
starts,
explaining it's the first-boot full-disk LUKS + dm-integrity wipe
(one-time,
can take 1h+) so the long phase doesn't read as a hang.

## Prereqs

`seismic-tee-bootstrap genesis` needs the `genesis` binary on PATH —
built
from summit, e.g. `cargo install --path node --bin genesis --locked`
(the
`--locked` matters; summit pins commonware via its lockfile).

## Testing

- Unit tests (mocked, no network): `summit_client` request envelope +
RPC-error
path; existing manifest/configure/status suites still pass. `ruff`
clean.
- Manually drove a single-node TEE network end-to-end to a live chain
  (`cast block-number` advancing) using these changes.

## Follow-ups (not in this PR)

- **`eth_genesis_hash` still needs a manual `-g`.** summit's genesis
template
carries an `eth_genesis_hash` that must equal reth's actual genesis
hash;
  today the operator passes it via `-g`. Proposed: have the ceremony
  auto-derive it from the node's own reth (`eth_getBlockByNumber 0`) and
  cross-check the cohort, removing the manual step.
- **Companion `summit` fix (separate
[PR](SeismicSystems/summit#433 the
`genesis` binary defined its
own genesis struct that had drifted from `summit_types::Genesis` and
silently
  dropped required fields (`validator_minimum_stake`); fixed to use the
canonical type. That PR also proposes moving genesis *assembly* into the
node
(`sendGenesis` taking template + validators) to retire the operator-side
  binary and the version-skew question entirely.
- **`genesis` reads each node's summit pubkey once (no retry).** A node
that
isn't ready yet fails the ceremony; retry-until-ready is a separate
change.
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.

1 participant