Skip to content

Add EIP: Batching Attestations at Source#11589

Open
raulk wants to merge 7 commits into
ethereum:masterfrom
raulk:raulk/batching-atts
Open

Add EIP: Batching Attestations at Source#11589
raulk wants to merge 7 commits into
ethereum:masterfrom
raulk:raulk/batching-atts

Conversation

@raulk

@raulk raulk commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

No description provided.

@raulk raulk requested a review from eth-bot as a code owner April 30, 2026 22:43
@github-actions github-actions Bot added c-new Creates a brand new proposal s-draft This EIP is a Draft labels Apr 30, 2026
@eth-bot

eth-bot commented Apr 30, 2026

Copy link
Copy Markdown
Collaborator

File EIPS/eip-8243.md

Requires 1 more review from Editors: @g11tech, @jochem-brouwer, @lightclient, @samwilsn

@github-actions github-actions Bot added the w-ci Waiting on CI to pass label Apr 30, 2026
Comment thread EIPS/eip-batched-attestations.md Outdated
@@ -0,0 +1,397 @@
---
eip: 9999

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
eip: 9999
eip: 8243

@raulk

Assigning next sequential EIP/ERC/RIP number.
Numbers are assigned by editors & associates.

Please also update the filename.

Comment thread EIPS/eip-8243.md Outdated
title: Batching attestations at source
description: Allow validators scheduled for duty on the same committee to publish a single pre-aggregated attestation in place of N individual ones
author: Raúl Kripalani (@raulk), Toni Wahrstätter (@nerolation), Mikhail Kalinin (@mkalinin)
discussions-to:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please create a discussions topic on Eth Magicians using the template
https://ethereum-magicians.org/c/eips/5

Comment thread EIPS/eip-8243.md

### Spam bound

An attacker controlling `k` co-committee keys can produce at most `k` accepted messages per duty: every accepted message must add at least one previously unseen attester to `seen_attesters`, and the attacker's pool of valid attesters has size `k`. Each accepted message carries valid attestation, seal, and batcher signatures, so the attacker's signing cost grows with their bandwidth output. The naive `O(2^k)` subset blowup never propagates: given the attacker's `k` accepted messages, every other subset they could construct has its members fully covered by `seen_attesters` from prior accepts and is dropped silently.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if we make this rule more aggressive: like, a batch is ignored if less than a half of its attesting indices are unseen. In this case SingleAttestation and any batch containing that attestation won’t suppress each other, at the same time the attack complexity reduces to O(log(k)).

I believe fallback batchers will have the same subset of attesters and if either of those two batches reaches different part of the network first, there doesn’t seem to be any harm from suppressing another batch with the same information.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, good flag. If V both submits a SingleAttestation and participates in a batch, the current proposal races. If the SingleAttestation arrives first, it can block the batch from being accepted, unless the client deconflicts and evicts it in favour of the stronger batch.

This race could occur if V decides to attest independently in addition to participating in a batch. This could happen as an operational fallback, or as malicious behaviour.

Generally speaking, the current version assumes high trust between the VC and the beacon node. That assumption may not hold in DVT, LST, and other staking designs. It would be good to loop in various teams and pressure-test against their specific assumptions.

Comment thread EIPS/eip-8243.md
- **Non-consensual inclusion.** A malicious operator cannot construct a batch claiming validators outside their control. BLS forgery is infeasible.
- **Signature theft.** An attacker observing V's `SingleAttestation` cannot replay V's signature into a batch. The seal is over a different domain (`DOMAIN_BATCH_ATTESTER`) and a different message (`BatchSealPreimage`), neither of which V signs when producing a single attestation.

### Why bind the seal to `(slot, committee_index, batcher)` only, and not to `aggregation_bits`?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is smart! 👍

Comment thread EIPS/eip-batched-attestations.md Outdated
| ------------------------------- | -------------------------- | ------------------------------------ |
| `DOMAIN_BATCH_ATTESTER` | `DomainType('0x0B000000')` | Domain for batch seal signatures |
| `DOMAIN_BATCHER` | `DomainType('0x0B0000FF')` | Domain for batcher signatures |
| `BATCH_SUBNET_REDUCTION_FACTOR` | TBD | Power-of-2 reduction in subnet count |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really think this change should be in a separate EIP as it is suggested below. I would like to see the mainnet effect of batching at the source in the first place, and then reduce the subnets as much as that effect allows to.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed -- I left it in the first draft for illustration, to make the potential downstream impact impact of this EIP easier to follow. Higher information density per committee => fewer messages => fewer bytes on the wire per committee => merge committees while keeping traffic constant => fewer slots per epoch => shorter epochs. What if we keep it as as placeholder for now, so it remains easy to frame the benefits in a single spec, then spin it off later?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should remove it from the spec level at some point before moving the EIP status from Draft to Review. The information about this EIP enabling other positive changes can sit in the Motivation section of the EIP

