Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
af1f6d8
chore(beacon): lay out the interfaces gloas validator duties will share
MegaRedHand Oct 5, 2026
4b160bb
feat(engine): build gloas payloads through forkchoiceUpdatedV4 and ge…
MegaRedHand Oct 5, 2026
a9392c7
feat(validator): pick duty deadlines by the fork of the slot
MegaRedHand Oct 5, 2026
fce2ce2
feat(beacon): key the payload attestation pool by slot, data and vali…
MegaRedHand Oct 5, 2026
c59de8d
feat(validator): propose gloas blocks and reveal the self-built envelope
MegaRedHand Oct 5, 2026
197c93b
feat(validator): attest and aggregate at gloas slots
MegaRedHand Oct 5, 2026
8bb015c
feat(validator): vote on payload timeliness from the committee
MegaRedHand Oct 5, 2026
0e34fd4
Merge feat/beacon-gloas-vd-vc: gloas duties in the validator client
MegaRedHand Oct 5, 2026
a3a587f
feat(beacon): assemble self-built gloas blocks and their payload enve…
MegaRedHand Oct 5, 2026
5edcaf9
feat(beacon): share one payload attestation pool across p2p and the B…
MegaRedHand Oct 5, 2026
53a7977
feat(beacon): gossip payload attestations a validator client signed
MegaRedHand Oct 5, 2026
013f1f9
feat(beacon): serve duties and attestation data at gloas epochs
MegaRedHand Oct 5, 2026
077452f
feat(beacon): accept gloas attestations and aggregates through the po…
MegaRedHand Oct 5, 2026
49bf025
Merge feat/beacon-gloas-vd-attestations: duties, attestations and agg…
MegaRedHand Oct 5, 2026
a5b7650
feat(beacon): record when a block's envelope arrived for payload_present
MegaRedHand Oct 5, 2026
dcf8f16
feat(beacon): serve gloas block production and envelope publication
MegaRedHand Oct 5, 2026
80ee595
feat(beacon): serve PTC duties, payload attestation data and the pool
MegaRedHand Oct 5, 2026
7e1bf4b
feat(beacon): gossip a self-built payload envelope with its data columns
MegaRedHand Oct 5, 2026
5f98361
Merge feat/beacon-gloas-vd-ptc: payload timeliness committee duties a…
MegaRedHand Oct 5, 2026
dce3551
Merge feat/beacon-gloas-vd-production: gloas block production and env…
MegaRedHand Oct 5, 2026
053cb53
test(beacon): port the validator-client tests to the gloas-aware clie…
MegaRedHand Oct 5, 2026
4537abc
docs(beacon): document gloas validator duties
MegaRedHand Oct 5, 2026
2508403
Merge feat/beacon-gloas-vd-docs: document gloas validator duties
MegaRedHand Oct 5, 2026
523f39e
refactor(beacon): expose the per-slot payload attestation aggregation
MegaRedHand Oct 5, 2026
d428c9b
fix(beacon): list the payload attestation pool as aggregates
MegaRedHand Oct 5, 2026
f8df515
test(beacon): drive the validator client end to end at a gloas slot
MegaRedHand Oct 5, 2026
d919fa0
Merge feat/beacon-gloas-vd-e2e: end-to-end gloas validator client tests
MegaRedHand Oct 5, 2026
eb8ab40
docs(beacon): the payload attestation pool is listed as aggregates
MegaRedHand Oct 5, 2026
8d27463
fix(rpc): accept blob-carrying blocks and envelopes over 2 MiB
MegaRedHand Oct 5, 2026
19f204d
Merge branch 'feat/beacon-gloas-live' into feat/beacon-gloas-validato…
MegaRedHand Oct 5, 2026
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
35 changes: 32 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -767,17 +767,46 @@ transitions are in `ethlambda-types`, per the section above. Nothing above
the parking of gloas column sidecars (they carry no signature). Fork-choice
events are timed at arrival, not at the slot tick, and the head's payload
status is kept with its root (`Store::head_payload_status`, recomputed after
a restart). The node stays a follower: the validator-client endpoints still
refuse a gloas epoch (`refuse_validator_duties_from_gloas`).
a restart). The node also serves gloas validator duties, self-build only (no
bids, no proposer preferences; see `docs/spec_deviations.md`).
`state_transition/src/beacon/gloas_block_production.rs` assembles the block and
its envelope (`gloas_payload_inputs`, `parse_gloas_execution_requests`,
`pack_gloas_attestations`, `pack_payload_attestations`, `assemble_gloas_block`,
`gloas_data_column_sidecars`); `rpc/src/beacon/gloas_proposal.rs` serves
`produceBlockV4` and the envelope endpoints (cache of the current and previous
slot's builds; the envelope POST waits up to 4 s for its block, then gossips
the envelope and all column sidecars through `RpcToP2P`, relying on gossipsub
fanout for subnets the node does not subscribe to) and `rpc/src/beacon/ptc.rs`
the PTC duties, payload attestation data and pool. One
`SharedPayloadAttestationPool` is shared by p2p (filled on accepted gossip) and
rpc. The store keeps an in-memory envelope-arrival record
(`insert_beacon_envelope_seen`, keyed by root, pruned with the el-hash cache,
not persisted) that `payload_present` reads against
`fork_choice::get_payload_due_ms`; `helpers::gloas::get_ptc_assignments` backs
the duties. `attestation_data.index` at a gloas slot comes from
`Store::head_payload_status`.
With `--execution-endpoint`, an envelope that passes the consensus checks is
judged by `engine_newPayloadV5` (INVALID with a null `latestValidHash` is a
hash mismatch that refuses only that envelope; INVALID with one condemns the
payload via the execution-chain walk; an engine error keeps the envelope and
retries once a slot, probing with the oldest), and a gloas head sends
`engine_forkchoiceUpdatedV4` with the custody columns (head hash by the head
node's FULL or EMPTY status, finalized and safe from the checkpoint blocks'
`bid.parent_block_hash`, safe being a fallback for fast confirmation). See
`bid.parent_block_hash`, safe being a fallback for fast confirmation). Building
a gloas payload for `produceBlockV4` uses `PayloadAttributesV4` (V3's fields
plus `slot_number` and `target_gas_limit`, the parent bid's gas limit) through
`forkchoice_updated_v4_with_attributes` and `get_payload_v6`
(`BuiltGloasPayload`, `ExecutionPayloadV4`). See
[`docs/beacon_engine.md`](docs/beacon_engine.md).
The validator client (`crates/validator`) at a gloas slot runs: propose at the
boundary (block published bare, then the proposer-signed envelope with
`Eth-Blob-Data-Included: true`, both inside the proposal's attester-offset
budget; an envelope failure is logged and counted, not a failed proposal),
attest at `ATTESTATION_DUE_BPS_GLOAS`, aggregate at `AGGREGATE_DUE_BPS_GLOAS`,
then the PTC vote at `PAYLOAD_ATTESTATION_DUE_BPS`. `SlotClock` picks the
offsets by each slot's own fork, and `/eth/v1/config/spec` supplies them. It
still keeps no slashing-protection record; PTC votes have an in-memory
`(validator, slot)` dedup only, and envelopes are unguarded.
`get_head_node` is one bottom-up walk for every fork, with
the current slot's fork selecting the payload rules and the boost gate, so a
follower on any network that schedules gloas (Sepolia does) pays work
Expand Down
13 changes: 13 additions & 0 deletions bin/ethlambda/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -717,12 +717,17 @@ async fn run_node(options: Options) -> eyre::Result<()> {
// read by the aggregate endpoint and block production; unused on lean.
let attestation_pool =
ethlambda_state_transition::beacon::attestation_pool::SharedAttestationPool::default();
// Filled by gossip and the Beacon API's payload attestation endpoint, read
// by block production and `GET .../pool/payload_attestations`.
let payload_attestation_pool =
ethlambda_state_transition::beacon::payload_attestation_pool::SharedPayloadAttestationPool::default();
let p2p = P2P::spawn(
built,
setup.store.clone(),
setup.node_names,
discovery,
attestation_pool.clone(),
payload_attestation_pool.clone(),
)
.await
.wrap_err("failed to start discv5 discovery")?;
Expand All @@ -734,6 +739,12 @@ async fn run_node(options: Options) -> eyre::Result<()> {
let rpc_sync_status = sync_status.clone();
let rpc_events = events.clone();
let rpc_p2p = p2p.actor_ref().to_rpc_to_p2p_ref();
let rpc_custody_columns = match &setup.chain {
ChainActor::Beacon {
custody_columns, ..
} => ethlambda_rpc::CustodyColumns(custody_columns.clone()),
ChainActor::Lean(..) => ethlambda_rpc::CustodyColumns::default(),
};
// Block production builds its payloads with the same execution client the
// chain actor validates them with.
let rpc_engine = match &setup.chain {
Expand All @@ -757,6 +768,8 @@ async fn run_node(options: Options) -> eyre::Result<()> {
ethlambda_rpc::BeaconApiHandles {
p2p: rpc_p2p,
attestation_pool: attestation_pool.clone(),
payload_attestation_pool: payload_attestation_pool.clone(),
custody_columns: rpc_custody_columns,
engine: rpc_engine,
},
local_peer_id,
Expand Down
5 changes: 5 additions & 0 deletions crates/blockchain/src/beacon_envelope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,11 @@ impl BlockChainServer {
);
self.store
.insert_beacon_block_payload_status(root, slot, status);
// When it arrived, not when it finished verifying: a held envelope is
// verified late, and the committee's `payload_present` asks whether it
// was seen on time.
let seen_ms = held.event_ms.saturating_sub(config.genesis_time_ms());
self.store.insert_beacon_envelope_seen(root, slot, seen_ms);
// Lets `latestValidHash` find this FULL node.
self.store.insert_beacon_el_block_hash(
root,
Expand Down
7 changes: 7 additions & 0 deletions crates/blockchain/state_transition/src/beacon/fork_choice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3530,6 +3530,13 @@ pub fn get_payload_attestation_due_ms(config: &Config) -> u64 {
get_slot_component_duration_ms(config.payload_attestation_due_bps, config)
}

/// `get_payload_due_ms` (gloas `fork-choice.md`): how far into a slot, in
/// milliseconds, an execution payload envelope must have been seen for the
/// payload timeliness committee to vote `payload_present`.
pub fn get_payload_due_ms(config: &Config) -> u64 {
get_slot_component_duration_ms(config.payload_due_bps, config)
}

// ---------------------------------------------------------------------------
// Merge transition helpers (bellatrix)
// ---------------------------------------------------------------------------
Expand Down
Loading
Loading