Status: working PoC note, 2026-07-23.
This note answers three implementation questions:
- What does each decoupled-consensus vote say?
- How is it represented in SSZ?
- What traffic and on-chain load should the PoC model?
The baseline here is the executable
simplex-healing
specification (d8673c6, 2026-07-13). The newer healing paper
(height_filter_healing.tex,
860a1b0, 2026-07-20) is used to identify semantic changes and open
theory-to-spec questions. The binding DC networking parameters remain in
requirements.md.
The vetted DC requirements specify two kinds of traffic:
- AC / available-chain votes from a small per-slot committee.
- FG / finality-gadget votes from the full validator set, divided into pipelined subrounds.
The executable Simplex spec has the same two validator attestation types:
AvailableAttestation, one per available-committee member per slot;Attestation, one per full-set validator per round.
Older AC notes explored merging Goldfish, payload availability, and finality fields into one committee message. That is not the current baseline: a 512-member AC committee cannot replace the supermajority of the full active set needed for finality.
The executable containers are:
class AvailableAttestationData(Container):
slot: Slot
payload_present: boolean
beacon_block_root: Root
class AvailableAttestation(Container):
aggregation_bits: Bitvector[AVAILABLE_COMMITTEE_SIZE] # 512
data: AvailableAttestationData
signature: BLSSignatureSource:
beacon-chain.md.
Conceptually, Goldfish votes for a block head. On the wire it cannot safely be an unqualified root: the signed object also needs time/duty context to prevent replay. The current Gloas-flavoured executable design additionally carries the payload-availability signal.
Exact uncompressed SSZ sizes:
| Object | Calculation | Bytes |
|---|---|---|
AvailableAttestationData |
8 + 1 + 32 |
41 |
AvailableAttestation |
64 + 41 + 96 |
201 |
The 512-bit aggregation vector is 64 bytes. Because it is fixed-size, an individual one-hot message and a fully aggregated message have the same serialized length.
There is no separate "finality chain." The available chain, stabilization gadget, and finality gadget all refer to checkpoints or blocks in the same beacon block tree. The combined fork choice is:
latest justified checkpoint
-> stabilized prefix
-> Goldfish available suffix
The public decoupled-consensus post describes stabilization and finality as one gadget voting round.
The executable containers are:
class Checkpoint(Container):
slot: Slot
root: Root
class AttestationData(Container):
slot: Slot
beacon_block_root: Root
target: Checkpoint
height: Height
finality_target: Checkpoint
finality_height: HeightThe fields mean:
slot: vote time and round context;beacon_block_root: the voter's latest stabilization head;height + target: the checkpoint proposed for justification;finality_height + finality_target: an optional commitment to finalize the latest justified checkpoint.
The three FG vote forms do not use an explicit vote_kind byte:
| Logical vote | Encoding |
|---|---|
| Target / justification | nonzero target, real height |
| Timeout | zero target, real height |
| Empty | zero target, height == 0 |
No finality piggyback is encoded as a zero finality_target and
FAR_FUTURE_HEIGHT.
The individual Electra gossip envelope inherited by Simplex is:
class SingleAttestation(Container):
committee_index: CommitteeIndex
attester_index: ValidatorIndex
data: AttestationData
signature: BLSSignatureSources:
AttestationData
and
SingleAttestation.
Exact uncompressed SSZ sizes:
| Object | Calculation | Bytes |
|---|---|---|
Checkpoint |
8 + 32 |
40 |
AttestationData |
8 + 32 + 40 + 8 + 40 + 8 |
136 |
SingleAttestation |
8 + 8 + 136 + 96 |
248 |
Thus the DC requirement's "individual vote approximately 100 B" is not the size of the current standard SSZ object. A BLS signature alone is 96 bytes. Approximately 100 bytes per signer is plausible only for a compact batch that sends common vote data once and then carries mostly signer positions and signatures. That is a separate wire-format experiment.
An older, now-deprecated networking exploration used:
class FinalityGadgetVote(Container):
height: uint64
block_root: Root
vote_kind: uint8
validator_index: ValidatorIndex
signature: BLSSignatureIts size was 8 + 32 + 1 + 8 + 96 = 145 bytes. It represented the simpler
alphabet Vote(B), Vote(bottom), and SecondVote(B). It is useful for
explaining the old approximately-100-byte assumption, but it lacks the latest
healing design's stabilization head, checkpoint slot, and finality piggyback.
It must not be used as the current PoC schema.
BLS can aggregate many signatures on identical data into one 96-byte signature. The verifier still needs to know exactly which validators signed: their public keys and voting weights determine whether the threshold was reached. Ethereum represents that set with a participation bitfield.
For one million validator seats:
1,000,000 bits / 8 = 125,000 bytes = approximately 122.1 KiB
This is the participation bitmap for one complete full-set round, not one validator's vote.
With ten 100,000-seat subrounds:
100,000 bits / 8 = 12,500 bytes per subround
10 * 12,500 = 125,000 bytes per complete round
SSZ Bitlist serialization adds a termination bit. For one ideal 100,000-seat
subround with one common AttestationData value:
fixed Attestation section 248 bytes
aggregation Bitlist ceil((100000 + 1)/8) 12501 bytes
---------------------------------------------------
on-chain Attestation 12749 bytes
The fixed section includes two four-byte offsets, the 136-byte data, the
96-byte aggregate signature, and the eight-byte mainnet committee bitvector.
The global SignedAggregateAndProof gossip wrapper adds 208 bytes, yielding
12,957 bytes before transport compression.
Ten ideal 100,000-seat on-chain aggregates therefore occupy 127,490 bytes (about 124.5 KiB) across the complete round. The DC explainer's "approximately 12.5 kB per subround" is the same calculation rounded to the dominant bitfield.
An optional HistoricalBlockProof for an old, noncanonical target adds 904
bytes to an on-chain attestation.
Ordinary BLS fast aggregation combines signatures only when validators signed
identical AttestationData. Different:
- stabilization heads;
- justification targets;
- finality piggybacks; or
- slots
require separate Attestation aggregates. Each aggregate carries its own
bitfield and signature. The 12.5 kB estimate is therefore a good-path lower
bound for a subround whose voters largely agree. The PoC should measure
aggregate fragmentation under delayed, partitioned, and healing scenarios.
The latest LaTeX healing paper models an additional ordering step. After
Goldfish confirmation, validator i signs an SG (stabilization gadget) head
pre-vote:
(validator i, round r, head B_i)
Its later FG message repeats the same round and head. The paper calls these two
copies of the same logical head vote. See
Live latest head vote
and the paper's Round schedule and state processing section.
This appeared in the repaired healing protocol on 2026-07-17 (55e88cdc) and
was updated in the canonical healing paper on 2026-07-18 (e7785512).
There is currently:
- no separate SG-pre-vote SSZ container in Francesco's executable spec;
- no third vote stream in the vetted DC networking requirements;
- an explicit open DC question about how healing affects networking and whether SG is on chain.
The executable spec instead uses AttestationData.beacon_block_root as the
network-received SG latest-head vote. A hypothetical direct encoding of the
paper's (validator, round, head) pre-vote would be 144 bytes with BLS, but
that number is an inference, not a specified Ethereum wire object.
For the baseline PoC, do not add a separate SG-pre-vote stream. Treat it as a named experiment or theory-to-spec integration decision.
The networking PoC should initially model:
AvailableAttestationat 201 bytes from a 512-seat committee each slot.SingleAttestationat 248 bytes from each scheduled FG validator.- Standard committee aggregation into the modified
Attestation. - One aggregate-and-proof wrapper per published aggregate.
- Vote-data disagreement and the resulting aggregate fragmentation.
- Vote in slot
i, aggregate ini+1, include ini+2, as specified inexplainer.md.
Run compact batching and a separate healing SG pre-vote only as explicitly labelled variants. This keeps the baseline aligned with both the conservative "standard gossip vertical" decision and the executable specification while making the unresolved healing traffic visible.