Comment thread EIPS/eip-8243.md
SSZ union for wire transport:

```python
WireAttestation = Union[SingleAttestation, BatchAttestation]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if union is widely supported across all CL clients but even if it is not, it should be easy to support this specific case.

@raulk raulk May 2, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@potuz also flagged this for Prysm, but they're working on SSZ serde redesigin anyway (@kasey). Not sure about other CLs. Rust and other langs have native tagged unions/enums, so I'd expect less friction there.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't used anywhere else, in general, in Ethereum in SSZ. It doesn't seem that warranted here, either.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More typically, the consensus specs would have new subnets for new SSZ types, so there would be BatchAttestation-carrying subnets/(currently-)libp2p topics; is there a reason this is avoided here? It fits more naturally into the rest of the consensus-specs than this approach.

@jochem-brouwer jochem-brouwer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some editorial comments, also address @abcoathup comments 😄 👍

Comment thread EIPS/eip-batched-attestations.md Outdated
@@ -0,0 +1,397 @@
---
eip: 9999
title: Batching attestations at source

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
title: Batching attestations at source
title: Batching attestations at Source

EIP-1 style, title should be Title Case

Comment thread EIPS/eip-batched-attestations.md Outdated
type: Standards Track
category: Consensus
created: 2026-05-01
requires:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If no required EIPs then this should be removed

Suggested change
requires:

Comment thread EIPS/eip-batched-attestations.md Outdated
requires:
---

# EIP-XXXX: Batching attestations at source

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This title will get rendered by the site and should be removed

Suggested change
# EIP-XXXX: Batching attestations at source

Comment thread EIPS/eip-batched-attestations.md Outdated

Ethereum has ~1M active validators today. With 100% participation, every slot triggers N x 1/32 attestations (around 31k), distributed over 64 subnets handling ~485 attestations each. Large operators run many validators, all typically sharing the same consensus view, and therefore typically voting in unison for head.

As we push towards shorter slots and faster finality, we need to drastically reduce the volume of attestations while maintaining protocol and consensus integrity. While EIP-7251 achieves this via validator balance consolidation, uptake has been relatively slow.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
As we push towards shorter slots and faster finality, we need to drastically reduce the volume of attestations while maintaining protocol and consensus integrity. While EIP-7251 achieves this via validator balance consolidation, uptake has been relatively slow.
As we push towards shorter slots and faster finality, we need to drastically reduce the volume of attestations while maintaining protocol and consensus integrity. While [EIP-7251](./eip-7251.md) achieves this via validator balance consolidation, uptake has been relatively slow.

(link EIPs on first ref)

Comment thread EIPS/eip-batched-attestations.md Outdated

This change is largely orthogonal to batching and may be split into a separate EIP.

## Backwards compatibility

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
## Backwards compatibility
## Backwards Compatibility

(sections should be Title Case)

Comment thread EIPS/eip-batched-attestations.md Outdated

TBD.

## Reference implementation

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
## Reference implementation
## Reference Implementation

(sections should be Title Case)

Comment thread EIPS/eip-batched-attestations.md Outdated

Fewer subnets means higher message volume per subnet. Determining the optimal `BATCH_SUBNET_REDUCTION_FACTOR` requires simulation.

## Test cases

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
## Test cases
## Test Cases

(sections should be Title Case)

Comment thread EIPS/eip-batched-attestations.md Outdated

TBD.

## Open questions

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(this should be Title Case as well)

This is not a mandatory section, I would remove it unless there is content there (which might also better fit in Rationale depending on the question)

Comment thread EIPS/eip-batched-attestations.md Outdated

## Copyright

Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
## Copyright
Copyright and related rights waived via [CC0](../LICENSE.md).

(the URL is not allowed)

Comment thread EIPS/eip-batched-attestations.md Outdated

### Leaked singles do not suppress batches

A validator V issuing both a `SingleAttestation` and a seal to batcher B (for example, due to misconfigured active-active VC redundancy) does not cause B's batch to be suppressed. The batch carries V's vote alongside others; if V's single arrives first, the batch is still accepted because its other members' votes are unseen. Conversely, if the batch arrives first, V's redundant single is dropped. In all orderings, no vote is lost, no party is penalized, and the on-chain `Attestation` reflects V exactly once.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the VC here? Is it a typo? If it is an abbreviation then it should be defined before abbreviating it

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eth-bot eth-bot added e-consensus Waiting on editor consensus e-review Waiting on editor to review labels May 25, 2026
@eth-bot eth-bot changed the title Add EIP: Batching attestations at source Add EIP: Batching Attestations at Source May 25, 2026
@github-actions github-actions Bot removed the w-ci Waiting on CI to pass label May 25, 2026
@raulk raulk force-pushed the raulk/batching-atts branch from b32d640 to a0e1e50 Compare May 25, 2026 14:18
@github-actions

Copy link
Copy Markdown

The commit a0e1e50 (as a parent of 0179e95) contains errors.
Please inspect the Run Summary for details.

@github-actions github-actions Bot added the w-ci Waiting on CI to pass label May 25, 2026

@mkalinin mkalinin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work! 👍 I left a few comments, other than that looks good to me

Comment thread EIPS/eip-8243.md Outdated
# Identifies the validator authorized to compose this batch.
batcher: ValidatorIndex
# Aggregate of seals from every validator indicated by `aggregation_bits`,
# over `BatchSealPreimage(slot, committee_index, batcher)`,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# over `BatchSealPreimage(slot, committee_index, batcher)`,
# over `BatchSealPreimage(data.slot, committee_index, batcher)`,

I think the slot must match data.slot

@raulk raulk May 27, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, fixed in f080c86. The BatchAttestation container carries slot indirectly via data.slot, so the docstring should reflect that.

Comment thread EIPS/eip-8243.md Outdated
# under DOMAIN_BATCH_ATTESTER.
# Gossip-only; discarded after validation.
batch_seal: BLSSignature
# Batcher's signature over `BatcherPreimage(slot, committee_index, aggregation_bits)`,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Batcher's signature over `BatcherPreimage(slot, committee_index, aggregation_bits)`,
# Batcher's signature over `BatcherPreimage(data.slot, committee_index, aggregation_bits)`,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in f080c86, same rationale as above.

Comment thread EIPS/eip-8243.md Outdated
### Helper functions

```python
def is_batch(att: WireAttestation) -> bool:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this function is unused

