working through attestation aggregation

This commit is contained in:
Danny Ryan 2019-10-22 15:49:50 +08:00
parent a11b01296b
commit bc8ff33a37
No known key found for this signature in database
GPG Key ID: 2765A792E42CE07A
2 changed files with 78 additions and 6 deletions

View File

@ -164,9 +164,9 @@ Unaggregated and aggregated attestations from all shards are sent to the `beacon
#### Mainnet #### 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 ### Messages

View File

@ -37,7 +37,7 @@
- [Attestations](#attestations) - [Attestations](#attestations)
- [Deposits](#deposits) - [Deposits](#deposits)
- [Voluntary exits](#voluntary-exits) - [Voluntary exits](#voluntary-exits)
- [Attestations](#attestations-1) - [Attesting](#attesting)
- [Attestation data](#attestation-data) - [Attestation data](#attestation-data)
- [LMD GHOST vote](#lmd-ghost-vote) - [LMD GHOST vote](#lmd-ghost-vote)
- [FFG vote](#ffg-vote) - [FFG vote](#ffg-vote)
@ -46,6 +46,15 @@
- [Aggregation bits](#aggregation-bits) - [Aggregation bits](#aggregation-bits)
- [Custody bits](#custody-bits) - [Custody bits](#custody-bits)
- [Aggregate signature](#aggregate-signature) - [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) - [How to avoid slashing](#how-to-avoid-slashing)
- [Proposer slashing](#proposer-slashing) - [Proposer slashing](#proposer-slashing)
- [Attester slashing](#attester-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). 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 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 #### Attestation data
@ -314,7 +323,7 @@ Set `attestation.data = attestation_data` where `attestation_data` is the `Attes
##### Aggregation bits ##### 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`. *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) 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 ## 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. "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.