Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

eip7549: flatten aggregate_bits #3631

Merged
merged 2 commits into from
Mar 26, 2024
Merged
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
15 changes: 10 additions & 5 deletions specs/_features/eip7549/beacon-chain.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ This is the beacon chain specification to move the attestation committee index o

```python
class Attestation(Container):
aggregation_bits: List[Bitlist[MAX_VALIDATORS_PER_COMMITTEE], MAX_COMMITTEES_PER_SLOT] # [Modified in EIP7549]
aggregation_bits: Bitlist[MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT] # [Modified in EIP7549]
data: AttestationData
committee_bits: Bitvector[MAX_COMMITTEES_PER_SLOT] # [New in EIP7549]
signature: BLSSignature
Expand Down Expand Up @@ -83,12 +83,15 @@ def get_attesting_indices(state: BeaconState, attestation: Attestation) -> Set[V

output = set()
committee_indices = get_committee_indices(attestation.committee_bits)
committee_offset = 0
for index in committee_indices:
attesting_bits = attestation.aggregation_bits[index]
committee = get_beacon_committee(state, attestation.data.slot, index)
committee_attesters = set(index for i, index in enumerate(committee) if attesting_bits[i])
committee_attesters = set(
index for i, index in enumerate(committee) if attestation.aggregation_bits[committee_offset + i])
output = output.union(committee_attesters)

committee_offset += len(committee)

return output
```

Expand All @@ -106,11 +109,13 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None:
# [Modified in EIP7549]
assert data.index == 0
committee_indices = get_committee_indices(attestation.committee_bits)
assert len(committee_indices) == len(attestation.aggregation_bits)
participants_count = 0
for index in committee_indices:
assert index < get_committee_count_per_slot(state, data.target.epoch)
committee = get_beacon_committee(state, data.slot, index)
assert len(attestation.aggregation_bits[index]) == len(committee)
participants_count += len(committee)

assert len(attestation.aggregation_bits) == participants_count

# Participation flag indices
participation_flag_indices = get_attestation_participation_flag_indices(state, data, state.slot - data.slot)
Expand Down
6 changes: 2 additions & 4 deletions specs/_features/eip7549/p2p-interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,17 @@ The `beacon_aggregate_and_proof` and `beacon_attestation_{subnet_id}` topics are

The following convenience variables are re-defined
- `index = get_committee_indices(aggregate.committee_bits)[0]`
- `aggregation_bits = aggregate.aggregation_bits[0]`

The following validations are added:
* [REJECT] `len(committee_indices) == len(aggregate.attestation_bits) == 1`, where `committee_indices = get_committee_indices(aggregate)`.
* [REJECT] `len(committee_indices) == 1`, where `committee_indices = get_committee_indices(aggregate)`.
* [REJECT] `aggregate.data.index == 0`

###### `beacon_attestation_{subnet_id}`

The following convenience variables are re-defined
- `index = get_committee_indices(attestation.committee_bits)[0]`
- `aggregation_bits = attestation.aggregation_bits[0]`

The following validations are added:
* [REJECT] `len(committee_indices) == len(attestation.attestation_bits) == 1`, where `committee_indices = get_committee_indices(attestation)`.
* [REJECT] `len(committee_indices) == 1`, where `committee_indices = get_committee_indices(attestation)`.
* [REJECT] `attestation.data.index == 0`

17 changes: 9 additions & 8 deletions specs/_features/eip7549/validator.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@ def compute_on_chain_aggregate(network_aggregates: List[Attestation]) -> Attesta
aggregates = sorted(network_aggregates, key=lambda a: get_committee_indices(a.committee_bits)[0])

data = aggregates[0].data
aggregation_bits = [a.aggregation_bits[0] for a in aggregates]
aggregation_bits = Bitlist[MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT]()
for a in aggregates:
for b in a.aggregation_bits:
aggregation_bits.append(b)

signature = bls.Aggregate([a.signature for a in aggregates])

committee_indices = [get_committee_indices(a.committee_bits)[0] for a in aggregates]
Expand All @@ -50,10 +54,8 @@ def compute_on_chain_aggregate(network_aggregates: List[Attestation]) -> Attesta
#### Construct attestation

- Set `attestation_data.index = 0`.
- Let `aggregation_bits` be a `Bitlist[MAX_VALIDATORS_PER_COMMITTEE]` of length `len(committee)`, where the bit of the index of the validator in the `committee` is set to `0b1`.
- Set `attestation.aggregation_bits = [aggregation_bits]`, a list of length 1
- Let `committee_bits` be a `Bitvector[MAX_COMMITTEES_PER_SLOT]`, where the bit at the index associated with the validator's committee is set to `0b1`
- Set `attestation.committee_bits = committee_bits`
- Let `attestation.aggregation_bits` be a `Bitlist[MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT]` of length `len(committee)`, where the bit of the index of the validator in the `committee` is set to `0b1`.
- Let `attestation.committee_bits` be a `Bitvector[MAX_COMMITTEES_PER_SLOT]`, where the bit at the index associated with the validator's committee is set to `0b1`.

*Note*: Calling `get_attesting_indices(state, attestation)` should return a list of length equal to 1, containing `validator_index`.

Expand All @@ -62,7 +64,6 @@ def compute_on_chain_aggregate(network_aggregates: List[Attestation]) -> Attesta
#### Construct aggregate

- Set `attestation_data.index = 0`.
- Let `aggregation_bits` be a `Bitlist[MAX_VALIDATORS_PER_COMMITTEE]` of length `len(committee)`, where each bit set from each individual attestation is set to `0b1`.
- Set `attestation.aggregation_bits = [aggregation_bits]`, a list of length 1
- Set `attestation.committee_bits = committee_bits`, where `committee_bits` has the same value as in each individual attestation
- Let `aggregation_bits` be a `Bitlist[MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT]` of length `len(committee)`, where each bit set from each individual attestation is set to `0b1`.
- Set `attestation.committee_bits = committee_bits`, where `committee_bits` has the same value as in each individual attestation.

2 changes: 1 addition & 1 deletion specs/phase0/p2p-interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ The following validations MUST pass before forwarding the `signed_aggregate_and_
- _[REJECT]_ The aggregate attestation's epoch matches its target -- i.e. `aggregate.data.target.epoch ==
compute_epoch_at_slot(aggregate.data.slot)`
- _[REJECT]_ The number of aggregation bits matches the committee size -- i.e.
`len(aggregation_bits) == len(get_beacon_committee(state, aggregate.data.slot, aggregate.data.index))`.
`len(aggregation_bits) == len(get_beacon_committee(state, aggregate.data.slot, index))`.
- _[REJECT]_ The aggregate attestation has participants --
that is, `len(get_attesting_indices(state, aggregate)) >= 1`.
- _[IGNORE]_ A valid aggregate attestation defined by `hash_tree_root(aggregate.data)` whose `aggregation_bits` is a non-strict superset has _not_ already been seen.
Expand Down
Loading