From 511f8034969bc24e12aaa870fbbf6cadeaea7d79 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Mon, 11 May 2020 12:44:46 -0600 Subject: [PATCH 1/3] use all attnets across the epoch even when not max committees per slot --- specs/phase0/p2p-interface.md | 21 ++++++++++----------- specs/phase0/validator.md | 16 ++++++++++++++-- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/specs/phase0/p2p-interface.md b/specs/phase0/p2p-interface.md index e06630ae5..98ee6edd2 100644 --- a/specs/phase0/p2p-interface.md +++ b/specs/phase0/p2p-interface.md @@ -151,7 +151,6 @@ 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 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. | @@ -221,12 +220,12 @@ The payload is carried in the `data` field of a gossipsub message, and varies de | Name | Message Type | |------------------------------------------------|-------------------------| -| beacon_block | SignedBeaconBlock | -| beacon_aggregate_and_proof | SignedAggregateAndProof | -| committee_index{subnet_id}\_beacon_attestation | Attestation | -| voluntary_exit | SignedVoluntaryExit | -| proposer_slashing | ProposerSlashing | -| attester_slashing | AttesterSlashing | +| beacon\_block | SignedBeaconBlock | +| beacon\_aggregate\_and\_proof | SignedAggregateAndProof | +| beacon_attestation\_{subnet\_id} | Attestation | +| voluntary\_exit | SignedVoluntaryExit | +| proposer\_slashing | ProposerSlashing | +| attester\_slashing | AttesterSlashing | Clients MUST reject (fail validation) messages containing an incorrect type, or invalid payload. @@ -273,8 +272,8 @@ 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 `Name`s are: -- `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. - - _[REJECT]_ The attestation's committee index (`attestation.data.index`) is for the correct subnet. +- `beacon_attestation_{subnet_id}` - 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. + - _[REJECT]_ The attestation is for the correct subnet (i.e. `compute_subnet_for_attestation(state, attestation) == subnet_id`). - _[IGNORE]_ `attestation.data.slot` is within the last `ATTESTATION_PROPAGATION_SLOT_RANGE` slots (within a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) -- i.e. `attestation.data.slot + ATTESTATION_PROPAGATION_SLOT_RANGE >= current_slot >= attestation.data.slot` (a client MAY queue future attestations for processing at the appropriate slot). - _[REJECT]_ The attestation is unaggregated -- that is, it has exactly one participating validator (`len([bit for bit in attestation.aggregation_bits if bit == 0b1]) == 1`). - _[IGNORE]_ There has been no other valid attestation seen on an attestation subnet that has an identical `attestation.data.target.epoch` and participating validator index. @@ -283,9 +282,9 @@ Attestation subnets are used to propagate unaggregated attestations to subsectio #### Attestations and Aggregation -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. +Attestation broadcasting is grouped into subnets defined by a topic. The number of subnets is defined via `ATTESTATION_SUBNET_COUNT`. The correct subnet for an attestation can be calculated with `compute_subnet_for_attestation`. `beacon_attestation_{subnet_id}` topics, are rotated through throughout the epoch in a similar fashion to rotating through shards in committees in Phase 1. -Unaggregated attestations are sent to the subnet topic, `committee_index{attestation.data.index % ATTESTATION_SUBNET_COUNT}_beacon_attestation` as `Attestation`s. +Unaggregated attestations are sent to the subnet topic, `beacon_attestation_{compute_subnet_for_attestation(state, attestation)}` as `Attestation`s. Aggregated attestations are sent to the `beacon_aggregate_and_proof` topic as `AggregateAndProof`s. diff --git a/specs/phase0/validator.md b/specs/phase0/validator.md index 62fdc0a93..398b882ee 100644 --- a/specs/phase0/validator.md +++ b/specs/phase0/validator.md @@ -90,6 +90,7 @@ All terminology, constants, functions, and protocol mechanics defined in the [Ph | `RANDOM_SUBNETS_PER_VALIDATOR` | `2**0` (= 1) | subnets | | | `EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION` | `2**8` (= 256) | epochs | ~27 hours | | `SECONDS_PER_ETH1_BLOCK` | `14` | seconds | | +| `ATTESTATION_SUBNET_COUNT` | `64` | The number of attestation subnets used in the gossipsub protocol. | ## Becoming a validator @@ -418,7 +419,18 @@ def get_attestation_signature(state: BeaconState, attestation_data: AttestationD #### Broadcast attestation -Finally, the validator broadcasts `attestation` to the associated attestation subnet -- the `committee_index{attestation.data.index % ATTESTATION_SUBNET_COUNT}_beacon_attestation` pubsub topic. +Finally, the validator broadcasts `attestation` to the associated attestation subnet -- the `beacon_attestation_{compute_subnet_for_attestation(state, attestation)}` pubsub topic. + +```python +def compute_subnet_for_attestation(state: BeaconState, attestation: Attestation) -> uint64: + slots_since_epoch_start = attestation.data.slot % SLOTS_PER_EPOCH + committees_since_epoch_start = sum([ + get_committee_count_at_slot(state, Slot(slot)) + for slot in range(slots_since_epoch_start) + ]) + + return (committees_since_epoch_start + attestation.data.index) % ATTESTATION_SUBNET_COUNT +``` ### Attestation aggregation @@ -519,7 +531,7 @@ class SignedAggregateAndProof(Container): ## Phase 0 attestation subnet stability -Because Phase 0 does not have shards and thus does not have Shard Committees, there is no stable backbone to the attestation subnets (`committee_index{subnet_id}_beacon_attestation`). To provide this stability, each validator must: +Because Phase 0 does not have shards and thus does not have Shard Committees, there is no stable backbone to the attestation subnets (`beacon_attestation_{subnet_id}`). To provide this stability, each validator must: * Randomly select and remain subscribed to `RANDOM_SUBNETS_PER_VALIDATOR` attestation subnets * Maintain advertisement of the randomly selected subnets in their node's ENR `attnets` entry by setting the randomly selected `subnet_id` bits to `True` (e.g. `ENR["attnets"][subnet_id] = True`) for all persistent attestation subnets From 3dd168335bf5a86a753a5f34de3afd2c1ad36bcf Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 14 May 2020 13:50:29 -0600 Subject: [PATCH 2/3] reformat compute_subnet_for_attestation to not use for loop --- specs/phase0/validator.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/specs/phase0/validator.md b/specs/phase0/validator.md index 398b882ee..75aae1f2e 100644 --- a/specs/phase0/validator.md +++ b/specs/phase0/validator.md @@ -423,11 +423,12 @@ Finally, the validator broadcasts `attestation` to the associated attestation su ```python def compute_subnet_for_attestation(state: BeaconState, attestation: Attestation) -> uint64: + """ + Compute the correct subnet for an attestation for Phase 0. + Note, this mimics expected Phase 1 behavior where attestations will be mapped to their shard subnet. + """ slots_since_epoch_start = attestation.data.slot % SLOTS_PER_EPOCH - committees_since_epoch_start = sum([ - get_committee_count_at_slot(state, Slot(slot)) - for slot in range(slots_since_epoch_start) - ]) + committees_since_epoch_start = get_committee_count_at_slot(state, attestation.data.slot) * slots_since_epoch_start return (committees_since_epoch_start + attestation.data.index) % ATTESTATION_SUBNET_COUNT ``` From 483f9a1d7b7faeafe635229881810247c754371b Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 14 May 2020 14:25:32 -0600 Subject: [PATCH 3/3] Update specs/phase0/p2p-interface.md Co-authored-by: Diederik Loerakker --- specs/phase0/p2p-interface.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/specs/phase0/p2p-interface.md b/specs/phase0/p2p-interface.md index 98ee6edd2..7b9d6b737 100644 --- a/specs/phase0/p2p-interface.md +++ b/specs/phase0/p2p-interface.md @@ -220,12 +220,14 @@ The payload is carried in the `data` field of a gossipsub message, and varies de | Name | Message Type | |------------------------------------------------|-------------------------| -| beacon\_block | SignedBeaconBlock | -| beacon\_aggregate\_and\_proof | SignedAggregateAndProof | -| beacon_attestation\_{subnet\_id} | Attestation | -| voluntary\_exit | SignedVoluntaryExit | -| proposer\_slashing | ProposerSlashing | -| attester\_slashing | AttesterSlashing | +| Name | Message Type | +|----------------------------------|---------------------------| +| `beacon_block` | `SignedBeaconBlock` | +| `beacon_aggregate_and_proof` | `SignedAggregateAndProof` | +| `beacon_attestation_{subnet_id}` | `Attestation` | +| `voluntary_exit` | `SignedVoluntaryExit` | +| `proposer_slashing` | `ProposerSlashing` | +| `attester_slashing` | `AttesterSlashing` | Clients MUST reject (fail validation) messages containing an incorrect type, or invalid payload.