From bc8ff33a371768cc2347fc68bc154d3984203d60 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Tue, 22 Oct 2019 15:49:50 +0800 Subject: [PATCH 01/17] working through attestation aggregation --- specs/networking/p2p-interface.md | 4 +- specs/validator/0_beacon-chain-validator.md | 80 +++++++++++++++++++-- 2 files changed, 78 insertions(+), 6 deletions(-) diff --git a/specs/networking/p2p-interface.md b/specs/networking/p2p-interface.md index c9bab8406..ed63281b4 100644 --- a/specs/networking/p2p-interface.md +++ b/specs/networking/p2p-interface.md @@ -164,9 +164,9 @@ Unaggregated and aggregated attestations from all shards are sent to the `beacon #### Mainnet -Shards are grouped into their own subnets (defined by a shard topic). The number of shard subnets is defined via `SHARD_SUBNET_COUNT` and the shard `shard_number % SHARD_SUBNET_COUNT` is assigned to the topic: `shard{shard_number % SHARD_SUBNET_COUNT}_beacon_attestation`. Unaggregated attestations are sent to the subnet topic. Aggregated attestations are sent to the `beacon_attestation` topic. +Attestation broadcasting is grouped into subnets defined by a topic. The number of subnets is defined via `ATTESTATION_SUBNET_COUNT`. The `CommitteeIndex`, `index`, is assigned to the topic: `index{index % ATTESTATION_SUBNET_COUNT}_beacon_attestation`. -TODO: [aggregation strategy](https://github.com/ethereum/eth2.0-specs/issues/1331) +Unaggregated attestations are sent to the subnet topic, `index{attestation.data.index % ATTESTATION_SUBNET_COUNT}_beacon_attestation`. Aggregated attestations are sent to the `beacon_attestation` topic. ### Messages diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index 1be028df4..8e36e649f 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -37,7 +37,7 @@ - [Attestations](#attestations) - [Deposits](#deposits) - [Voluntary exits](#voluntary-exits) - - [Attestations](#attestations-1) + - [Attesting](#attesting) - [Attestation data](#attestation-data) - [LMD GHOST vote](#lmd-ghost-vote) - [FFG vote](#ffg-vote) @@ -46,6 +46,15 @@ - [Aggregation bits](#aggregation-bits) - [Custody bits](#custody-bits) - [Aggregate signature](#aggregate-signature) + - [Broadcast attestation](#broadcast-attestation) + - [Attestation aggregation](#attestation-aggregation) + - [Construct aggregate](#construct-aggregate) + - [Data](#data-1) + - [Aggregation bits](#aggregation-bits-1) + - [Custody bits](#custody-bits-1) + - [Aggregate signature](#aggregate-signature-1) + - [Broadcast aggregate](#broadcast-aggregate) + - [How to avoid slashing](#how-to-avoid-slashing) - [Proposer slashing](#proposer-slashing) - [Attester slashing](#attester-slashing) @@ -272,11 +281,11 @@ The `proof` for each deposit must be constructed against the deposit root contai Up to `MAX_VOLUNTARY_EXITS`, [`VoluntaryExit`](../core/0_beacon-chain.md#voluntaryexit) objects can be included in the `block`. The exits must satisfy the verification conditions found in [exits processing](../core/0_beacon-chain.md#voluntary-exits). -### Attestations +### Attesting A validator is expected to create, sign, and broadcast an attestation during each epoch. The `committee`, assigned `index`, and assigned `slot` for which the validator performs this role during an epoch are defined by `get_committee_assignment(state, epoch, validator_index)`. -A validator should create and broadcast the attestation halfway through the `slot` during which the validator is assigned―that is, `SECONDS_PER_SLOT * 0.5` seconds after the start of `slot`. +A validator should create and broadcast the `attestation` to the associated attestation subnet one-third of the way through the `slot` during which the validator is assigned―that is, `SECONDS_PER_SLOT / 3` seconds after the start of `slot`. #### Attestation data @@ -314,7 +323,7 @@ Set `attestation.data = attestation_data` where `attestation_data` is the `Attes ##### Aggregation bits -- Let `attestation.aggregation_bits` be a `Bitlist[MAX_VALIDATORS_PER_COMMITTEE]` where the bits at the index in the aggregated validator's `committee` is set to `0b1`. +- Let `attestation.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`. *Note*: Calling `get_attesting_indices(state, attestation.data, attestation.aggregation_bits)` should return a list of length equal to 1, containing `validator_index`. @@ -339,6 +348,69 @@ def get_signed_attestation_data(state: BeaconState, attestation: IndexedAttestat return bls_sign(privkey, hash_tree_root(attestation_data_and_custody_bit), domain) ``` +#### Broadcast attestation + +Finally, the validator broadcasts `attestation` to the associated attestation subnet -- the `index{attestation.data.index % ATTESTATION_SUBNET_COUNT}_beacon_attestation` pubsub topic. + +## Attestation aggregation + +The validator is expected to locally aggregate attestations with a similar `attestation_data` to their constructed `attestation` for the assigned `slot`. + +The validator then _might_ broadcast their best aggregate to a global attestation channel two-thirds of the way through the `slot`-that is, `SECONDS_PER_SLOT * 2 / 3` seconds after the start of `slot`. + +#### Construct aggregate + +Collect `attestations` seen via gossip during the `slot` that have an equivalent `attestation_data` to that constructed by the validator. + +The validator should create an `aggregate_attestation` with the following fields. + +##### Data + +Set `aggregate_attestation.data = attestation_data` where `attestation_data` is the `AttestationData` object that is the same for each individual attestation being aggregated. + +##### Aggregation bits + +Let `aggregate_attestation.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`. + +##### Custody bits + +- Let `aggregate_attestation.custody_bits` be a `Bitlist[MAX_VALIDATORS_PER_COMMITTEE]` filled with zeros of length `len(committee)`. + +*Note*: This is a stub for Phase 0. + +##### Aggregate signature + +Set `aggregate_attestation.signature = aggregate_signature` where `aggregate_signature` is obtained from: + +```python +def get_aggregate_signature(attestations: Attestation) -> BLSSignature: + signatures = [attestation.signature for attestation in attestations] + aggregate_signature = bls_aggregate_signatures(signatures) + return aggregate_signature +``` + +#### Broadcast aggregate + +Starting two-thirds of the way into the slot, the validator begins running the following routine to decide if their best aggregate should be broadcast to the global attestation channel (`beacon_attestation`). `seen()` is defined as having seen an aggregate + +```python +def should_broadcast_aggregate(aggregate_attestation: Attestation, index: ValidatorIndex) -> bool: + if seen(index): + return False + if random.randrange(SIDED_DIE) == 0: + return True + time.sleep(WAIT // 1000) +``` + +Define `seen_better(aggregate_attestation, attestations)` as your aggregate +having more attestations included than any in the attestations you've seen on +the network so far. Could also make it better by _some_ amount. + +```python +def have_better_aggregate(aggregate_attestation, attestations): + +``` + ## How to avoid slashing "Slashing" is the burning of some amount of validator funds and immediate ejection from the active validator set. In Phase 0, there are two ways in which funds can be slashed: [proposer slashing](#proposer-slashing) and [attester slashing](#attester-slashing). Although being slashed has serious repercussions, it is simple enough to avoid being slashed all together by remaining _consistent_ with respect to the messages a validator has previously signed. From a9c21125715497dd8362a640a1155b048438f5ec Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Wed, 23 Oct 2019 17:13:01 +0900 Subject: [PATCH 02/17] add bulk of naive aggregation strategy --- specs/networking/p2p-interface.md | 32 +++++++++-- specs/validator/0_beacon-chain-validator.md | 61 ++++++++++++--------- 2 files changed, 62 insertions(+), 31 deletions(-) diff --git a/specs/networking/p2p-interface.md b/specs/networking/p2p-interface.md index ed63281b4..68a46c504 100644 --- a/specs/networking/p2p-interface.md +++ b/specs/networking/p2p-interface.md @@ -119,6 +119,7 @@ This section outlines constants that are used in this spec. | `SHARD_SUBNET_COUNT` | `TODO` | The number of shard subnets used in the gossipsub protocol. | | `TTFB_TIMEOUT` | `5s` | The maximum time to wait for first byte of request response (time-to-first-byte). | | `RESP_TIMEOUT` | `10s` | The maximum time for complete response transfer. | +| `ATTESTATION_PROPAGATION_SLOT_RANGE` | `4` | The maximum number of slots during which an attestation can be propagated. | ## The gossip domain: gossipsub @@ -147,10 +148,27 @@ Topics are plain UTF-8 strings and are encoded on the wire as determined by prot Topic strings have form: `/eth2/TopicName/TopicEncoding`. This defines both the type of data being sent on the topic and how the data field of the message is encoded. (Further details can be found in [Messages](#Messages)). -There are two main topics used to propagate attestations and beacon blocks to all nodes on the network. Their `TopicName`s are: +There are two main topics used to propagate aggregate attestations and beacon blocks to all nodes on the network. Their `TopicName`s are: - `beacon_block` - This topic is used solely for propagating new beacon blocks to all nodes on the networks. Blocks are sent in their entirety. Clients MUST validate the block proposer signature before forwarding it across the network. -- `beacon_attestation` - This topic is used to propagate aggregated attestations (in their entirety) to subscribing nodes (typically block proposers) to be included in future blocks. Clients MUST validate that the block being voted for passes validation before forwarding the attestation on the network (TODO: [additional validations](https://github.com/ethereum/eth2.0-specs/issues/1332)). +- `beacon_aggregate_and_proof` - This topic is used to propagate aggregated attestations (as `AggregateAndProof`s) to subscribing nodes (typically validators) to be included in future blocks. The following validations MUST pass before forwarding the `aggregate_and_proof` on the network. + - Clients MUST validate that the block being voted for (`aggregate_and_proof.aggregate.data.beacon_block_root`) passes validation. + - Clients MUST validate that `aggregate_and_proof.aggregate.data.slot` is + within the last `ATTESTATION_PROPAGATION_SLOT_RANGE` slots. + - Clients MUST validate that the validator index is within the aggregate's + committee -- i.e. `aggregate_and_proof.index in get_attesting_indices(state, aggregate_and_proof.aggregate.data, aggregate_and_proof.aggregate.aggregation_bits)`. + - Clients MUST validate that `aggregate_and_proof.selection_proof` selects + the validator as an aggregator for the slot -- i.e. `is_aggregator(state, aggregate_and_proof.aggregate.data.index, aggregate_and_proof.selection_proof)` returns `True`. + - Clients MUST validate that the `aggregate_and_proof.selection_proof` is a + valid signature of the `aggregate_and_proof.aggregate.data.slot` by the validator with index `aggregate_and_proof.index`. + - Clients MUST validate that the signature of `aggregate_and_proof.aggregate`. + +Attestation subnets are used to propagate unaggregated attestations to subsections of the network. Their `TopicName`s are: + +- `index{index % ATTESTATION_SUBNET_COUNT}_beacon_attestation` - This topic is used to propagate unaggregated attestations to subsections of the network (typically beacon and persistent committees) to be aggregated before being passed to `beacon_aggregate_and_proof`. The following validations MUST pass before forwarding the `attestation` on the network. + - Clients MUST validate that the block being voted for (`attestation.data.beacon_block_root`) passes validation. + - Clients MUST validate that `attestation.data.slot` is within the last `ATTESTATION_PROPAGATION_SLOT_RANGE` slots. + - Clients MUST validate the signature of `attestation`. Additional topics are used to propagate lower frequency validator messages. Their `TopicName`s are: @@ -160,13 +178,15 @@ Additional topics are used to propagate lower frequency validator messages. Thei #### Interop -Unaggregated and aggregated attestations from all shards are sent to the `beacon_attestation` topic. Clients are not required to publish aggregate attestations but must be able to process them. All validating clients SHOULD try to perform local attestation aggregation to prepare for block proposing. +Unaggregated and aggregated attestations from all shards are sent as `Attestation` to the `beacon_aggregate_and_proof` topic. Clients are not required to publish aggregate attestations but must be able to process them. All validating clients SHOULD try to perform local attestation aggregation to prepare for block proposing. #### Mainnet Attestation broadcasting is grouped into subnets defined by a topic. The number of subnets is defined via `ATTESTATION_SUBNET_COUNT`. The `CommitteeIndex`, `index`, is assigned to the topic: `index{index % ATTESTATION_SUBNET_COUNT}_beacon_attestation`. -Unaggregated attestations are sent to the subnet topic, `index{attestation.data.index % ATTESTATION_SUBNET_COUNT}_beacon_attestation`. Aggregated attestations are sent to the `beacon_attestation` topic. +Unaggregated attestations are sent to the subnet topic, `index{attestation.data.index % ATTESTATION_SUBNET_COUNT}_beacon_attestation` as `Attestation`s. + +Aggregated attestations are sent to the `beacon_aggregate_and_proof` topic as `AggregateAndProof`s. ### Messages @@ -180,7 +200,7 @@ The payload is carried in the `data` field of a gossipsub message, and varies de | Topic | Message Type | |------------------------------|-------------------| | beacon_block | BeaconBlock | -| beacon_attestation | Attestation | +| beacon_aggregate_and_proof | Attestation | | shard{N}\_beacon_attestation | Attestation | | voluntary_exit | VoluntaryExit | | proposer_slashing | ProposerSlashing | @@ -200,7 +220,7 @@ Topics are post-fixed with an encoding. Encodings define how the payload of a go #### Mainnet -- `ssz_snappy` - All objects are SSZ-encoded and then compressed with [Snappy](https://github.com/google/snappy). Example: The beacon attestation topic string is `/eth2/beacon_attestation/ssz_snappy`, and the data field of a gossipsub message is an `Attestation` that has been SSZ-encoded and then compressed with Snappy. +- `ssz_snappy` - All objects are SSZ-encoded and then compressed with [Snappy](https://github.com/google/snappy). Example: The beacon aggregate attestation topic string is `/eth2/beacon_aggregate_and_proof/ssz_snappy`, and the data field of a gossipsub message is an `AggregateAndProof` that has been SSZ-encoded and then compressed with Snappy. Implementations MUST use a single encoding. Changing an encoding will require coordination between participating implementations. diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index 27f0037fa..294145c0e 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -354,31 +354,46 @@ Finally, the validator broadcasts `attestation` to the associated attestation su ## Attestation aggregation -The validator is expected to locally aggregate attestations with a similar `attestation_data` to their constructed `attestation` for the assigned `slot`. +Some validators are selected to locally aggregate attestations with a similar `attestation_data` to their constructed `attestation` for the assigned `slot`. -The validator then _might_ broadcast their best aggregate to a global attestation channel two-thirds of the way through the `slot`-that is, `SECONDS_PER_SLOT * 2 / 3` seconds after the start of `slot`. +### Aggregation selection -#### Construct aggregate +A validator is selected to aggregate based upon the following -Collect `attestations` seen via gossip during the `slot` that have an equivalent `attestation_data` to that constructed by the validator. +```python +def slot_signature(slot: Slot, privkey: int) -> BLSSignature: + domain = get_domain(state, DOMAIN_BEACON_AGGREGATOR, attestation.data.slot) + return bls_sign(prvkey, hash_tree_root(slot), domain) +``` -The validator should create an `aggregate_attestation` with the following fields. +```python +def is_aggregator(state: BeaconState, slot: Slot, committee_index: CommitteeIndex, slot_signature: BLSSignature) -> bool: + committee = get_beacon_committee(state, slot, committee_index) + modulo = max(1, len(committee) // TARGET_AGGREGATORS_PER_COMMITTEE) + return bytes_to_int(hash(slot_signature)[0:8]) % modulo == 0 +``` -##### Data +### Construct aggregate + +If the validator is selected to aggregate (`is_aggregator()`), they construct an aggregate attestation via the following. + +Collect `attestations` seen via gossip during the `slot` that have an equivalent `attestation_data` to that constructed by the validator, and create an `aggregate_attestation` with the following fields. + +#### Data Set `aggregate_attestation.data = attestation_data` where `attestation_data` is the `AttestationData` object that is the same for each individual attestation being aggregated. -##### Aggregation bits +#### Aggregation bits Let `aggregate_attestation.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`. -##### Custody bits +#### Custody bits - Let `aggregate_attestation.custody_bits` be a `Bitlist[MAX_VALIDATORS_PER_COMMITTEE]` filled with zeros of length `len(committee)`. *Note*: This is a stub for Phase 0. -##### Aggregate signature +#### Aggregate signature Set `aggregate_attestation.signature = aggregate_signature` where `aggregate_signature` is obtained from: @@ -389,27 +404,23 @@ def get_aggregate_signature(attestations: Attestation) -> BLSSignature: return aggregate_signature ``` -#### Broadcast aggregate +### Broadcast aggregate -Starting two-thirds of the way into the slot, the validator begins running the following routine to decide if their best aggregate should be broadcast to the global attestation channel (`beacon_attestation`). `seen()` is defined as having seen an aggregate +If the validator is selected to aggregate (`is_aggregator`), then they broadcast their best aggregate to the global aggregate channel (`beacon_aggregate_and_proof`) two-thirds of the way through the `slot`-that is, `SECONDS_PER_SLOT * 2 / 3` seconds after the start of `slot`. + +Aggregate attestations are broadcast as `AggregateAndProof` objects to prove to the gossip channel that the validator has been selected as an aggregator. ```python -def should_broadcast_aggregate(aggregate_attestation: Attestation, index: ValidatorIndex) -> bool: - if seen(index): - return False - if random.randrange(SIDED_DIE) == 0: - return True - time.sleep(WAIT // 1000) +class AggregateAndProof(Container): + index: ValidatorIndex + selection_proof: BLSSignature + aggregate: Attestation ``` -Define `seen_better(aggregate_attestation, attestations)` as your aggregate -having more attestations included than any in the attestations you've seen on -the network so far. Could also make it better by _some_ amount. - -```python -def have_better_aggregate(aggregate_attestation, attestations): - -``` +Where +* `index` is the validator's `validator_index`. +* `selection_proof` is the signature of the slot (`slot_signature()`). +* `aggregate` is the `aggregate_attestation` constructed in the previous section. ## How to avoid slashing From 7fcb60795bcc7b7eeaa8652397ff8c54fc7c5ed7 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Wed, 23 Oct 2019 17:29:53 +0900 Subject: [PATCH 03/17] lint --- scripts/build_spec.py | 1 + specs/networking/p2p-interface.md | 8 ++++---- specs/validator/0_beacon-chain-validator.md | 13 ++++++++----- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/scripts/build_spec.py b/scripts/build_spec.py index c47249fe4..e05907014 100644 --- a/scripts/build_spec.py +++ b/scripts/build_spec.py @@ -28,6 +28,7 @@ from eth2spec.utils.ssz.ssz_typing import ( Bytes1, Bytes4, Bytes8, Bytes32, Bytes48, Bytes96, Bitlist, Bitvector, ) from eth2spec.utils.bls import ( + bls_aggregate_signatures, bls_aggregate_pubkeys, bls_verify, bls_verify_multiple, diff --git a/specs/networking/p2p-interface.md b/specs/networking/p2p-interface.md index 68a46c504..d3a8c156b 100644 --- a/specs/networking/p2p-interface.md +++ b/specs/networking/p2p-interface.md @@ -116,7 +116,7 @@ This section outlines constants that are used in this spec. | `REQ_RESP_MAX_SIZE` | `TODO` | The maximum size of uncompressed req/resp messages that clients will allow. | | `SSZ_MAX_LIST_SIZE` | `TODO` | The maximum size of SSZ-encoded variable lists. | | `GOSSIP_MAX_SIZE` | `2**20` (= 1048576, 1 MiB) | The maximum size of uncompressed gossip messages. | -| `SHARD_SUBNET_COUNT` | `TODO` | The number of shard subnets used in the gossipsub protocol. | +| `ATTESTATION_SUBNET_COUNT` | `TODO` | The number of shard subnets used in the gossipsub protocol. | | `TTFB_TIMEOUT` | `5s` | The maximum time to wait for first byte of request response (time-to-first-byte). | | `RESP_TIMEOUT` | `10s` | The maximum time for complete response transfer. | | `ATTESTATION_PROPAGATION_SLOT_RANGE` | `4` | The maximum number of slots during which an attestation can be propagated. | @@ -200,8 +200,8 @@ The payload is carried in the `data` field of a gossipsub message, and varies de | Topic | Message Type | |------------------------------|-------------------| | beacon_block | BeaconBlock | -| beacon_aggregate_and_proof | Attestation | -| shard{N}\_beacon_attestation | Attestation | +| beacon_aggregate_and_proof | AggregateAndProof | +| index{N}\_beacon_attestation | Attestation | | voluntary_exit | VoluntaryExit | | proposer_slashing | ProposerSlashing | | attester_slashing | AttesterSlashing | @@ -648,7 +648,7 @@ No security or privacy guarantees are lost as a result of choosing plaintext top Furthermore, the Eth 2.0 topic names are shorter than their digest equivalents (assuming SHA-256 hash), so hashing topics would bloat messages unnecessarily. -### Why are there `SHARD_SUBNET_COUNT` subnets, and why is this not defined? +### Why are there `ATTESTATION_SUBNET_COUNT` subnets, and why is this not defined? Depending on the number of validators, it may be more efficient to group shard subnets and might provide better stability for the gossipsub channel. The exact grouping will be dependent on more involved network tests. This constant allows for more flexibility in setting up the network topology for attestation aggregation (as aggregation should happen on each subnet). diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index 294145c0e..3b4085ff3 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -78,6 +78,7 @@ All terminology, constants, functions, and protocol mechanics defined in the [Ph | Name | Value | Unit | Duration | | - | - | :-: | :-: | | `ETH1_FOLLOW_DISTANCE` | `2**10` (= 1,024) | blocks | ~4 hours | +| `TARGET_AGGREGATORS_PER_COMMITTEE` | `2**4` (= 16) | validators | | ## Becoming a validator @@ -361,14 +362,14 @@ Some validators are selected to locally aggregate attestations with a similar `a A validator is selected to aggregate based upon the following ```python -def slot_signature(slot: Slot, privkey: int) -> BLSSignature: - domain = get_domain(state, DOMAIN_BEACON_AGGREGATOR, attestation.data.slot) - return bls_sign(prvkey, hash_tree_root(slot), domain) +def slot_signature(state: BeaconState, slot: Slot, privkey: int) -> BLSSignature: + domain = get_domain(state, DOMAIN_BEACON_ATTESTER, compute_epoch_at_slot(slot)) + return bls_sign(privkey, hash_tree_root(slot), domain) ``` ```python -def is_aggregator(state: BeaconState, slot: Slot, committee_index: CommitteeIndex, slot_signature: BLSSignature) -> bool: - committee = get_beacon_committee(state, slot, committee_index) +def is_aggregator(state: BeaconState, slot: Slot, index: CommitteeIndex, slot_signature: BLSSignature) -> bool: + committee = get_beacon_committee(state, slot, index) modulo = max(1, len(committee) // TARGET_AGGREGATORS_PER_COMMITTEE) return bytes_to_int(hash(slot_signature)[0:8]) % modulo == 0 ``` @@ -410,6 +411,8 @@ If the validator is selected to aggregate (`is_aggregator`), then they broadcast Aggregate attestations are broadcast as `AggregateAndProof` objects to prove to the gossip channel that the validator has been selected as an aggregator. +### `AggregateAndProof` + ```python class AggregateAndProof(Container): index: ValidatorIndex From cf1d855be666b8f0221e4ca3aa42e9574a676ea9 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Wed, 23 Oct 2019 17:37:32 +0900 Subject: [PATCH 04/17] lint --- specs/networking/p2p-interface.md | 2 +- specs/validator/0_beacon-chain-validator.md | 26 ++++++++++----------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/specs/networking/p2p-interface.md b/specs/networking/p2p-interface.md index d3a8c156b..6b7b84b64 100644 --- a/specs/networking/p2p-interface.md +++ b/specs/networking/p2p-interface.md @@ -178,7 +178,7 @@ Additional topics are used to propagate lower frequency validator messages. Thei #### Interop -Unaggregated and aggregated attestations from all shards are sent as `Attestation` to the `beacon_aggregate_and_proof` topic. Clients are not required to publish aggregate attestations but must be able to process them. All validating clients SHOULD try to perform local attestation aggregation to prepare for block proposing. +Unaggregated and aggregated attestations from all shards are sent as `Attestation`s to the `beacon_aggregate_and_proof` topic. Clients are not required to publish aggregate attestations but must be able to process them. All validating clients SHOULD try to perform local attestation aggregation to prepare for block proposing. #### Mainnet diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index 3b4085ff3..b477c5156 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -54,7 +54,6 @@ - [Custody bits](#custody-bits-1) - [Aggregate signature](#aggregate-signature-1) - [Broadcast aggregate](#broadcast-aggregate) - - [How to avoid slashing](#how-to-avoid-slashing) - [Proposer slashing](#proposer-slashing) - [Attester slashing](#attester-slashing) @@ -353,13 +352,13 @@ def get_signed_attestation_data(state: BeaconState, attestation: IndexedAttestat Finally, the validator broadcasts `attestation` to the associated attestation subnet -- the `index{attestation.data.index % ATTESTATION_SUBNET_COUNT}_beacon_attestation` pubsub topic. -## Attestation aggregation +### Attestation aggregation Some validators are selected to locally aggregate attestations with a similar `attestation_data` to their constructed `attestation` for the assigned `slot`. -### Aggregation selection +#### Aggregation selection -A validator is selected to aggregate based upon the following +A validator is selected to aggregate based upon the return value of `is_aggregator()`. ```python def slot_signature(state: BeaconState, slot: Slot, privkey: int) -> BLSSignature: @@ -374,44 +373,43 @@ def is_aggregator(state: BeaconState, slot: Slot, index: CommitteeIndex, slot_si return bytes_to_int(hash(slot_signature)[0:8]) % modulo == 0 ``` -### Construct aggregate +#### Construct aggregate If the validator is selected to aggregate (`is_aggregator()`), they construct an aggregate attestation via the following. Collect `attestations` seen via gossip during the `slot` that have an equivalent `attestation_data` to that constructed by the validator, and create an `aggregate_attestation` with the following fields. -#### Data +##### Data Set `aggregate_attestation.data = attestation_data` where `attestation_data` is the `AttestationData` object that is the same for each individual attestation being aggregated. -#### Aggregation bits +##### Aggregation bits Let `aggregate_attestation.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`. -#### Custody bits +##### Custody bits - Let `aggregate_attestation.custody_bits` be a `Bitlist[MAX_VALIDATORS_PER_COMMITTEE]` filled with zeros of length `len(committee)`. *Note*: This is a stub for Phase 0. -#### Aggregate signature +##### Aggregate signature Set `aggregate_attestation.signature = aggregate_signature` where `aggregate_signature` is obtained from: ```python -def get_aggregate_signature(attestations: Attestation) -> BLSSignature: +def get_aggregate_signature(attestations: Sequence[Attestation]) -> BLSSignature: signatures = [attestation.signature for attestation in attestations] - aggregate_signature = bls_aggregate_signatures(signatures) - return aggregate_signature + return bls_aggregate_signatures(signatures) ``` -### Broadcast aggregate +#### Broadcast aggregate If the validator is selected to aggregate (`is_aggregator`), then they broadcast their best aggregate to the global aggregate channel (`beacon_aggregate_and_proof`) two-thirds of the way through the `slot`-that is, `SECONDS_PER_SLOT * 2 / 3` seconds after the start of `slot`. Aggregate attestations are broadcast as `AggregateAndProof` objects to prove to the gossip channel that the validator has been selected as an aggregator. -### `AggregateAndProof` +##### `AggregateAndProof` ```python class AggregateAndProof(Container): From 1cda8c8a8b1f3e81c55d0e46b0ba16e3b83a898d Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 24 Oct 2019 10:08:23 +0900 Subject: [PATCH 05/17] aggregation cleanups --- specs/networking/p2p-interface.md | 16 +++++++++++----- specs/validator/0_beacon-chain-validator.md | 2 ++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/specs/networking/p2p-interface.md b/specs/networking/p2p-interface.md index 6b7b84b64..7f9977be3 100644 --- a/specs/networking/p2p-interface.md +++ b/specs/networking/p2p-interface.md @@ -116,10 +116,10 @@ This section outlines constants that are used in this spec. | `REQ_RESP_MAX_SIZE` | `TODO` | The maximum size of uncompressed req/resp messages that clients will allow. | | `SSZ_MAX_LIST_SIZE` | `TODO` | The maximum size of SSZ-encoded variable lists. | | `GOSSIP_MAX_SIZE` | `2**20` (= 1048576, 1 MiB) | The maximum size of uncompressed gossip messages. | -| `ATTESTATION_SUBNET_COUNT` | `TODO` | The number of shard subnets used in the gossipsub protocol. | +| `ATTESTATION_SUBNET_COUNT` | `64` | The number of shard subnets used in the gossipsub protocol. | | `TTFB_TIMEOUT` | `5s` | The maximum time to wait for first byte of request response (time-to-first-byte). | | `RESP_TIMEOUT` | `10s` | The maximum time for complete response transfer. | -| `ATTESTATION_PROPAGATION_SLOT_RANGE` | `4` | The maximum number of slots during which an attestation can be propagated. | +| `ATTESTATION_PROPAGATION_SLOT_RANGE` | `32` | The maximum number of slots during which an attestation can be propagated. | ## The gossip domain: gossipsub @@ -165,7 +165,7 @@ There are two main topics used to propagate aggregate attestations and beacon bl Attestation subnets are used to propagate unaggregated attestations to subsections of the network. Their `TopicName`s are: -- `index{index % ATTESTATION_SUBNET_COUNT}_beacon_attestation` - This topic is used to propagate unaggregated attestations to subsections of the network (typically beacon and persistent committees) to be aggregated before being passed to `beacon_aggregate_and_proof`. The following validations MUST pass before forwarding the `attestation` on the network. +- `index{index % ATTESTATION_SUBNET_COUNT}_beacon_attestation` - These topics are used to propagate unaggregated attestations to subsections of the network (typically beacon and persistent committees) to be aggregated before being gossiped to `beacon_aggregate_and_proof`. The following validations MUST pass before forwarding the `attestation` on the network. - Clients MUST validate that the block being voted for (`attestation.data.beacon_block_root`) passes validation. - Clients MUST validate that `attestation.data.slot` is within the last `ATTESTATION_PROPAGATION_SLOT_RANGE` slots. - Clients MUST validate the signature of `attestation`. @@ -648,9 +648,15 @@ No security or privacy guarantees are lost as a result of choosing plaintext top Furthermore, the Eth 2.0 topic names are shorter than their digest equivalents (assuming SHA-256 hash), so hashing topics would bloat messages unnecessarily. -### Why are there `ATTESTATION_SUBNET_COUNT` subnets, and why is this not defined? +### Why are there `ATTESTATION_SUBNET_COUNT` subnets? -Depending on the number of validators, it may be more efficient to group shard subnets and might provide better stability for the gossipsub channel. The exact grouping will be dependent on more involved network tests. This constant allows for more flexibility in setting up the network topology for attestation aggregation (as aggregation should happen on each subnet). +Depending on the number of validators, it may be more efficient to group shard subnets and might provide better stability for the gossipsub channel. The exact grouping will be dependent on more involved network tests. This constant allows for more flexibility in setting up the network topology for attestation aggregation (as aggregation should happen on each subnet). The value is currently set to to be equal `MAX_COMMITTEES_PER_SLOT` until network tests indicate otherwise. + +### Why are attestations limited to be broadcast on gossip channels within `SLOTS_PER_EPOCH` slots? + +Attestations can only be included on chain within an epoch's worth of slots so this is the natural cutoff. There is no utility to the chain to broadcast attestations older than one epoch, and because validators have a chance to make a new attestation each epoch, there is minimal utility to the fork choice to relay old attestations as a new latest message can soon be created by each validator. + +In addition to this, relaying attestations requires validating the attestation in the context of the `state` during which it was created. Thus, validating arbitrarily old attestations would put additional requirements on which states need to be readily available to the node. This would result in a higher resource burden and could serve as a DoS vector. ### Why are we sending entire objects in the pubsub and not just hashes? diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index b477c5156..a79b178b3 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -48,12 +48,14 @@ - [Aggregate signature](#aggregate-signature) - [Broadcast attestation](#broadcast-attestation) - [Attestation aggregation](#attestation-aggregation) + - [Aggregation selection](#aggregation-selection) - [Construct aggregate](#construct-aggregate) - [Data](#data-1) - [Aggregation bits](#aggregation-bits-1) - [Custody bits](#custody-bits-1) - [Aggregate signature](#aggregate-signature-1) - [Broadcast aggregate](#broadcast-aggregate) + - [`AggregateAndProof`](#aggregateandproof) - [How to avoid slashing](#how-to-avoid-slashing) - [Proposer slashing](#proposer-slashing) - [Attester slashing](#attester-slashing) From 7804f94279294275579c69cf99bae0c6d998413d Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 24 Oct 2019 10:23:37 +0900 Subject: [PATCH 06/17] explain why aggregate_and_proof for aggregate gossip in p2p faq --- specs/networking/p2p-interface.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/specs/networking/p2p-interface.md b/specs/networking/p2p-interface.md index 7f9977be3..4f8829cd8 100644 --- a/specs/networking/p2p-interface.md +++ b/specs/networking/p2p-interface.md @@ -11,7 +11,7 @@ It consists of four main sections: ## Table of contents - + @@ -658,6 +658,10 @@ Attestations can only be included on chain within an epoch's worth of slots so t In addition to this, relaying attestations requires validating the attestation in the context of the `state` during which it was created. Thus, validating arbitrarily old attestations would put additional requirements on which states need to be readily available to the node. This would result in a higher resource burden and could serve as a DoS vector. +### Why are aggregate attestations broadcast to the global topic as `AggregateAndProof`s rather than just as `Attestation`s? + +The dominant strategy for an individual validator is to always broadcast an aggregate containing their own attestation to the global channel to ensure that proposers see their attestation for inclusion. Using a private selection criteria and providing this proof of selection alongside the gossiped aggregate ensures that this dominant strategy will not flood the global channel. + ### Why are we sending entire objects in the pubsub and not just hashes? Entire objects should be sent to get the greatest propagation speeds. If only hashes are sent, then block and attestation propagation is dependent on recursive requests from each peer. In a hash-only scenario, peers could receive hashes without knowing who to download the actual contents from. Sending entire objects ensures that they get propagated through the entire network. From c2cebef64910de3a1b9e0f68f61b4f7f8d6dd3ef Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Fri, 25 Oct 2019 17:13:00 +0800 Subject: [PATCH 07/17] Update specs/validator/0_beacon-chain-validator.md Co-Authored-By: Hsiao-Wei Wang --- specs/validator/0_beacon-chain-validator.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index a79b178b3..3d679a991 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -379,7 +379,7 @@ def is_aggregator(state: BeaconState, slot: Slot, index: CommitteeIndex, slot_si If the validator is selected to aggregate (`is_aggregator()`), they construct an aggregate attestation via the following. -Collect `attestations` seen via gossip during the `slot` that have an equivalent `attestation_data` to that constructed by the validator, and create an `aggregate_attestation` with the following fields. +Collect `attestations` seen via gossip during the `slot` that have an equivalent `attestation_data` to that constructed by the validator, and create an `aggregate_attestation: Attestation` with the following fields. ##### Data From db8347645e297ee44ca8ce5514e48774998b9f47 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Sun, 27 Oct 2019 12:18:13 +0900 Subject: [PATCH 08/17] add validation condition to aggregate gossip to prevent forwarding duplicate aggregates along --- specs/networking/p2p-interface.md | 1 + 1 file changed, 1 insertion(+) diff --git a/specs/networking/p2p-interface.md b/specs/networking/p2p-interface.md index 4f8829cd8..7921b8d72 100644 --- a/specs/networking/p2p-interface.md +++ b/specs/networking/p2p-interface.md @@ -152,6 +152,7 @@ There are two main topics used to propagate aggregate attestations and beacon bl - `beacon_block` - This topic is used solely for propagating new beacon blocks to all nodes on the networks. Blocks are sent in their entirety. Clients MUST validate the block proposer signature before forwarding it across the network. - `beacon_aggregate_and_proof` - This topic is used to propagate aggregated attestations (as `AggregateAndProof`s) to subscribing nodes (typically validators) to be included in future blocks. The following validations MUST pass before forwarding the `aggregate_and_proof` on the network. + - Clients MUST validate that the aggregate attestation defined by `hash_tree_root(aggregate_and_proof.aggregate)` has _not_ already been seen (via aggregate gossip, within a block, or through the creation of an equivalent aggregate locally). - Clients MUST validate that the block being voted for (`aggregate_and_proof.aggregate.data.beacon_block_root`) passes validation. - Clients MUST validate that `aggregate_and_proof.aggregate.data.slot` is within the last `ATTESTATION_PROPAGATION_SLOT_RANGE` slots. From e005bb04c56cc2d948de5f505f5c76613ba180db Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Sun, 27 Oct 2019 12:29:11 +0900 Subject: [PATCH 09/17] add unaggregated attestation validations --- specs/networking/p2p-interface.md | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/specs/networking/p2p-interface.md b/specs/networking/p2p-interface.md index 7921b8d72..c4bace2d7 100644 --- a/specs/networking/p2p-interface.md +++ b/specs/networking/p2p-interface.md @@ -154,19 +154,17 @@ There are two main topics used to propagate aggregate attestations and beacon bl - `beacon_aggregate_and_proof` - This topic is used to propagate aggregated attestations (as `AggregateAndProof`s) to subscribing nodes (typically validators) to be included in future blocks. The following validations MUST pass before forwarding the `aggregate_and_proof` on the network. - Clients MUST validate that the aggregate attestation defined by `hash_tree_root(aggregate_and_proof.aggregate)` has _not_ already been seen (via aggregate gossip, within a block, or through the creation of an equivalent aggregate locally). - Clients MUST validate that the block being voted for (`aggregate_and_proof.aggregate.data.beacon_block_root`) passes validation. - - Clients MUST validate that `aggregate_and_proof.aggregate.data.slot` is - within the last `ATTESTATION_PROPAGATION_SLOT_RANGE` slots. - - Clients MUST validate that the validator index is within the aggregate's - committee -- i.e. `aggregate_and_proof.index in get_attesting_indices(state, aggregate_and_proof.aggregate.data, aggregate_and_proof.aggregate.aggregation_bits)`. - - Clients MUST validate that `aggregate_and_proof.selection_proof` selects - the validator as an aggregator for the slot -- i.e. `is_aggregator(state, aggregate_and_proof.aggregate.data.index, aggregate_and_proof.selection_proof)` returns `True`. - - Clients MUST validate that the `aggregate_and_proof.selection_proof` is a - valid signature of the `aggregate_and_proof.aggregate.data.slot` by the validator with index `aggregate_and_proof.index`. + - Clients MUST validate that `aggregate_and_proof.aggregate.data.slot` is within the last `ATTESTATION_PROPAGATION_SLOT_RANGE` slots. + - Clients MUST validate that the validator index is within the aggregate's committee -- i.e. `aggregate_and_proof.index in get_attesting_indices(state, aggregate_and_proof.aggregate.data, aggregate_and_proof.aggregate.aggregation_bits)`. + - Clients MUST validate that `aggregate_and_proof.selection_proof` selects the validator as an aggregator for the slot -- i.e. `is_aggregator(state, aggregate_and_proof.aggregate.data.index, aggregate_and_proof.selection_proof)` returns `True`. + - Clients MUST validate that the `aggregate_and_proof.selection_proof` is a valid signature of the `aggregate_and_proof.aggregate.data.slot` by the validator with index `aggregate_and_proof.index`. - Clients MUST validate that the signature of `aggregate_and_proof.aggregate`. Attestation subnets are used to propagate unaggregated attestations to subsections of the network. Their `TopicName`s are: -- `index{index % ATTESTATION_SUBNET_COUNT}_beacon_attestation` - These topics are used to propagate unaggregated attestations to subsections of the network (typically beacon and persistent committees) to be aggregated before being gossiped to `beacon_aggregate_and_proof`. The following validations MUST pass before forwarding the `attestation` on the network. +- `committee_index{index % ATTESTATION_SUBNET_COUNT}_beacon_attestation` - These topics are used to propagate unaggregated attestations to subsections of the network (typically beacon and persistent committees) to be aggregated before being gossiped to `beacon_aggregate_and_proof`. The following validations MUST pass before forwarding the `attestation` on the network. + - Clients MUST validate that the attestation's committee index (`attestation.data.index`) is for the correct subnet. + - Clients MUST validate that the attestation is unaggregated -- that is, it has exactly one participating validator (`len([bit for bit in attestation.aggregation_bits if bit == 0b1]) == 1`). - Clients MUST validate that the block being voted for (`attestation.data.beacon_block_root`) passes validation. - Clients MUST validate that `attestation.data.slot` is within the last `ATTESTATION_PROPAGATION_SLOT_RANGE` slots. - Clients MUST validate the signature of `attestation`. From a700e7a86504e074a7089a5780537d4032c5c450 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Sun, 27 Oct 2019 12:32:28 +0900 Subject: [PATCH 10/17] fmt --- specs/networking/p2p-interface.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/specs/networking/p2p-interface.md b/specs/networking/p2p-interface.md index c4bace2d7..2afd2276c 100644 --- a/specs/networking/p2p-interface.md +++ b/specs/networking/p2p-interface.md @@ -152,22 +152,22 @@ There are two main topics used to propagate aggregate attestations and beacon bl - `beacon_block` - This topic is used solely for propagating new beacon blocks to all nodes on the networks. Blocks are sent in their entirety. Clients MUST validate the block proposer signature before forwarding it across the network. - `beacon_aggregate_and_proof` - This topic is used to propagate aggregated attestations (as `AggregateAndProof`s) to subscribing nodes (typically validators) to be included in future blocks. The following validations MUST pass before forwarding the `aggregate_and_proof` on the network. - - Clients MUST validate that the aggregate attestation defined by `hash_tree_root(aggregate_and_proof.aggregate)` has _not_ already been seen (via aggregate gossip, within a block, or through the creation of an equivalent aggregate locally). - - Clients MUST validate that the block being voted for (`aggregate_and_proof.aggregate.data.beacon_block_root`) passes validation. - - Clients MUST validate that `aggregate_and_proof.aggregate.data.slot` is within the last `ATTESTATION_PROPAGATION_SLOT_RANGE` slots. - - Clients MUST validate that the validator index is within the aggregate's committee -- i.e. `aggregate_and_proof.index in get_attesting_indices(state, aggregate_and_proof.aggregate.data, aggregate_and_proof.aggregate.aggregation_bits)`. - - Clients MUST validate that `aggregate_and_proof.selection_proof` selects the validator as an aggregator for the slot -- i.e. `is_aggregator(state, aggregate_and_proof.aggregate.data.index, aggregate_and_proof.selection_proof)` returns `True`. - - Clients MUST validate that the `aggregate_and_proof.selection_proof` is a valid signature of the `aggregate_and_proof.aggregate.data.slot` by the validator with index `aggregate_and_proof.index`. - - Clients MUST validate that the signature of `aggregate_and_proof.aggregate`. + - The aggregate attestation defined by `hash_tree_root(aggregate_and_proof.aggregate)` has _not_ already been seen (via aggregate gossip, within a block, or through the creation of an equivalent aggregate locally). + - The block being voted for (`aggregate_and_proof.aggregate.data.beacon_block_root`) passes validation. + - `aggregate_and_proof.aggregate.data.slot` is within the last `ATTESTATION_PROPAGATION_SLOT_RANGE` slots. + - The validator index is within the aggregate's committee -- i.e. `aggregate_and_proof.index in get_attesting_indices(state, aggregate_and_proof.aggregate.data, aggregate_and_proof.aggregate.aggregation_bits)`. + - `aggregate_and_proof.selection_proof` selects the validator as an aggregator for the slot -- i.e. `is_aggregator(state, aggregate_and_proof.aggregate.data.index, aggregate_and_proof.selection_proof)` returns `True`. + - The `aggregate_and_proof.selection_proof` is a valid signature of the `aggregate_and_proof.aggregate.data.slot` by the validator with index `aggregate_and_proof.index`. + - The signature of `aggregate_and_proof.aggregate` is valid. Attestation subnets are used to propagate unaggregated attestations to subsections of the network. Their `TopicName`s are: - `committee_index{index % ATTESTATION_SUBNET_COUNT}_beacon_attestation` - These topics are used to propagate unaggregated attestations to subsections of the network (typically beacon and persistent committees) to be aggregated before being gossiped to `beacon_aggregate_and_proof`. The following validations MUST pass before forwarding the `attestation` on the network. - - Clients MUST validate that the attestation's committee index (`attestation.data.index`) is for the correct subnet. - - Clients MUST validate that the attestation is unaggregated -- that is, it has exactly one participating validator (`len([bit for bit in attestation.aggregation_bits if bit == 0b1]) == 1`). - - Clients MUST validate that the block being voted for (`attestation.data.beacon_block_root`) passes validation. - - Clients MUST validate that `attestation.data.slot` is within the last `ATTESTATION_PROPAGATION_SLOT_RANGE` slots. - - Clients MUST validate the signature of `attestation`. + - The attestation's committee index (`attestation.data.index`) is for the correct subnet. + - The attestation is unaggregated -- that is, it has exactly one participating validator (`len([bit for bit in attestation.aggregation_bits if bit == 0b1]) == 1`). + - The block being voted for (`attestation.data.beacon_block_root`) passes validation. + - `attestation.data.slot` is within the last `ATTESTATION_PROPAGATION_SLOT_RANGE` slots. + - The signature of `attestation` is valid. Additional topics are used to propagate lower frequency validator messages. Their `TopicName`s are: From 6a62cfd3f56bf0823d2edf5ce3cf72ccc5f0e49a Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Sun, 27 Oct 2019 12:38:38 +0900 Subject: [PATCH 11/17] gossip cleanup --- specs/networking/p2p-interface.md | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/specs/networking/p2p-interface.md b/specs/networking/p2p-interface.md index 2afd2276c..ae84cb147 100644 --- a/specs/networking/p2p-interface.md +++ b/specs/networking/p2p-interface.md @@ -177,13 +177,13 @@ Additional topics are used to propagate lower frequency validator messages. Thei #### Interop -Unaggregated and aggregated attestations from all shards are sent as `Attestation`s to the `beacon_aggregate_and_proof` topic. Clients are not required to publish aggregate attestations but must be able to process them. All validating clients SHOULD try to perform local attestation aggregation to prepare for block proposing. +Unaggregated and aggregated attestations from all shards are sent as `Attestation`s to the `beacon_attestation` topic. Clients are not required to publish aggregate attestations but must be able to process them. All validating clients SHOULD try to perform local attestation aggregation to prepare for block proposing. #### Mainnet -Attestation broadcasting is grouped into subnets defined by a topic. The number of subnets is defined via `ATTESTATION_SUBNET_COUNT`. The `CommitteeIndex`, `index`, is assigned to the topic: `index{index % ATTESTATION_SUBNET_COUNT}_beacon_attestation`. +Attestation broadcasting is grouped into subnets defined by a topic. The number of subnets is defined via `ATTESTATION_SUBNET_COUNT`. The `CommitteeIndex`, `index`, is assigned to the topic: `committee_index{index % ATTESTATION_SUBNET_COUNT}_beacon_attestation`. -Unaggregated attestations are sent to the subnet topic, `index{attestation.data.index % ATTESTATION_SUBNET_COUNT}_beacon_attestation` as `Attestation`s. +Unaggregated attestations are sent to the subnet topic, `committee_index{attestation.data.index % ATTESTATION_SUBNET_COUNT}_beacon_attestation` as `Attestation`s. Aggregated attestations are sent to the `beacon_aggregate_and_proof` topic as `AggregateAndProof`s. @@ -196,19 +196,22 @@ Clients MUST reject (fail validation) messages that are over this size limit. Li The payload is carried in the `data` field of a gossipsub message, and varies depending on the topic: -| Topic | Message Type | -|------------------------------|-------------------| -| beacon_block | BeaconBlock | -| beacon_aggregate_and_proof | AggregateAndProof | -| index{N}\_beacon_attestation | Attestation | -| voluntary_exit | VoluntaryExit | -| proposer_slashing | ProposerSlashing | -| attester_slashing | AttesterSlashing | +| Topic | Message Type | +|----------------------------------------|-------------------| +| beacon_block | BeaconBlock | +| beacon_aggregate_and_proof | AggregateAndProof | +| beacon_attestation\* | Attestation | +| committee_index{N}\_beacon_attestation | Attestation | +| voluntary_exit | VoluntaryExit | +| proposer_slashing | ProposerSlashing | +| attester_slashing | AttesterSlashing | Clients MUST reject (fail validation) messages containing an incorrect type, or invalid payload. When processing incoming gossip, clients MAY descore or disconnect peers who fail to observe these constraints. +\* The `beacon_attestation` topic is only for interop and will be removed prior to mainnet. + ### Encodings Topics are post-fixed with an encoding. Encodings define how the payload of a gossipsub message is encoded. From d6563bce2d3bee99ad5597a34bb8b561e9bf218d Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Sun, 27 Oct 2019 12:50:55 +0900 Subject: [PATCH 12/17] minor edits to p2p faq --- specs/networking/p2p-interface.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/specs/networking/p2p-interface.md b/specs/networking/p2p-interface.md index ae84cb147..3f02757f9 100644 --- a/specs/networking/p2p-interface.md +++ b/specs/networking/p2p-interface.md @@ -11,7 +11,7 @@ It consists of four main sections: ## Table of contents - + @@ -650,7 +650,7 @@ No security or privacy guarantees are lost as a result of choosing plaintext top Furthermore, the Eth 2.0 topic names are shorter than their digest equivalents (assuming SHA-256 hash), so hashing topics would bloat messages unnecessarily. -### Why are there `ATTESTATION_SUBNET_COUNT` subnets? +### Why are there `ATTESTATION_SUBNET_COUNT` attestation subnets? Depending on the number of validators, it may be more efficient to group shard subnets and might provide better stability for the gossipsub channel. The exact grouping will be dependent on more involved network tests. This constant allows for more flexibility in setting up the network topology for attestation aggregation (as aggregation should happen on each subnet). The value is currently set to to be equal `MAX_COMMITTEES_PER_SLOT` until network tests indicate otherwise. @@ -664,6 +664,8 @@ In addition to this, relaying attestations requires validating the attestation i The dominant strategy for an individual validator is to always broadcast an aggregate containing their own attestation to the global channel to ensure that proposers see their attestation for inclusion. Using a private selection criteria and providing this proof of selection alongside the gossiped aggregate ensures that this dominant strategy will not flood the global channel. +Also, an attacker can create any number of honest-looking aggregates and broadcast them to the global pubsub channel. Thus without some sort of proof of selection as an aggregator, the global channel can trivially be spammed. + ### Why are we sending entire objects in the pubsub and not just hashes? Entire objects should be sent to get the greatest propagation speeds. If only hashes are sent, then block and attestation propagation is dependent on recursive requests from each peer. In a hash-only scenario, peers could receive hashes without knowing who to download the actual contents from. Sending entire objects ensures that they get propagated through the entire network. From 2d59ca6d575f7e48ba3a9907753212018f6121d2 Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Mon, 28 Oct 2019 12:43:29 +0800 Subject: [PATCH 13/17] Update ToC --- specs/validator/0_beacon-chain-validator.md | 1 + 1 file changed, 1 insertion(+) diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index 3d679a991..c6623dd09 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -39,6 +39,7 @@ - [Voluntary exits](#voluntary-exits) - [Attesting](#attesting) - [Attestation data](#attestation-data) + - [General](#general) - [LMD GHOST vote](#lmd-ghost-vote) - [FFG vote](#ffg-vote) - [Construct attestation](#construct-attestation) From e8fc84eadc730bf5d3feaa3fdd131e3a7b071b8f Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Mon, 28 Oct 2019 15:00:55 +0800 Subject: [PATCH 14/17] Update specs/networking/p2p-interface.md Co-Authored-By: Hsiao-Wei Wang --- specs/networking/p2p-interface.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/networking/p2p-interface.md b/specs/networking/p2p-interface.md index 50a24a83a..9659dac5a 100644 --- a/specs/networking/p2p-interface.md +++ b/specs/networking/p2p-interface.md @@ -115,7 +115,7 @@ This section outlines constants that are used in this spec. |---|---|---| | `GOSSIP_MAX_SIZE` | `2**20` (= 1048576, 1 MiB) | The maximum allowed size of uncompressed gossip messages. | | `MAX_CHUNK_SIZE` | `2**20` (1048576, 1 MiB) | The maximum allowed size of uncompressed req/resp chunked responses. | -| `ATTESTATION_SUBNET_COUNT` | `64` | The number of shard subnets used in the gossipsub protocol. | +| `ATTESTATION_SUBNET_COUNT` | `64` | The number of attestation subnets used in the gossipsub protocol. | | `TTFB_TIMEOUT` | `5s` | The maximum time to wait for first byte of request response (time-to-first-byte). | | `RESP_TIMEOUT` | `10s` | The maximum time for complete response transfer. | | `ATTESTATION_PROPAGATION_SLOT_RANGE` | `32` | The maximum number of slots during which an attestation can be propagated. | From 6fc1feaa2a87e47bc8bb1b09642cdb7b3b177274 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Mon, 28 Oct 2019 16:15:26 +0900 Subject: [PATCH 15/17] rearrange some of the gossip info in response to hwwhww review --- specs/networking/p2p-interface.md | 97 +++++++++++++++---------------- 1 file changed, 47 insertions(+), 50 deletions(-) diff --git a/specs/networking/p2p-interface.md b/specs/networking/p2p-interface.md index 9659dac5a..2338aaf88 100644 --- a/specs/networking/p2p-interface.md +++ b/specs/networking/p2p-interface.md @@ -11,7 +11,7 @@ It consists of four main sections: ## Table of contents - + @@ -141,60 +141,14 @@ The following gossipsub [parameters](https://github.com/libp2p/specs/tree/master - `gossip_history` (number of heartbeat intervals to retain message IDs): 5 - `heartbeat_interval` (frequency of heartbeat, seconds): 1 -### Topics +### Topics and messages -Topics are plain UTF-8 strings and are encoded on the wire as determined by protobuf (gossipsub messages are enveloped in protobuf messages). +Topics are plain UTF-8 strings and are encoded on the wire as determined by protobuf (gossipsub messages are enveloped in protobuf messages). Topic strings have form: `/eth2/TopicName/TopicEncoding`. This defines both the type of data being sent on the topic and how the data field of the message is encoded. -Topic strings have form: `/eth2/TopicName/TopicEncoding`. This defines both the type of data being sent on the topic and how the data field of the message is encoded. (Further details can be found in [Messages](#Messages)). - -There are two main topics used to propagate aggregate attestations and beacon blocks to all nodes on the network. Their `TopicName`s are: - -- `beacon_block` - This topic is used solely for propagating new beacon blocks to all nodes on the networks. Blocks are sent in their entirety. Clients MUST validate the block proposer signature before forwarding it across the network. -- `beacon_aggregate_and_proof` - This topic is used to propagate aggregated attestations (as `AggregateAndProof`s) to subscribing nodes (typically validators) to be included in future blocks. The following validations MUST pass before forwarding the `aggregate_and_proof` on the network. - - The aggregate attestation defined by `hash_tree_root(aggregate_and_proof.aggregate)` has _not_ already been seen (via aggregate gossip, within a block, or through the creation of an equivalent aggregate locally). - - The block being voted for (`aggregate_and_proof.aggregate.data.beacon_block_root`) passes validation. - - `aggregate_and_proof.aggregate.data.slot` is within the last `ATTESTATION_PROPAGATION_SLOT_RANGE` slots. - - The validator index is within the aggregate's committee -- i.e. `aggregate_and_proof.index in get_attesting_indices(state, aggregate_and_proof.aggregate.data, aggregate_and_proof.aggregate.aggregation_bits)`. - - `aggregate_and_proof.selection_proof` selects the validator as an aggregator for the slot -- i.e. `is_aggregator(state, aggregate_and_proof.aggregate.data.index, aggregate_and_proof.selection_proof)` returns `True`. - - The `aggregate_and_proof.selection_proof` is a valid signature of the `aggregate_and_proof.aggregate.data.slot` by the validator with index `aggregate_and_proof.index`. - - The signature of `aggregate_and_proof.aggregate` is valid. - -Attestation subnets are used to propagate unaggregated attestations to subsections of the network. Their `TopicName`s are: - -- `committee_index{index % ATTESTATION_SUBNET_COUNT}_beacon_attestation` - These topics are used to propagate unaggregated attestations to subsections of the network (typically beacon and persistent committees) to be aggregated before being gossiped to `beacon_aggregate_and_proof`. The following validations MUST pass before forwarding the `attestation` on the network. - - The attestation's committee index (`attestation.data.index`) is for the correct subnet. - - The attestation is unaggregated -- that is, it has exactly one participating validator (`len([bit for bit in attestation.aggregation_bits if bit == 0b1]) == 1`). - - The block being voted for (`attestation.data.beacon_block_root`) passes validation. - - `attestation.data.slot` is within the last `ATTESTATION_PROPAGATION_SLOT_RANGE` slots. - - The signature of `attestation` is valid. - -Additional topics are used to propagate lower frequency validator messages. Their `TopicName`s are: - -- `voluntary_exit` - This topic is used solely for propagating voluntary validator exits to proposers on the network. Voluntary exits are sent in their entirety. Clients who receive a voluntary exit on this topic MUST validate the conditions within `process_voluntary_exit` before forwarding it across the network. -- `proposer_slashing` - This topic is used solely for propagating proposer slashings to proposers on the network. Proposer slashings are sent in their entirety. Clients who receive a proposer slashing on this topic MUST validate the conditions within `process_proposer_slashing` before forwarding it across the network. -- `attester_slashing` - This topic is used solely for propagating attester slashings to proposers on the network. Attester slashings are sent in their entirety. Clients who receive an attester slashing on this topic MUST validate the conditions within `process_attester_slashing` before forwarding it across the network. - -#### Interop - -Unaggregated and aggregated attestations from all shards are sent as `Attestation`s to the `beacon_attestation` topic. Clients are not required to publish aggregate attestations but must be able to process them. All validating clients SHOULD try to perform local attestation aggregation to prepare for block proposing. - -#### Mainnet - -Attestation broadcasting is grouped into subnets defined by a topic. The number of subnets is defined via `ATTESTATION_SUBNET_COUNT`. The `CommitteeIndex`, `index`, is assigned to the topic: `committee_index{index % ATTESTATION_SUBNET_COUNT}_beacon_attestation`. - -Unaggregated attestations are sent to the subnet topic, `committee_index{attestation.data.index % ATTESTATION_SUBNET_COUNT}_beacon_attestation` as `Attestation`s. - -Aggregated attestations are sent to the `beacon_aggregate_and_proof` topic as `AggregateAndProof`s. - -### Messages - -Each gossipsub [message](https://github.com/libp2p/go-libp2p-pubsub/blob/master/pb/rpc.proto#L17-L24) has a maximum size of `GOSSIP_MAX_SIZE`. - -Clients MUST reject (fail validation) messages that are over this size limit. Likewise, clients MUST NOT emit or propagate messages larger than this limit. +Each gossipsub [message](https://github.com/libp2p/go-libp2p-pubsub/blob/master/pb/rpc.proto#L17-L24) has a maximum size of `GOSSIP_MAX_SIZE`. Clients MUST reject (fail validation) messages that are over this size limit. Likewise, clients MUST NOT emit or propagate messages larger than this limit. The payload is carried in the `data` field of a gossipsub message, and varies depending on the topic: - | Topic | Message Type | |----------------------------------------|-------------------| | beacon_block | BeaconBlock | @@ -211,6 +165,49 @@ When processing incoming gossip, clients MAY descore or disconnect peers who fai \* The `beacon_attestation` topic is only for interop and will be removed prior to mainnet. +#### Global topics + +There are two primary global topics used to propagate beacon blocks and aggregate attestations to all nodes on the network. Their `TopicName`s are: + +- `beacon_block` - This topic is used solely for propagating new beacon blocks to all nodes on the networks. Blocks are sent in their entirety. Clients MUST validate the block proposer signature before forwarding it across the network. +- `beacon_aggregate_and_proof` - This topic is used to propagate aggregated attestations (as `AggregateAndProof`s) to subscribing nodes (typically validators) to be included in future blocks. The following validations MUST pass before forwarding the `aggregate_and_proof` on the network. + - The aggregate attestation defined by `hash_tree_root(aggregate_and_proof.aggregate)` has _not_ already been seen (via aggregate gossip, within a block, or through the creation of an equivalent aggregate locally). + - The block being voted for (`aggregate_and_proof.aggregate.data.beacon_block_root`) passes validation. + - `aggregate_and_proof.aggregate.data.slot` is within the last `ATTESTATION_PROPAGATION_SLOT_RANGE` slots. + - The validator index is within the aggregate's committee -- i.e. `aggregate_and_proof.index in get_attesting_indices(state, aggregate_and_proof.aggregate.data, aggregate_and_proof.aggregate.aggregation_bits)`. + - `aggregate_and_proof.selection_proof` selects the validator as an aggregator for the slot -- i.e. `is_aggregator(state, aggregate_and_proof.aggregate.data.index, aggregate_and_proof.selection_proof)` returns `True`. + - The `aggregate_and_proof.selection_proof` is a valid signature of the `aggregate_and_proof.aggregate.data.slot` by the validator with index `aggregate_and_proof.index`. + - The signature of `aggregate_and_proof.aggregate` is valid. + +Additional global topics are used to propagate lower frequency validator messages. Their `TopicName`s are: + +- `voluntary_exit` - This topic is used solely for propagating voluntary validator exits to proposers on the network. Voluntary exits are sent in their entirety. Clients who receive a voluntary exit on this topic MUST validate the conditions within `process_voluntary_exit` before forwarding it across the network. +- `proposer_slashing` - This topic is used solely for propagating proposer slashings to proposers on the network. Proposer slashings are sent in their entirety. Clients who receive a proposer slashing on this topic MUST validate the conditions within `process_proposer_slashing` before forwarding it across the network. +- `attester_slashing` - This topic is used solely for propagating attester slashings to proposers on the network. Attester slashings are sent in their entirety. Clients who receive an attester slashing on this topic MUST validate the conditions within `process_attester_slashing` before forwarding it across the network. + +#### Attestation subnets + +Attestation subnets are used to propagate unaggregated attestations to subsections of the network. Their `TopicName`s are: + +- `committee_index{index % ATTESTATION_SUBNET_COUNT}_beacon_attestation` - These topics are used to propagate unaggregated attestations to subsections of the network (typically beacon and persistent committees) to be aggregated before being gossiped to `beacon_aggregate_and_proof`. The following validations MUST pass before forwarding the `attestation` on the network. + - The attestation's committee index (`attestation.data.index`) is for the correct subnet. + - The attestation is unaggregated -- that is, it has exactly one participating validator (`len([bit for bit in attestation.aggregation_bits if bit == 0b1]) == 1`). + - The block being voted for (`attestation.data.beacon_block_root`) passes validation. + - `attestation.data.slot` is within the last `ATTESTATION_PROPAGATION_SLOT_RANGE` slots. + - The signature of `attestation` is valid. + +#### Interop + +Unaggregated and aggregated attestations from all shards are sent as `Attestation`s to the `beacon_attestation` topic. Clients are not required to publish aggregate attestations but must be able to process them. All validating clients SHOULD try to perform local attestation aggregation to prepare for block proposing. + +#### Mainnet + +Attestation broadcasting is grouped into subnets defined by a topic. The number of subnets is defined via `ATTESTATION_SUBNET_COUNT`. The `CommitteeIndex`, `index`, is assigned to the topic: `committee_index{index % ATTESTATION_SUBNET_COUNT}_beacon_attestation`. + +Unaggregated attestations are sent to the subnet topic, `committee_index{attestation.data.index % ATTESTATION_SUBNET_COUNT}_beacon_attestation` as `Attestation`s. + +Aggregated attestations are sent to the `beacon_aggregate_and_proof` topic as `AggregateAndProof`s. + ### Encodings Topics are post-fixed with an encoding. Encodings define how the payload of a gossipsub message is encoded. From 3bb6aec3aba680b4493df26139d96cf71a545a4b Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Mon, 28 Oct 2019 17:10:48 +0800 Subject: [PATCH 16/17] Clarify committee_index subnets by defining and using "subnet" var Co-Authored-By: Hsiao-Wei Wang --- specs/networking/p2p-interface.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specs/networking/p2p-interface.md b/specs/networking/p2p-interface.md index 2338aaf88..787ecafb8 100644 --- a/specs/networking/p2p-interface.md +++ b/specs/networking/p2p-interface.md @@ -154,7 +154,7 @@ The payload is carried in the `data` field of a gossipsub message, and varies de | beacon_block | BeaconBlock | | beacon_aggregate_and_proof | AggregateAndProof | | beacon_attestation\* | Attestation | -| committee_index{N}\_beacon_attestation | Attestation | +| committee_index{subnet_id}\_beacon_attestation | Attestation | | voluntary_exit | VoluntaryExit | | proposer_slashing | ProposerSlashing | | attester_slashing | AttesterSlashing | @@ -189,7 +189,7 @@ Additional global topics are used to propagate lower frequency validator message Attestation subnets are used to propagate unaggregated attestations to subsections of the network. Their `TopicName`s are: -- `committee_index{index % ATTESTATION_SUBNET_COUNT}_beacon_attestation` - These topics are used to propagate unaggregated attestations to subsections of the network (typically beacon and persistent committees) to be aggregated before being gossiped to `beacon_aggregate_and_proof`. The following validations MUST pass before forwarding the `attestation` on the network. +- `committee_index{subnet_id}_beacon_attestation` - These topics are used to propagate unaggregated attestations to the subnet `subnet_id` (typically beacon and persistent committees) to be aggregated before being gossiped to `beacon_aggregate_and_proof`. The following validations MUST pass before forwarding the `attestation` on the subnet. - The attestation's committee index (`attestation.data.index`) is for the correct subnet. - The attestation is unaggregated -- that is, it has exactly one participating validator (`len([bit for bit in attestation.aggregation_bits if bit == 0b1]) == 1`). - The block being voted for (`attestation.data.beacon_block_root`) passes validation. @@ -202,7 +202,7 @@ Unaggregated and aggregated attestations from all shards are sent as `Attestatio #### Mainnet -Attestation broadcasting is grouped into subnets defined by a topic. The number of subnets is defined via `ATTESTATION_SUBNET_COUNT`. The `CommitteeIndex`, `index`, is assigned to the topic: `committee_index{index % ATTESTATION_SUBNET_COUNT}_beacon_attestation`. +Attestation broadcasting is grouped into subnets defined by a topic. The number of subnets is defined via `ATTESTATION_SUBNET_COUNT`. For the `committee_index{subnet_id}_beacon_attestation` topics, `subnet_id` is set to `index % ATTESTATION_SUBNET_COUNT`, where `index` is the `CommitteeIndex` of the given committee. Unaggregated attestations are sent to the subnet topic, `committee_index{attestation.data.index % ATTESTATION_SUBNET_COUNT}_beacon_attestation` as `Attestation`s. From 04c20aeb28d4eaec28f11aa2b37baf0c4051b7b6 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Mon, 28 Oct 2019 18:18:24 +0900 Subject: [PATCH 17/17] add expicit ranges for valid attesation propogation range --- specs/networking/p2p-interface.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specs/networking/p2p-interface.md b/specs/networking/p2p-interface.md index 787ecafb8..1872b5e5d 100644 --- a/specs/networking/p2p-interface.md +++ b/specs/networking/p2p-interface.md @@ -11,7 +11,7 @@ It consists of four main sections: ## Table of contents - + @@ -173,7 +173,7 @@ There are two primary global topics used to propagate beacon blocks and aggregat - `beacon_aggregate_and_proof` - This topic is used to propagate aggregated attestations (as `AggregateAndProof`s) to subscribing nodes (typically validators) to be included in future blocks. The following validations MUST pass before forwarding the `aggregate_and_proof` on the network. - The aggregate attestation defined by `hash_tree_root(aggregate_and_proof.aggregate)` has _not_ already been seen (via aggregate gossip, within a block, or through the creation of an equivalent aggregate locally). - The block being voted for (`aggregate_and_proof.aggregate.data.beacon_block_root`) passes validation. - - `aggregate_and_proof.aggregate.data.slot` is within the last `ATTESTATION_PROPAGATION_SLOT_RANGE` slots. + - `aggregate_and_proof.aggregate.data.slot` is within the last `ATTESTATION_PROPAGATION_SLOT_RANGE` slots (`aggregate_and_proof.aggregate.data.slot + ATTESTATION_PROPAGATION_SLOT_RANGE >= current_slot >= aggregate_and_proof.aggregate.data.slot`). - The validator index is within the aggregate's committee -- i.e. `aggregate_and_proof.index in get_attesting_indices(state, aggregate_and_proof.aggregate.data, aggregate_and_proof.aggregate.aggregation_bits)`. - `aggregate_and_proof.selection_proof` selects the validator as an aggregator for the slot -- i.e. `is_aggregator(state, aggregate_and_proof.aggregate.data.index, aggregate_and_proof.selection_proof)` returns `True`. - The `aggregate_and_proof.selection_proof` is a valid signature of the `aggregate_and_proof.aggregate.data.slot` by the validator with index `aggregate_and_proof.index`. @@ -193,7 +193,7 @@ Attestation subnets are used to propagate unaggregated attestations to subsectio - The attestation's committee index (`attestation.data.index`) is for the correct subnet. - The attestation is unaggregated -- that is, it has exactly one participating validator (`len([bit for bit in attestation.aggregation_bits if bit == 0b1]) == 1`). - The block being voted for (`attestation.data.beacon_block_root`) passes validation. - - `attestation.data.slot` is within the last `ATTESTATION_PROPAGATION_SLOT_RANGE` slots. + - `attestation.data.slot` is within the last `ATTESTATION_PROPAGATION_SLOT_RANGE` slots (`attestation.data.slot + ATTESTATION_PROPAGATION_SLOT_RANGE >= current_slot >= attestation.data.slot`). - The signature of `attestation` is valid. #### Interop