Repository navigation
Conversation
…slashing-protection import
…mport the per-key watermark at start
…offset and live cut-off; assert the target after generation
Envelopes go with Eth-Blob-Data-Included: true and empty blobs, as an outside publisher must, and with broadcast_validation=consensus, since Grandine only imports them on that path. Each envelope is confirmed by GET of the envelope, or for Prysm by its EL head reaching the payload, which also stops Prysm's goroutine-sent forkchoice updates from reordering. Gloas blocks are posted bare. The report records each node's EL head, since Grandine leaves it one payload behind until the next head change.
…tional services main.star returns early when additional_services is empty, before the wait_for_finalization block, so the per-node target check never ran in the usual fast_forward config. The check now runs before that return.
…insertion In a Fulu-genesis, Gloas-at-epoch-3 run, Nimbus, Lighthouse and Grandine reached the generated head within 5 s while Prysm was at block 12. Prysm's resyncIfBehind saw peers two epochs ahead and reverted to initial sync, so it answered 503 and range-synced the rest, reaching the head after 276 s with a 23-slot handover gap. Lighthouse did the same in another run: a peer more than 32 slots ahead made it open a head-chain range sync that never completed, leaving is_syncing true. Pacing the fast nodes keeps every peer within one epoch, so neither triggers.
…until resolved to
…t times, pick the handover slot once every slow step is done, start VCs just before it; Grandine loads its in-process keys through the keymanager
…the generated chain's last finalized checkpoint fast_forward.history picks how beacon nodes get the generated history: - checkpoint (default): ff-gen runs before any beacon node, while checkpoint.py feeds every EL the payloads up to the generator's current finalized checkpoint (and finally up to the anchor, never past it, with a forkchoice update every 32 payloads). The anchor block, post-state and envelope plus the blocks after it are stored; ff-checkpoint serves the anchor (and the genesis state for Prysm) as a beacon API, every CL checkpoint-syncs from it, and insert.py publishes only the tail, starting with the anchor's envelope. - full: the previous path, publishing every block from genesis. A chain with no finalized checkpoint after genesis (history ending before epoch 3) falls back to full. Also: ff-reth gets a 64 MB MDBX growth step (the default 4 GB step filled the container layer) and is removed once generation ends, the generated history is deleted from the run's container after use, the live fork cut-off uses ff-gen --max-slot so generation keeps following the wall clock, and the generation and insert waits scale with the history length.
In the checkpoint path the payloads, blocks and envelopes before the finalized checkpoint are never read again once every EL has them, so the feeder deletes them as it goes and the run's disk use stays at a few epochs of files instead of growing with the history.
…s its root After checkpoint sync the anchor's children carry an older justified checkpoint than the anchor, so Lighthouse imports them without making them head; waiting for the head slot made it time out on the first tail block.
Teku checkpoint-syncs from the state alone, has no anchor block, and answers 400 to the anchor's envelope; it still imports the tail. Post the anchor envelope once with a short wait, record a rejection, and carry on.
…sses the payload When later blocks arrive by gossip, Prysm's EL head can move past a payload between two polls, so waiting for the head to equal it timed out and stopped the publish to that node. Accept a head at or beyond the payload's number whose chain holds the payload's hash.
history: checkpoint now ends in the same glide-path handover as history: full. Both modes generate 32 slots past the wall clock (timeskip --ahead-slots), publish up to the wall slot, and drip the rest at slot times. The tail keeps interchange.json and attesters.json for the drip's watermark. The generator is the timeskip image (ghcr.io/ethpandaops/timeskip), with TIMESKIP_MNEMONIC and a python3 entrypoint for the checkpoint server.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Summary
Adds fast_forward: genesis is placed in the past, timeskip generates the history against a private reth, ELs are fed (checkpoint path) or blocks are inserted (full path), and VCs take over at a slot boundary with imported slashing protection. The fast-forward machinery itself checks out against the real timeskip CLI/output contract and is internally consistent. The real problem is unrequested scaffolding that silently changes default behavior for kt- remote-enclave networks, activating duplicate validators on a live source enclave.
Issues
- 🔴
src/package_io/input_parser.star:1797— kt- networks no longer auto-zero validator counts, silently activating duplicate validators — The zeroing exclusion plus remote_enclave.star:68 generating keystores whenever a mnemonic exists (always — preregistered_validator_keys_mnemonic is validated non-empty) means every kt- run now boots in-process validators derived from the same mnemonic the source enclave runs, with no slashing-protection import on this path (load_in_process_keys only runs when fast_forward is enabled, which resolve_fast_forward forbids for kt-). B's validators duplicate A's live validators and can double-propose, slashing them and forking the source chain — contradicting README.md:200 ('Validator counts are auto-zeroed for kt- networks, so B is observer-mode by default'), which this PR does not update. This should be gated on an explicit opt-in or reverted. - 🟡
src/participant_network.star:259— ff-el-feed-gate hijacks checkpoint_sync_url on kt- networks — see the thread on that line
Reviewed @ ec07b02d
"Weeks of coding can save you hours of planning."
| constants.NETWORK_NAME.remote_enclave | ||
| ) and args_with_right_defaults.checkpoint_sync_url.startswith("http"): | ||
| plan.run_sh( | ||
| name="ff-el-feed-gate", |
There was a problem hiding this comment.
🟡 ff-el-feed-gate hijacks checkpoint_sync_url on kt- networks
For any kt- network with checkpoint_sync_url set (e.g. pointing at the source enclave's beacon API), the launch now blocks forever on wget {url}/ff/ready and fails after the 20 m wait, instead of checkpoint-syncing as before. The gate should key off a dedicated fast-forward input, not reuse checkpoint_sync_url.
Adds
fast_forward, which starts a fresh kurtosis network already finalized: genesis goes in the past, timeskip generates every slot since then against a private reth, the chain goes into every beacon node, and the validator clients take over at a slot boundary with slashing protection for the generated history.untilsets where the generated history ends, as a fork or epoch plus a state (activating,activated,justifiedorfinalized);activatinghands overslots_beforeslots (default 10) ahead of the fork, so the transition runs live. With the defaulthistory: checkpoint, beacon nodes checkpoint-sync from the generated finalized checkpoint and only the later blocks are published, which keeps long histories such as Gloas at epoch 1000 practical. A Gloas-at-genesis Lighthouse + Prysm network comes back fromkurtosis runfinalized in about 50 s, instead of after about 26 minutes.