Skip to content

Commit 8983893

Browse files
authored
Merge pull request #3552 from etan-status/gv-alignaggregate
Align gossip validation for aggregates with single attestations
2 parents 9a54a32 + 321870c commit 8983893

File tree

1 file changed

+9
-4
lines changed

1 file changed

+9
-4
lines changed

specs/phase0/p2p-interface.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -355,17 +355,20 @@ to subscribing nodes (typically validators) to be included in future blocks.
355355

356356
The following validations MUST pass before forwarding the `signed_aggregate_and_proof` on the network.
357357
(We define the following for convenience -- `aggregate_and_proof = signed_aggregate_and_proof.message` and `aggregate = aggregate_and_proof.aggregate`)
358+
- _[REJECT]_ The committee index is within the expected range -- i.e. `aggregate.data.index < get_committee_count_per_slot(state, aggregate.data.target.epoch)`.
358359
- _[IGNORE]_ `aggregate.data.slot` is within the last `ATTESTATION_PROPAGATION_SLOT_RANGE` slots (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) --
359360
i.e. `aggregate.data.slot + ATTESTATION_PROPAGATION_SLOT_RANGE >= current_slot >= aggregate.data.slot`
360361
(a client MAY queue future aggregates for processing at the appropriate slot).
361362
- _[REJECT]_ The aggregate attestation's epoch matches its target -- i.e. `aggregate.data.target.epoch ==
362363
compute_epoch_at_slot(aggregate.data.slot)`
364+
- _[REJECT]_ The number of aggregation bits matches the committee size -- i.e.
365+
`len(aggregate.aggregation_bits) == len(get_beacon_committee(state, aggregate.data.slot, aggregate.data.index))`.
366+
- _[REJECT]_ The aggregate attestation has participants --
367+
that is, `len(get_attesting_indices(state, aggregate.data, aggregate.aggregation_bits)) >= 1`.
363368
- _[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.
364369
(via aggregate gossip, within a verified block, or through the creation of an equivalent aggregate locally).
365370
- _[IGNORE]_ The `aggregate` is the first valid aggregate received for the aggregator
366371
with index `aggregate_and_proof.aggregator_index` for the epoch `aggregate.data.target.epoch`.
367-
- _[REJECT]_ The attestation has participants --
368-
that is, `len(get_attesting_indices(state, aggregate.data, aggregate.aggregation_bits)) >= 1`.
369372
- _[REJECT]_ `aggregate_and_proof.selection_proof` selects the validator as an aggregator for the slot --
370373
i.e. `is_aggregator(state, aggregate.data.slot, aggregate.data.index, aggregate_and_proof.selection_proof)` returns `True`.
371374
- _[REJECT]_ The aggregator's validator index is within the committee --
@@ -378,6 +381,8 @@ The following validations MUST pass before forwarding the `signed_aggregate_and_
378381
(via both gossip and non-gossip sources)
379382
(a client MAY queue aggregates for processing once block is retrieved).
380383
- _[REJECT]_ The block being voted for (`aggregate.data.beacon_block_root`) passes validation.
384+
- _[REJECT]_ The aggregate attestation's target block is an ancestor of the block named in the LMD vote -- i.e.
385+
`get_checkpoint_block(store, aggregate.data.beacon_block_root, aggregate.data.target.epoch) == aggregate.data.target.root`
381386
- _[IGNORE]_ The current `finalized_checkpoint` is an ancestor of the `block` defined by `aggregate.data.beacon_block_root` -- i.e.
382387
`get_checkpoint_block(store, aggregate.data.beacon_block_root, finalized_checkpoint.epoch)
383388
== store.finalized_checkpoint.root`
@@ -425,7 +430,7 @@ The `beacon_attestation_{subnet_id}` topics are used to propagate unaggregated a
425430
to the subnet `subnet_id` (typically beacon and persistent committees) to be aggregated before being gossiped to `beacon_aggregate_and_proof`.
426431

427432
The following validations MUST pass before forwarding the `attestation` on the subnet.
428-
- _[REJECT]_ The committee index is within the expected range -- i.e. `data.index < get_committee_count_per_slot(state, data.target.epoch)`.
433+
- _[REJECT]_ The committee index is within the expected range -- i.e. `attestation.data.index < get_committee_count_per_slot(state, attestation.data.target.epoch)`.
429434
- _[REJECT]_ The attestation is for the correct subnet --
430435
i.e. `compute_subnet_for_attestation(committees_per_slot, attestation.data.slot, attestation.data.index) == subnet_id`,
431436
where `committees_per_slot = get_committee_count_per_slot(state, attestation.data.target.epoch)`,
@@ -439,7 +444,7 @@ The following validations MUST pass before forwarding the `attestation` on the s
439444
- _[REJECT]_ The attestation is unaggregated --
440445
that is, it has exactly one participating validator (`len([bit for bit in attestation.aggregation_bits if bit]) == 1`, i.e. exactly 1 bit is set).
441446
- _[REJECT]_ The number of aggregation bits matches the committee size -- i.e.
442-
`len(attestation.aggregation_bits) == len(get_beacon_committee(state, data.slot, data.index))`.
447+
`len(attestation.aggregation_bits) == len(get_beacon_committee(state, attestation.data.slot, attestation.data.index))`.
443448
- _[IGNORE]_ There has been no other valid attestation seen on an attestation subnet
444449
that has an identical `attestation.data.target.epoch` and participating validator index.
445450
- _[REJECT]_ The signature of `attestation` is valid.

0 commit comments

Comments
 (0)