@raulk raulk May 27, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, is_batch is dead: the validators dispatch on att.selector directly. Removed in f080c86.

Replace the strawmap inline link with plain text and add the
ethereum-magicians thread ID (28606) to satisfy markdown-rel-links
and preamble-re-discussions-to.

Address mkalinin review comments: refer to `data.slot` in the
BatchSealPreimage and BatcherPreimage docstring blocks (since
BatchAttestation carries the slot via `data`), and drop the unused
`is_batch` helper.

Convert remaining inline links to reference-style at the bottom.
@github-actions github-actions Bot removed the w-ci Waiting on CI to pass label May 27, 2026
Comment thread EIPS/eip-8243.md

| Name | Value | Description |
| ----------------------- | -------------------------- | -------------------------------- |
| `DOMAIN_BATCH_ATTESTER` | `DomainType('0x0B000000')` | Domain for batch seal signatures |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This clashes with DOMAIN_BEACON_BUILDER

Comment thread EIPS/eip-8243.md
return False

pubkey = state.validators[att.attester_index].pubkey
return bls.Verify(pubkey, compute_signing_root(att.data), att.signature)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

compute_signing_root is missing domain

Comment thread EIPS/eip-8243.md

# Resolve attester indices
committee = get_beacon_committee(state, att.data.slot, att.committee_index)
attesters = [committee[i] for i, bit in enumerate(att.aggregation_bits) if bit]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should there be a length check?

if len(att.aggregation_bits) != len(committee):
      return False

Comment thread EIPS/eip-8243.md
```

```python
def is_valid_wire_attestation(state: BeaconState, att: WireAttestation) -> bool:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe safer this way?

Suggested change
def is_valid_wire_attestation(state: BeaconState, att: WireAttestation) -> bool:
def is_valid_wire_attestation(state: BeaconState, att: WireAttestation) -> bool:
if att.selector == 0x00:
return is_valid_single_attestation(state, att.value)
elif att.selector == 0x01:
return is_valid_batch_attestation(state, att.value)
else:
return False

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c-new Creates a brand new proposal e-consensus Waiting on editor consensus e-review Waiting on editor to review s-draft This EIP is a Draft t-core

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants