feat(cli): add digest + set-validators subcommands to genesis command - #449
Merged
Conversation
The genesis config digest identifies the chain a genesis file founds: it derives the P2P and consensus domains, so two nodes that disagree on it cannot authenticate each other as peers or verify each other's certificates. Nothing printed it — the value existed only inside a running node. `genesis digest` prints it as a single 0x-prefixed hex line, so tooling that needs to commit to a chain's identity can shell out for it the same way it already does for `seismic-reth genesis-hash`. The file goes through `Genesis::load_from_file`, exactly as a starting validator loads it, so a successful digest doubles as a verdict that the genesis is well formed. Failures exit non-zero with the parse or validation error on stderr rather than a panic backtrace, since this is meant to be shelled out to.
The `genesis` binary built a complete genesis file from a template plus a validator list. Its logic moves into the CLI and the binary is deleted. Emission belongs next to the type it emits. What this command writes is the byte source of `config_digest`, so the field set, hex spelling, and validator order are all chain identity, and a second implementation of that serialization — in another language, in the tooling that founds networks — would have to reproduce summit's canonical form and keep reproducing it. dae625e already fixed this class of bug once, when the binary carried its own copy of the `Genesis` struct and silently dropped fields the runtime requires. Beyond the move: - `-o` names a file rather than a directory, and is optional: with no `-o` the genesis goes to stdout, so a caller re-emitting it with current validator IPs can pipe instead of staging a temp file. Diagnostics go to stderr, so stdout carries genesis and nothing else. - `-i` is now required. It defaulted to `./example_genesis.toml`, so a forgotten flag silently founded a chain on the example's namespace, hash, and stake bounds. - The `-g` eth_genesis_hash override is gone. Nothing passed it, and it could emit a hash disagreeing with the template a network manifest commits to, quietly defeating that check. - Validators sort by decoded node key, so a `0x`-prefixed or upper-case key in the JSON sorts correctly instead of panicking in `from_hex().unwrap()`. - The rendered genesis is parsed back through `Genesis::from_toml_str` (new; `load_from_file` now delegates to it) before being emitted, for both destinations. Emitting a genesis no node can load is the failure this command exists to prevent, so it fails here and not at a boot. Tests cover what a binary couldn't: a complete, sorted genesis built from reverse-ordered input, an emitted genesis that reloads with an unchanged config digest, and a non-hex node key rejected. example_genesis.toml gains a header stating what the digest does and does not cover, a separator marking which parameters are governed after launch, and explicit values for the two governed fields that were relying on serde defaults. Note for anyone bisecting: the tooling that shelled out to the deleted binary needs its call site pointed at the subcommand in lockstep.
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.
Human Summary
These are purely changes to the summit CLI that processes genesis files. It doesn't touch any of the main binary logic. I need this for TEE network bootstrap phase where I need to build the summit genesis.
2 separate PRs, which should probably be merged as a rebase to keep their history separate:
genesis digestcommand to compute the SSZ digest of the genesis file, so that it can be pinned as part of the TEE's network-manifest.genesisbinary that we had as a subcommandgenesis set-validatorssince that's all that it does: injects (or overwrites) validators into a genesis template file.LLM Summary
Two related gaps around genesis files, closed together.
Nothing printed a genesis file's config digest. That digest identifies the
chain a genesis founds: it derives the P2P and consensus domains, so two nodes
that disagree on it cannot authenticate each other as peers or verify each
other's certificates. It existed only inside a running node — no way to obtain
it offline, and no way to learn a genesis file was malformed short of having a
validator exit on it at startup.
Genesis emission lived in a separate
genesisbinary that no image shipsand that duplicated knowledge of the
Genesisschema. Since what it writes isthe byte source of the digest — field set, hex spelling, validator order are all
chain identity — that logic belongs next to the type it emits, not in a binary
whose only caller is external tooling. Otherwise the next tool that needs to
write a genesis reimplements summit's canonical form and has to keep
reproducing it;
dae625ealready fixed that class of bug once, when this binarycarried its own copy of the
Genesisstruct and silently dropped fields theruntime requires.
Commits
feat: add a genesis digest subcommand— prints the digest as a single0x-prefixed hex line so tooling can shell out for it, the same way it alreadydoes for
seismic-reth genesis-hash. The file goes throughGenesis::load_from_file, exactly as a starting validator loads it, so asuccessful digest doubles as a verdict that the genesis is well formed. Failures
exit non-zero with the parse or validation error on stderr rather than a panic
backtrace.
feat: move genesis emission into summit genesis set-validators— thegenesisbinary's logic moves into the CLI and the binary is deleted. Thevalidators read from JSON become the whole set (replaced, never appended to),
emitted sorted by node public key because
config_digesthashes them in fileorder; everything else comes from the input untouched.
Behaviour changes from the deleted binary
-onames a file, not a directory, and is optional. With no-othegenesis goes to stdout, so a caller re-emitting it with current validator IPs
can pipe instead of staging a temp file. Diagnostics go to stderr, so stdout
carries genesis bytes and nothing else.
-iis now required. It defaulted to./example_genesis.toml, so aforgotten flag silently founded a chain on the example's namespace, EL genesis
hash, and stake bounds.
-g(eth_genesis_hash override) is gone. Nothing passed it, and it couldemit a hash disagreeing with the template a network manifest commits to,
quietly defeating that check.
0x-prefixed or upper-case keyin the JSON sorts correctly instead of panicking in
from_hex().unwrap().TOML is parsed back through the validator's own path for both destinations —
writing a genesis no node can load is the failure this command exists to
prevent, so it fails here rather than at someone's boot.
Worth a reviewer's eye
Genesis::from_toml_stris new insummit-types: parse + validate from astring, with
load_from_filenow delegating to it. It is what lets theemitter check its own output on the stdout path, where there is no file to
reload.
example_genesis.tomlgains a header stating what the digest does and doesnot cover (
validators[].ip_addressis the one excluded field), a separatormarking which parameters are governed after launch via
ProtocolParams.sol,and explicit values for the two governed fields that were relying on serde
defaults.
Breaking
Tooling that resolved the
genesisbinary onPATHmust point atsummit genesis set-validatorsin lockstep — the argv is otherwise unchangedapart from
-onow taking a file path. Nothing inside this repo referenced thebinary.