Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ crates/
├─ src/lib.rs # BlockChain actor, tick events, validator duties
├─ src/store.rs # Fork choice store, block/attestation processing
├─ src/block_builder.rs # Block assembly (pre-built at previous slot's interval 4)
├─ src/aggregation.rs # Interval-2 signature aggregation worker
├─ src/aggregation.rs # Always-on signature aggregation worker (+ body-proof jobs)
├─ src/body_proof.rs # Candidate block bodies: build, buffer, and the proposer's choice
├─ src/reaggregate.rs # Re-aggregation of block-borne votes on import
├─ src/sync_status.rs # Sync-gate tracker (suppresses duties while syncing)
├─ src/key_manager.rs # Validator key management and signing
Expand Down Expand Up @@ -54,12 +55,15 @@ crates/

### Tick-Based Validator Duties (4-second slots, 5 intervals per slot)
```
Interval 0: Block published (at the slot boundary). The build+publish code path is merged into the previous slot's interval 4 (see below) and aligned to publish here; no attestation acceptance happens at interval 0.
Interval 0: Accept attestations (if proposing), then assemble+publish our block from the buffered BlockBodyProof candidates (or an empty body)
Interval 1: Attestation production (all validators, including proposer)
Interval 2: Aggregation (aggregators create proofs from gossip signatures)
Interval 2: Publish the aggregates the always-on worker produced since the last such interval
Interval 3: Safe target update (fork choice)
Interval 4: Accept accumulated attestations; build the NEXT slot's block and publish it aligned to that slot's interval 0 (build and publish merged into this tick)
Interval 4: Accept accumulated attestations; the worker packs the NEXT slot's candidate BlockBodyProof, gossiped as it finishes
```
Aggregation itself is NOT interval-bound: one always-on `spawn_blocking` worker holds a
`Store` clone and proves the best job it can find, continuously (`aggregation.rs`). The
intervals above only govern *publication*.

### Attestation Pipeline
```
Expand Down Expand Up @@ -274,8 +278,8 @@ actual_slot = finalized_slot + 1 + relative_index

### Protocols
- **Transport**: QUIC over UDP (TLS 1.3)
- **Gossipsub**: Blocks + Attestations (snappy raw compression)
- Topic: `/leanconsensus/{fork_digest}/{block|aggregation|attestation_N}/ssz_snappy`
- **Gossipsub**: Blocks + Attestations + candidate block bodies (snappy raw compression)
- Topic: `/leanconsensus/{fork_digest}/{block|aggregation|block_body_proof|attestation_N}/ssz_snappy`
- `fork_digest` is a 4-byte hex string (no `0x` prefix); currently the dummy `12345678` agreed across clients
- Mesh size: 8 (6-12 bounds), heartbeat: 700ms
- **Req/Resp**: Status, BlocksByRoot, BlocksByRange (snappy frame compression + varint length)
Expand Down Expand Up @@ -343,7 +347,7 @@ incremental, and line-tables-only debuginfo, so rebuilds are much faster than
### Aggregator Flag Required for Finalization
- At least one node **must** be started with `--is-aggregator` to finalize blocks
- Without this flag, attestations pass signature verification and are logged as "Attestation processed", but the signature is never stored for aggregation (the `is_aggregator` gate in `on_gossip_attestation`, `store.rs`), so blocks are always built with `attestation_count=0`
- The attestation pipeline: gossip → verify signature → store gossip signature (only if `is_aggregator`) → aggregate at interval 2 → promote to known → pack into blocks
- The attestation pipeline: gossip → verify signature → store gossip signature (only if `is_aggregator`) → aggregate on the always-on worker → publish at interval 2 → promote to known → packed into a candidate body proof at interval 4
- **Symptom**: `justified_slot=0` and `finalized_slot=0` indefinitely despite healthy block production and attestation gossip

### Runtime Aggregator Toggle (Hot-Standby Model)
Expand Down
4 changes: 2 additions & 2 deletions bin/ethlambda/src/benchmark/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use ethlambda_blockchain::block_builder::ProposerConfig;
use ethlambda_blockchain::metrics::BLOCK_PROPOSAL_ATTESTATION_BUILD_PHASES;
use ethlambda_blockchain::store::{on_block_without_verification, produce_block_with_signatures};
use ethlambda_storage::{NEW_PAYLOAD_CAP, Store};
use ethlambda_types::block::{MultiMessageAggregate, SignedBlock};
use ethlambda_types::block::{BlockProof, SignedBlock};
use ethlambda_types::primitives::HashTreeRoot as _;
use eyre::WrapErr as _;

Expand Down Expand Up @@ -247,7 +247,7 @@ fn build_one_slot(
// index.
let signed_block = SignedBlock {
message: block,
proof: MultiMessageAggregate::default(),
proof: BlockProof::default(),
};
on_block_without_verification(store, signed_block)
.wrap_err_with(|| format!("importing the built block failed at slot {slot}"))?;
Expand Down
Loading
Loading