Repository navigation
fix: v1.0.0 release feedback (docker stop, version note, shutdown log, identity metadata, anchor canonical) - #727
MegaRedHand wants to merge 4 commits into
Conversation
A clean shutdown during catch-up took 14.3 s, past Docker's default 10 s stop timeout, so `docker stop` killed the node mid-flush and lost the state `--stop-signal SIGINT` was there to save. Both `docker run` lines now pass `--stop-timeout 60`. A release binary reports `-rc.N-` in `--version` while the promoted image reports `-stable-`, and only RELEASE.md said why. The release notes link this README, so the explanation goes here too. The `is_syncing` caveat understated the problem: during catch-up it can also flip back and forth, and `/eth/v1/node/health` can answer 200 while the node is far behind.
Every Ctrl+C logged `ERROR Swarm adapter loop exited — P2P networking is no longer functional`, which reads as a crash to an operator. The swarm loop ends when the P2P actor drops its end of either channel, which is how a shutdown reaches it, so that exit is now logged at info. An actor that panicked instead looks the same from the loop, but spawned-concurrency already logs the panic as an error before stopping the actor. Only the swarm's own event stream ending, which never happens while the swarm lives, stays an error.
`metadata` was a hard-coded placeholder (seq 0, no subnets), so it disagreed with the ENR's `attnets` and with what peers get over req/resp. The p2p layer now publishes its MetaData (`seq_number`, `attnets`, `syncnets`) to a shared `MetaDataController` at startup and on every sequence-number bump, all of which go through `BeaconWire::bump_metadata_seq_number`. The endpoint reads it per request, since `syncnets` and the sequence number change when a validator client joins sync committee subnets. `seq_number` stays the MetaData counter, which the p2p specification keeps separate from the ENR's `seq`.
`/eth/v1/beacon/headers/head` answered `canonical: false` while the head was still the checkpoint anchor. `update_checkpoints` keeps `BlockRoots` by diffing the old head against the new one, which never writes the block both start from, and at bootstrap that is the anchor. Lean's `init_store` writes the anchor's row itself; the beacon bootstrap did not. `get_forkchoice_store` now calls `Store::index_beacon_anchor`, which keys the row by the anchor block's slot rather than the anchor state's: a checkpoint state sits at an epoch's first slot, after its latest block whenever that slot was empty. BlocksByRange now serves the anchor block too, which BlocksByRoot already did. Directories bootstrapped before this change still have no row for their anchor, and keep relying on `anchored_root_at_slot` for slot lookups.
🤖 Claude Code ReviewReview of PR 727I read the diff and did not build or run it. The changes are small, well scoped and well documented, and I found no blocking issues. Anchor index (
Identity metadata
Swarm loop exit logging
README and docs
Testing gap
Verdict: looks good to merge once CI is green. Automated review by Claude (Anthropic) · sonnet · custom prompt |
🤖 Kimi Code ReviewI'll review this PR focusing on the areas you specified. This is a substantial change touching P2P metadata handling, fork choice indexing, and RPC endpoints. Overall AssessmentThe PR introduces live Critical Issues1. Potential Deadlock in
|
| Priority | File | Line | Issue |
|---|---|---|---|
| Medium | crates/net/api/src/lib.rs |
471-513 | Consider parking_lot::RwLock; document lock ordering |
| Medium | bin/ethlambda/src/main.rs |
145-161 | Refactor beacon_identity to avoid split construction |
| Low | crates/net/p2p/src/lib.rs |
1301 | Return Option<&MetaDataController> if possible |
| Low | crates/net/rpc/src/beacon/node.rs |
122-126 | Document hardcoded bitfield sizes or make dynamic |
| Low | crates/net/rpc/src/beacon/headers.rs |
157 | Replace unreachable! with proper enum handling |
No critical security vulnerabilities found. The consensus changes (anchor indexing) appear correct and well-tested.
Automated review by Kimi (Moonshot AI) · kimi-k2.6 · custom prompt
🤖 Codex Code ReviewLooks good overall. I did not spot a consensus-critical regression in fork choice, attestation handling, justification/finalization, state transition, XMSS, or SSZ logic from this diff. The two substantive changes both look correct and well-contained.
No obvious security issues jump out from the new code:
Small note:
Automated review by OpenAI Codex · gpt-5.4 · custom prompt |
🗒️ Description / Motivation
Fixes from testing the v1.0.0 release (
ethlambda beaconon mainnet, Docker and the release binary). Four commits, one per finding:docker stopforce-kills after 10 s, but a clean shutdown during catch-up took 14.3 s, so the state was lost--stop-timeout 60on bothdocker runlines--versionsays-rc.2-while the image says-stable-, and only RELEASE.md explains whyERROR ... P2P networking is no longer functional/eth/v1/node/identitymetadatawas a placeholder (seq 0, no subnets), disagreeing with the ENR'sattnetsMetaDatapeers get over req/resp/eth/v1/beacon/headers/headreturnedcanonical: falsewhile the head was still the checkpoint anchorBlockRoots, as lean'sinit_storealready doesNot fixed here:
is_syncingand/eth/v1/node/healthmisreport during catch-up (health200while 80+ slots behind). The cause is that the beacon sync tracker's "freshest block seen" counts only imported blocks, so pending gossip blocks during catch-up look like a network stall. Changing that input has a security trade-off (leanSpec counts only signature-valid blocks so a peer cannot fake freshness), so this PR only widens the README caveat.What Changed
--stop-timeout 60, the version-string note, and a wideris_syncing/health caveat.crates/net/p2p/src/swarm_adapter.rs:swarm_loopbreaks with aLoopExitreason. A channel closed by the P2P actor is a graceful shutdown (info). An actor panic looks the same from here, but spawned-concurrency logs it as an error before stopping the actor.MetaData:ethlambda-network-apigainsMetaDataController/AdvertisedMetaData, a shared handle in theSyncStatusControllermould.BeaconWirepublishes to it at startup and on every sequence-number bump, all of which now go throughBeaconWire::bump_metadata_seq_number(fork digest switch, sync committee subnet join and leave).P2P::local_metadata()hands it tomain.rs, which puts it inBeaconIdentity;get_identityreads it per request.Store::index_beacon_anchorwrites the anchor'sBlockRootsrow, keyed by the anchor block's slot (a checkpoint state sits after its latest block when the epoch's first slot was empty).get_forkchoice_storecalls it right after inserting the anchor block, and so does the RPC test fixture that mirrors it.block_id.rs,docs/data_storage.mdanddocs/rpc.mdupdated.Correctness / Behavior Guarantees
metadata.seq_numberis the MetaData counter, not the ENR'sseq: the p2p specification counts the two separately, so they can still differ.attnetsnow matches the ENR.BeaconBlocksByRangeserves the anchor block too (BlocksByRoot already did). Its data columns were never fetched, so a columns-by-range answer still has none for that slot.anchored_root_at_slot(the head, justified and finalized roots). NoDB_VERSIONbump.MetaData.Tests Added / Run
canonical_is_checked_against_the_indexnow expects the anchor to betrue(it pinned the old gap) and adds a non-canonical sibling that must befalse.index_beacon_anchor_keys_the_row_by_the_blocks_slot(storage),the_beacon_api_copy_follows_every_change(p2p),identity_reports_the_metadata_peers_are_told(rpc).cargo test --profile release-fast --libforethlambda-storage,-rpc,-p2p,-network-api,-state-transition,-blockchain: all pass. leanSpec fixture tests not run.✅ Verification Checklist
make fmt— cleanmake lint(clippy with-D warnings) — cleanmake test(test-consensusplustest-node, atrelease-fast) — only the--libtargets above