Merge pull request #4002 from mkalinin/fix-committee-validation

eip7549: Ensure non-zero bits for each committee bitfield comprising an aggregate
This commit is contained in:
Justin Traglia 2024-11-20 09:25:26 -06:00 committed by GitHub
commit af72bae4e0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 45 additions and 6 deletions

View File

@ -1255,6 +1255,8 @@ def process_operations(state: BeaconState, body: BeaconBlockBody) -> None:
###### Modified `process_attestation`
*Note*: The function is modified to support EIP7549.
```python
def process_attestation(state: BeaconState, attestation: Attestation) -> None:
data = attestation.data
@ -1265,13 +1267,19 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None:
# [Modified in Electra:EIP7549]
assert data.index == 0
committee_indices = get_committee_indices(attestation.committee_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)
participants_count += len(committee)
committee_offset = 0
for committee_index in committee_indices:
assert committee_index < get_committee_count_per_slot(state, data.target.epoch)
committee = get_beacon_committee(state, data.slot, committee_index)
committee_attesters = set(
attester_index for i, attester_index in enumerate(committee)
if attestation.aggregation_bits[committee_offset + i]
)
assert len(committee_attesters) > 0
committee_offset += len(committee)
assert len(attestation.aggregation_bits) == participants_count
# Bitfield length matches total number of participants
assert len(attestation.aggregation_bits) == committee_offset
# Participation flag indices
participation_flag_indices = get_attestation_participation_flag_indices(state, data, state.slot - data.slot)

View File

@ -88,6 +88,7 @@ def test_invalid_nonset_committee_bits(spec, state):
@with_electra_and_later
@spec_state_test
@with_presets([MINIMAL], "need multiple committees per slot")
def test_invalid_nonset_multiple_committee_bits(spec, state):
"""
EIP-7549 test
@ -148,3 +149,33 @@ def test_one_committee_with_gap(spec, state):
next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY)
yield from run_attestation_processing(spec, state, attestation)
@with_electra_and_later
@spec_state_test
@with_presets([MINIMAL], "need multiple committees per slot")
def test_invalid_nonset_bits_for_one_committee(spec, state):
"""
EIP-7549 test
"""
# Attestation with full committee participating
committee_0 = spec.get_beacon_committee(state, state.slot, 0)
attestation_1 = get_valid_attestation(spec, state, index=1, signed=True)
# Create an on chain aggregate
aggregate = spec.Attestation(data=attestation_1.data, signature=attestation_1.signature)
aggregate.committee_bits[0] = True
aggregate.committee_bits[1] = True
aggregate.aggregation_bits = get_empty_eip7549_aggregation_bits(
spec, state, aggregate.committee_bits, aggregate.data.slot
)
committee_offset = len(committee_0)
for i in range(len(attestation_1.aggregation_bits)):
aggregate.aggregation_bits[committee_offset + i] = attestation_1.aggregation_bits[i]
# Check that only one committee is presented
assert spec.get_attesting_indices(state, aggregate) == spec.get_attesting_indices(state, attestation_1)
next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY)
yield from run_attestation_processing(spec, state, aggregate, valid=False)