Skip to content

Genesis & the network bundle

Every node on a Krypton network shares one small network bundle. This page explains what's in it, the two ways genesis is produced (the ceremony that stands up a network vs. joining an existing one), and the spec.toml filename rule that trips people up.

The bundle = three files

The network bundle distributed to every joining node is exactly:

FileWhat it is
eth-genesis.jsonEL genesis — chainId for the network, dev account funded, FEE_SINK / INFLATION_SINK pre-allocated.
spec.tomlThe CL chain-spec actually used (W4 inflation keys + W3 safety params; deposit-eth1-chain-id matching the chain-id).
kzg-trusted-setup.jsonThe KZG trusted setup (blob commitments).

The spec MUST be named spec.toml in the bundle

The genesis tool emits the spec as krypton-<chain-id>.spec.toml (e.g. krypton-473374.spec.toml), but the compose file and bootstrap.sh read /network/spec.toml. When assembling the bundle you rename the per-network spec to spec.toml. The bundle does not include the CL genesis.json — that is consumed by beacond from each validator's own home, not from the shared bundle.

Path A — Stand up a network (the genesis ceremony)

Run once, by the launch coordinator, to mint the network. Uses from-source/genesis/gen-genesis.sh — the non-interactive port of upstream's ceremony (initadd-premined-depositcollect-premined-depositsset-deposit-storageexecution-payload), looped to N validators.

sh
cd l1/from-source/genesis

# 8-validator genesis on chain-id 473374, using the custom CL image:
CHAIN_ID=473374 VALIDATORS=8 \
  BEACOND_IMAGE=ghcr.io/foreseerco/krypton-beacond:v1.3.9-473374 \
  ./gen-genesis.sh

CHAIN_ID defaults to 47337 (mainnet); set CHAIN_ID=473374 for the public testnet. It produces, under genesis/out/:

ArtifactWhat it is
eth-genesis.jsonEL genesis, chainId: 473374, dev account funded, FEE_SINK/INFLATION_SINK pre-allocated.
genesis.jsonCL (beacon) genesis with the N premined validators.
krypton-473374.spec.tomlThe chain-spec used — the template with deposit-eth1-chain-id sed'd to the chain-id.
kzg-trusted-setup.jsonKZG trusted setup.
val-0 … val-7/One beacond home per validator, each holding priv_validator_key.json + node_key.jsonSECRETS.

Verify immediately:

sh
jq .config.chainId out/eth-genesis.json     # expect 473374

Assemble the shared bundle — exactly the three files (NOT the per-validator homes), with the spec renamed to spec.toml:

sh
cd out
mkdir -p bundle
cp eth-genesis.json kzg-trusted-setup.json bundle/
cp krypton-473374.spec.toml bundle/spec.toml         # the rename that matters
tar -czf krypton-testnet-bundle.tar.gz -C bundle .

Publish the tarball at a stable https URL (the BUNDLE_URL operators fetch) and also publish its sha256bootstrap.sh/install.sh require BUNDLE_SHA256 and verify the download before extracting (a remote bundle is extracted as a privileged user, so it is authenticated, scheme-checked, and path-scanned first). Distribute each validator's home (val-i/) privately to that operator over a secure channel — they contain private keys. Collect the first-up nodes' enode (EL) and CometBFT node-id (CL) addresses and publish them as EL_BOOTNODES / CL_SEEDS for joiners.

sh
sha256sum krypton-testnet-bundle.tar.gz   # publish this alongside the URL

Path B — Join an existing network

Run on every joining host. You need the published BUNDLE_URL (or a local BUNDLE_DIR), the EL_BOOTNODES / CL_SEEDS peer strings, and (validators only) your priv_validator_key.json from the ceremony.

sh
# Fetch + install bundle (https + BUNDLE_SHA256-verified), generate JWT, sanity-check
# keys, compose up:
BUNDLE_URL=https://…/krypton-testnet-bundle.tar.gz BUNDLE_SHA256=<sha256> sudo -E ./bootstrap.sh

bootstrap.sh is idempotent. It validates .env, creates DATA_DIR/{el,cl} + NETWORK_DIR (chowned to KRYPTON_UID, 0700), installs the bundle, fails fast if the bundle chainId ≠ the expected id (473374 on testnet), generates the Engine-API JWT (0600) if absent, sanity-checks the validator key, prints a firewall reminder, then docker compose pull && up -d.

Validators: place the key first

Put your priv_validator_key.json at DATA_DIR/cl/config/priv_validator_key.jsonbefore running bootstrap. If absent, bootstrap WARNs and the node will not sign.

The spec is one template, sed-derived per network

There is a single chain-spec template (from-source/spec/krypton.spec.toml). It carries deposit-eth1-chain-id = 47337 as the in-file default, but that line is sed'd to the selected chain-id by both the Dockerfile (bake path) and gen-genesis.sh (genesis path) before use — so CL and EL always agree on the chain-id. All W3 safety params live only in this one template. See Networks & chain IDs.

See also

Operator docs. Testnet chain-id 473374; mainnet 47337 (gated on external audit). Not financial advice.