freecoding.school100% FREE · NO SIGNUP
The EVM CoreISSUE #2 of 48

attestations · committees · aggregation

SoliaVSThe Reentrancy Reaper
Solia saysEach slot, 1/32 of validators attest to the head and the FFG checkpoints; BLS aggregation collapses millions of signatures into a handful of bytes per epoch.

Every active validator attests once per epoch. The set is split into 32 slot committees — one per slot — and within each slot further into up to 64 sub-committees that aggregate in parallel. Each attestation carries three claims: a head vote (LMD-GHOST), an FFG source checkpoint, and an FFG target.

Without aggregation, a million validators each emitting a 96-byte BLS signature per epoch would be ~100 MB. BLS signature aggregation collapses that to one signature per committee per slot — kilobytes. The demo computes the committee math and the aggregation savings for a 1M-validator set.

Power-ups you unlock

The Reentrancy Reaper attacks — common mistakes

Boss battleGiven 1M validators and 32 slots/epoch, compute per-slot attesters, per-committee size, and the aggregation byte savings.

Example code

<!doctype html><html><head><meta charset="utf-8"></head>
<body style="background:#06040d;color:#e6e0ff;font-family:monospace;padding:20px"><pre id="o"></pre>
<script>
const N = 1000000;
const slotsPerEpoch = 32;
const validatorsPerSlot = Math.floor(N / slotsPerEpoch);
const committeesPerSlot = 64;
const committeeSize = Math.floor(validatorsPerSlot / committeesPerSlot);
const bytesPerSig = 96;
const rawSigBytes = N * bytesPerSig;
const aggSigBytes = committeesPerSlot * slotsPerEpoch * bytesPerSig;
document.getElementById('o').textContent = [
  N.toLocaleString() + ' validators · ' + slotsPerEpoch + ' slots/epoch:',
  '  per-slot sub-committees:    ' + committeesPerSlot,
  '  per-slot total attesters:   ' + validatorsPerSlot.toLocaleString(),
  '  per-sub-committee size:     ' + committeeSize.toLocaleString(),
  '  attestations per epoch:     ' + N.toLocaleString() + ' (every validator)',
  '',
  'BLS aggregation savings per epoch:',
  '  raw signatures:    ' + (rawSigBytes/1e6).toFixed(1) + ' MB',
  '  aggregated:        ' + (aggSigBytes/1e3).toFixed(1) + ' KB',
  '  reduction:         ' + Math.round(rawSigBytes / aggSigBytes) + '×'
].join('\n');
</script></body></html>
▶ Open the interactive comic issue
‹ The Beacon Chain · The Consensus LayerSync Committees · Light-Client Support ›