chore(crypto): rename the well-known network keys for what they are - #262
Merged
samlaf merged 1 commit intoAug 20, 2026
Conversation
Part of SEI-172 The sample-key getters — get_unsecure_sample_secp256k1_sk/pk and get_unsecure_sample_schnorrkel_keypair — named these keys as test fixtures. They are not: every network with no root key to derive purpose keys from (dev networks and pre-TEE deployments, the live testnet included) runs them as its real network keys. Rename them for what they are, and document them plainly: published in this public repository, no confidentiality against anyone who reads the source; their only property is that every node and client agrees on them. - well_known_tx_io_keypair() replaces the secp256k1 sk/pk pair. One function, not two: the public half is derived from the secret half, so pair consistency holds by construction, and a test freezes the published public key against drift. - well_known_rng_ikm() -> [u8; 64] replaces the schnorrkel-keypair getter. Every consumer narrows the keypair to secret.to_bytes() and feeds the result to HKDF, so the function returns those 64 bytes directly, written in hex to compare easily against key material in logs. A dev-dependency test recomputes the original schnorrkel expansion and pins the bytes: the value is a consensus input via the RNG precompile, so it must never drift. - get_unsecure_sample_aesgcm_key and the SchnorrkelKeypair re-export are deleted; neither has a caller anywhere. With the expansion out of production code, schnorrkel drops to a dev-dependency and leaves every consumer's transitive graph. Consumers pin this crate by git rev, so they take the rename when they bump.
samlaf
deleted the
sl/sei-172-chore-rename-the-well-known-keys-in-seismic-crypto-and
branch
August 20, 2026 16:46
samlaf
added a commit
to SeismicSystems/seismic-revm
that referenced
this pull request
Aug 20, 2026
…239) Part of SEI-172 seismic-crypto renamed its well-known network key getters for what they are (SeismicSystems/enclave#262): these are the keys every network without a root key actually runs, not test fixtures. The RNG tests here take the rename: well_known_rng_ikm() returns the 64 ikm bytes directly, which every call site already narrowed the schnorrkel keypair down to. The bytes are identical, so the pinned RNG-precompile outputs (consensus-visible) are unchanged. - schnorrkel is now a dev-dependency of seismic-crypto, so it and its curve25519-dalek subtree leave this crate's dependency graph. - RootRng::test_default() is deleted. It was public API with no callers outside this crate's own tests, and hid which key the tests pin; the tests construct RootRng::new(well_known_rng_ikm()) directly.
samlaf
added a commit
to SeismicSystems/seismic-alloy
that referenced
this pull request
Aug 20, 2026
…4f (well-known key rename) seismic-crypto renamed its well-known network key getters for what they are (SeismicSystems/enclave#262): these are the keys every network without a root key actually runs, not test fixtures. The tests here take the rename: well_known_tx_io_keypair() replaces the split sk/pk getters, so a mismatched pair is unrepresentable, and the tee-pubkey test still matches the key sanvil serves — the values are unchanged. The seismic-revm pin moves to the rev that takes the same rename (SeismicSystems/seismic-revm#239): the [patch.crates-io] seismic-crypto override applies to seismic-revm's build too, so both pins advance together. Part of SEI-172
samlaf
added a commit
to SeismicSystems/seismic-alloy
that referenced
this pull request
Aug 20, 2026
…ame) (#113) Part of SEI-172 seismic-crypto renamed its well-known network key getters for what they are (SeismicSystems/enclave#262): these are the keys every network without a root key actually runs, not test fixtures. The tests here take the rename: well_known_tx_io_keypair() replaces the split sk/pk getters, so a mismatched pair is unrepresentable, and the tee-pubkey test still matches the key sanvil serves — the values are unchanged. The seismic-revm pin moves to the rev that takes the same rename (SeismicSystems/seismic-revm#239): the [patch.crates-io] seismic-crypto override applies to seismic-revm's build too, so both pins advance together.
samlaf
added a commit
to SeismicSystems/seismic-evm
that referenced
this pull request
Aug 20, 2026
…ypair (#65) Part of SEI-172 seismic-crypto renamed its well-known network key getters for what they are (SeismicSystems/enclave#262): these are the keys every network without a root key actually runs, not test fixtures. The revm and alloy pins move to the revs that take the same rename (SeismicSystems/seismic-revm#239, SeismicSystems/seismic-alloy#113). PurposeKeys holds the tx-io pair as one secp256k1::Keypair, so a mismatched pair is unrepresentable everywhere the struct travels; call sites read .secret_key() / .public_key(), and the redacting Debug prints tx_io.public_key(). PurposeKeys::well_known() names the bundle a network with no root key runs, in the crate that owns the type — one definition for the node's built-in key source and for every test that needs a bundle a node would accept. Its dependency costs nothing: seismic-crypto is already in this crate's graph through both seismic-revm and seismic-alloy-consensus. The alloy-tx-macros tag patch goes away: seismic-alloy exact-pins it at =1.1.0 in the crate that introduces the edge, and version requirements propagate where patches do not. Cargo.lock is committed so CI stops resolving fresh and picking up releases inside caret ranges that conflict with the pinned alloy-core fork.
samlaf
added a commit
to SeismicSystems/seismic-foundry
that referenced
this pull request
Aug 20, 2026
…223) Part of SEI-172 seismic-crypto renamed its well-known network key getters for what they are (SeismicSystems/enclave#262): these are the keys every network without a root key actually runs, not test fixtures. sanvil serves the well-known tx-io public key from seismic_getTeePublicKey and decrypts calldata with the secret half, so every call site here takes the rename. The key values are unchanged. The seismic-revm and seismic-alloy pins move to the revs carrying the same rename (SeismicSystems/seismic-revm#239, SeismicSystems/seismic-alloy#113). The alloy-evm pin stays where it is: nothing here builds a PurposeKeys, and the newer revs rename alloy_evm::overrides::StateOverrideError, which anvil's error module imports. seismic-alloy exact-pins alloy-chains at =0.2.34 so the constraint reaches its consumers, which moves this lock from 0.2.25 to 0.2.34. alloy-chains replaced EtherlinkTestnet (128123) with EtherlinkShadownet (127823) in that range, so the different-gas-calc chain list names the Etherlink test network that crate now knows.
samlaf
added a commit
to SeismicSystems/seismic-reth
that referenced
this pull request
Aug 20, 2026
… copy (#482) Fixes SEI-172 seismic-crypto renamed its well-known network key getters for what they are (SeismicSystems/enclave#262): these are the keys every network without a root key actually runs — the live testnet included, via `--seismic.purpose-keys-source built-in` — not test fixtures. seismic-evm now owns the bundle built from them: PurposeKeys holds the tx-io pair as one secp256k1::Keypair, and PurposeKeys::well_known() is the single definition of what a network with no root key boots on (SeismicSystems/seismic-evm#65). The revm and alloy pins move to the revs carrying the same rename (SeismicSystems/seismic-revm#239, SeismicSystems/seismic-alloy#113). So this repo's second copy goes away: the two hex literals, WELL_KNOWN_RNG_IKM, and the well_known_purpose_keys() wrapper are gone, and the built-in key source returns PurposeKeys::well_known() directly, keeping the note on what those keys mean for a pre-TEE network. Two tests go with them: one asserted our copy equalled seismic-crypto's, which is now a tautology, and one asserted the hardcoded public key was the secret key's, which the Keypair makes structural. The four mock bundles (node test utils, fuzz targets, the evm unit tests, the hardfork e2e test) call the same constructor, so every key value they use is unchanged. Elsewhere the tx-io pair is read through the keypair: the rpc extension serves tx_io.public_key() and encrypts and decrypts with tx_io.secret_key(). The custodian decode keeps its wire-level cross-check of the served pair and then builds the Keypair from the secret half; the IPC contract is untouched. schnorrkel leaves the repo along with the derivation that needed it. The rng ikm is HKDF input material that no schnorrkel cryptography ever touched, and seismic-crypto now returns those same bytes as a frozen constant.
samlaf
added a commit
that referenced
this pull request
Aug 21, 2026
Part of SEI-222 get_rng_ikm derived its 64 bytes as HKDF(root_key) -> MiniSecretKey -> expand(Uniform) -> secret bytes. The schnorrkel step is a leftover of the original VRF-based RNG design: no schnorrkel cryptography is performed with the result, and every consumer already narrows it to a raw [u8; 64]. It now takes those 64 bytes from the purpose derivation itself. This changes the rng key on every network that has a root key, and RNG-precompile outputs are consensus, so re-found any running TEE devnet across the change rather than upgrading it in place. A network with no root key runs the well-known ikm literal (#262) and never reaches this derivation; the live testnet is one of those and is unaffected. expand_purpose<const N> is now the crate's only deriver: 32 bytes for every purpose, 64 for RngPrecompile. That retires the last schnorrkel use in production code, so the crate drops the dependency and schnorrkel stays only as seismic-crypto's dev-dependency, without the serde feature nothing asked for. The derivation also stops being public API. Key, KeyPurpose and derive_purpose_key leave the crate's surface, which is now exactly one way out per defined key: get_tx_io_sk, get_tx_io_pk, get_rng_ikm and get_snapshot_key hand a caller its key in that key's own type, and write_luks_keyfile exports the LUKS pair, whose bytes no in-process caller ever holds. Nothing outside the crate imported the removed items. Two things fall out of that: - Key had one job left, scrubbing root_key, and that needs no named type: Custodian derives ZeroizeOnDrop over a plain [u8; 32]. The vacuous Result on derive_purpose_key, its .expect at three call sites, and get_snapshot_key's length try_into go with it. - write_luks_keyfile assembles both LUKS keys into one buffer that leaves as a file. The buffer is now Zeroizing, so the copy this process keeps is scrubbed once the write lands.
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.
Part of SEI-172
The sample-key getters — get_unsecure_sample_secp256k1_sk/pk and get_unsecure_sample_schnorrkel_keypair — named these keys as test fixtures. They are not: every network with no root key to derive purpose keys from (dev networks and pre-TEE deployments, the live testnet included) runs them as its real network keys. Rename them for what they are, and document them plainly: published in this public repository, no confidentiality against anyone who reads the source; their only property is that every node and client agrees on them.
With the expansion out of production code, schnorrkel drops to a dev-dependency and leaves every consumer's transitive graph. Consumers pin this crate by git rev, so they take the rename when they bump.