From 59134fb0aecd9330cf07b825ede2e35bd0956f27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A9=20Monnot?= Date: Fri, 26 Mar 2021 12:18:51 +0800 Subject: [PATCH 01/19] Modify incentives to preserve invariant --- specs/altair/beacon-chain.md | 17 +++++++++-------- .../test_process_sync_committee.py | 5 ++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/specs/altair/beacon-chain.md b/specs/altair/beacon-chain.md index 81e7af14b..5389590b6 100644 --- a/specs/altair/beacon-chain.md +++ b/specs/altair/beacon-chain.md @@ -84,11 +84,12 @@ Altair is the first beacon chain hard fork. Its main features are: | Name | Value | | - | - | -| `TIMELY_HEAD_WEIGHT` | `12` | -| `TIMELY_SOURCE_WEIGHT` | `12` | -| `TIMELY_TARGET_WEIGHT` | `24` | -| `SYNC_REWARD_WEIGHT` | `8` | -| `WEIGHT_DENOMINATOR` | `64` | +| `TIMELY_HEAD_WEIGHT` | `3` | +| `TIMELY_SOURCE_WEIGHT` | `3` | +| `TIMELY_TARGET_WEIGHT` | `6` | +| `SYNC_REWARD_WEIGHT` | `2` | +| `NON_PROPOSER_TOTAL` | `14` | +| `WEIGHT_DENOMINATOR` | `16` | *Note*: The sum of the weight fractions (7/8) plus the proposer inclusion fraction (1/8) equals 1. @@ -477,7 +478,7 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None: proposer_reward_numerator += get_base_reward(state, index) * weight # Reward proposer - proposer_reward = Gwei(proposer_reward_numerator // (WEIGHT_DENOMINATOR * PROPOSER_REWARD_QUOTIENT)) + proposer_reward = Gwei(proposer_reward_numerator // (NON_PROPOSER_TOTAL * PROPOSER_REWARD_QUOTIENT)) increase_balance(state, get_beacon_proposer_index(state), proposer_reward) ``` @@ -550,9 +551,9 @@ def process_sync_committee(state: BeaconState, aggregate: SyncAggregate) -> None for included_index in included_indices: effective_balance = state.validators[included_index].effective_balance inclusion_reward = Gwei(max_slot_rewards * effective_balance // committee_effective_balance) - proposer_reward = Gwei(inclusion_reward // PROPOSER_REWARD_QUOTIENT) + proposer_reward = Gwei((inclusion_reward * WEIGHT_DENOMINATOR) // (NON_PROPOSER_TOTAL * PROPOSER_REWARD_QUOTIENT)) increase_balance(state, get_beacon_proposer_index(state), proposer_reward) - increase_balance(state, included_index, inclusion_reward - proposer_reward) + increase_balance(state, included_index, inclusion_reward) ``` ### Epoch processing diff --git a/tests/core/pyspec/eth2spec/test/altair/block_processing/test_process_sync_committee.py b/tests/core/pyspec/eth2spec/test/altair/block_processing/test_process_sync_committee.py index 958953176..b644d46b8 100644 --- a/tests/core/pyspec/eth2spec/test/altair/block_processing/test_process_sync_committee.py +++ b/tests/core/pyspec/eth2spec/test/altair/block_processing/test_process_sync_committee.py @@ -126,8 +126,7 @@ def compute_sync_committee_participant_reward(spec, state, participant_index, co inclusion_reward = compute_sync_committee_inclusion_reward( spec, state, participant_index, committee, committee_bits, ) - proposer_reward = spec.Gwei(inclusion_reward // spec.PROPOSER_REWARD_QUOTIENT) - return spec.Gwei((inclusion_reward - proposer_reward) * multiplicities[participant_index]) + return spec.Gwei(inclusion_reward * multiplicities[participant_index]) def compute_sync_committee_proposer_reward(spec, state, committee, committee_bits): @@ -138,7 +137,7 @@ def compute_sync_committee_proposer_reward(spec, state, committee, committee_bit inclusion_reward = compute_sync_committee_inclusion_reward( spec, state, index, committee, committee_bits, ) - proposer_reward += spec.Gwei(inclusion_reward // spec.PROPOSER_REWARD_QUOTIENT) + proposer_reward += spec.Gwei((inclusion_reward * spec.WEIGHT_DENOMINATOR) // (spec.NON_PROPOSER_TOTAL * spec.PROPOSER_REWARD_QUOTIENT)) return proposer_reward From 71d03a411c93ab4d1fe4c36a80302e4246f7f9ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A9=20Monnot?= Date: Fri, 26 Mar 2021 18:36:49 +0800 Subject: [PATCH 02/19] Scale up weights; use existing constants and new PROPOSER_WEIGHT --- specs/altair/beacon-chain.md | 18 ++++++++++-------- .../test_process_sync_committee.py | 3 ++- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/specs/altair/beacon-chain.md b/specs/altair/beacon-chain.md index 5389590b6..d81a3a0b1 100644 --- a/specs/altair/beacon-chain.md +++ b/specs/altair/beacon-chain.md @@ -84,12 +84,12 @@ Altair is the first beacon chain hard fork. Its main features are: | Name | Value | | - | - | -| `TIMELY_HEAD_WEIGHT` | `3` | -| `TIMELY_SOURCE_WEIGHT` | `3` | -| `TIMELY_TARGET_WEIGHT` | `6` | -| `SYNC_REWARD_WEIGHT` | `2` | -| `NON_PROPOSER_TOTAL` | `14` | -| `WEIGHT_DENOMINATOR` | `16` | +| `TIMELY_HEAD_WEIGHT` | `12` | +| `TIMELY_SOURCE_WEIGHT` | `12` | +| `TIMELY_TARGET_WEIGHT` | `24` | +| `SYNC_REWARD_WEIGHT` | `8` | +| `PROPOSER_WEIGHT` | `8` | +| `WEIGHT_DENOMINATOR` | `64` | *Note*: The sum of the weight fractions (7/8) plus the proposer inclusion fraction (1/8) equals 1. @@ -478,7 +478,8 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None: proposer_reward_numerator += get_base_reward(state, index) * weight # Reward proposer - proposer_reward = Gwei(proposer_reward_numerator // (NON_PROPOSER_TOTAL * PROPOSER_REWARD_QUOTIENT)) + reward_denominator = (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT) * PROPOSER_REWARD_QUOTIENT + proposer_reward = Gwei(proposer_reward_numerator // reward_denominator) increase_balance(state, get_beacon_proposer_index(state), proposer_reward) ``` @@ -551,7 +552,8 @@ def process_sync_committee(state: BeaconState, aggregate: SyncAggregate) -> None for included_index in included_indices: effective_balance = state.validators[included_index].effective_balance inclusion_reward = Gwei(max_slot_rewards * effective_balance // committee_effective_balance) - proposer_reward = Gwei((inclusion_reward * WEIGHT_DENOMINATOR) // (NON_PROPOSER_TOTAL * PROPOSER_REWARD_QUOTIENT)) + proposer_denominator = (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT) * PROPOSER_REWARD_QUOTIENT + proposer_reward = Gwei((inclusion_reward * WEIGHT_DENOMINATOR) // proposer_denominator) increase_balance(state, get_beacon_proposer_index(state), proposer_reward) increase_balance(state, included_index, inclusion_reward) ``` diff --git a/tests/core/pyspec/eth2spec/test/altair/block_processing/test_process_sync_committee.py b/tests/core/pyspec/eth2spec/test/altair/block_processing/test_process_sync_committee.py index b644d46b8..70509bea3 100644 --- a/tests/core/pyspec/eth2spec/test/altair/block_processing/test_process_sync_committee.py +++ b/tests/core/pyspec/eth2spec/test/altair/block_processing/test_process_sync_committee.py @@ -137,7 +137,8 @@ def compute_sync_committee_proposer_reward(spec, state, committee, committee_bit inclusion_reward = compute_sync_committee_inclusion_reward( spec, state, index, committee, committee_bits, ) - proposer_reward += spec.Gwei((inclusion_reward * spec.WEIGHT_DENOMINATOR) // (spec.NON_PROPOSER_TOTAL * spec.PROPOSER_REWARD_QUOTIENT)) + proposer_denominator = (spec.WEIGHT_DENOMINATOR - spec.PROPOSER_WEIGHT) * spec.PROPOSER_REWARD_QUOTIENT + proposer_reward += spec.Gwei((inclusion_reward * spec.WEIGHT_DENOMINATOR) // proposer_denominator) return proposer_reward From 0481e920f0cbc27719aa4597dc5646e3dfb5a86d Mon Sep 17 00:00:00 2001 From: Justin Date: Fri, 26 Mar 2021 10:51:29 +0000 Subject: [PATCH 03/19] Deprecate the use of PROPOSER_REWARD_QUOTIENT --- specs/altair/beacon-chain.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/specs/altair/beacon-chain.md b/specs/altair/beacon-chain.md index d81a3a0b1..0c4284ca5 100644 --- a/specs/altair/beacon-chain.md +++ b/specs/altair/beacon-chain.md @@ -413,7 +413,7 @@ def slash_validator(state: BeaconState, if whistleblower_index is None: whistleblower_index = proposer_index whistleblower_reward = Gwei(validator.effective_balance // WHISTLEBLOWER_REWARD_QUOTIENT) - proposer_reward = Gwei(whistleblower_reward // PROPOSER_REWARD_QUOTIENT) + proposer_reward = Gwei(whistleblower_reward * PROPOSER_WEIGHT // WEIGHT_DENOMINATOR) increase_balance(state, proposer_index, proposer_reward) increase_balance(state, whistleblower_index, Gwei(whistleblower_reward - proposer_reward)) ``` @@ -478,8 +478,8 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None: proposer_reward_numerator += get_base_reward(state, index) * weight # Reward proposer - reward_denominator = (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT) * PROPOSER_REWARD_QUOTIENT - proposer_reward = Gwei(proposer_reward_numerator // reward_denominator) + proposer_reward_denominator = (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT) * WEIGHT_DENOMINATOR // PROPOSER_WEIGHT + proposer_reward = Gwei(proposer_reward_numerator // proposer_reward_denominator) increase_balance(state, get_beacon_proposer_index(state), proposer_reward) ``` @@ -552,10 +552,10 @@ def process_sync_committee(state: BeaconState, aggregate: SyncAggregate) -> None for included_index in included_indices: effective_balance = state.validators[included_index].effective_balance inclusion_reward = Gwei(max_slot_rewards * effective_balance // committee_effective_balance) - proposer_denominator = (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT) * PROPOSER_REWARD_QUOTIENT - proposer_reward = Gwei((inclusion_reward * WEIGHT_DENOMINATOR) // proposer_denominator) - increase_balance(state, get_beacon_proposer_index(state), proposer_reward) increase_balance(state, included_index, inclusion_reward) + proposer_reward_denominator = (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT) * WEIGHT_DENOMINATOR // PROPOSER_WEIGHT + proposer_reward = Gwei(inclusion_reward * WEIGHT_DENOMINATOR // proposer_reward_denominator) + increase_balance(state, get_beacon_proposer_index(state), proposer_reward) ``` ### Epoch processing From 582965fd0bdc03c49af564f0c417c6ab30e7545c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A9=20Monnot?= Date: Fri, 26 Mar 2021 18:57:02 +0800 Subject: [PATCH 04/19] Deprecate PROPOSER_REWARD_QUOTIENT from tests --- .../test/altair/block_processing/test_process_sync_committee.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/altair/block_processing/test_process_sync_committee.py b/tests/core/pyspec/eth2spec/test/altair/block_processing/test_process_sync_committee.py index 70509bea3..fb6206388 100644 --- a/tests/core/pyspec/eth2spec/test/altair/block_processing/test_process_sync_committee.py +++ b/tests/core/pyspec/eth2spec/test/altair/block_processing/test_process_sync_committee.py @@ -137,7 +137,7 @@ def compute_sync_committee_proposer_reward(spec, state, committee, committee_bit inclusion_reward = compute_sync_committee_inclusion_reward( spec, state, index, committee, committee_bits, ) - proposer_denominator = (spec.WEIGHT_DENOMINATOR - spec.PROPOSER_WEIGHT) * spec.PROPOSER_REWARD_QUOTIENT + proposer_reward_denominator = (spec.WEIGHT_DENOMINATOR - spec.PROPOSER_WEIGHT) * spec.WEIGHT_DENOMINATOR // spec.PROPOSER_WEIGHT proposer_reward += spec.Gwei((inclusion_reward * spec.WEIGHT_DENOMINATOR) // proposer_denominator) return proposer_reward From d1c9b8bade7a6b65aa79e16b14409a97fbda97d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A9=20Monnot?= Date: Fri, 26 Mar 2021 19:03:12 +0800 Subject: [PATCH 05/19] Fix variable name --- .../test/altair/block_processing/test_process_sync_committee.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/altair/block_processing/test_process_sync_committee.py b/tests/core/pyspec/eth2spec/test/altair/block_processing/test_process_sync_committee.py index fb6206388..340273a8f 100644 --- a/tests/core/pyspec/eth2spec/test/altair/block_processing/test_process_sync_committee.py +++ b/tests/core/pyspec/eth2spec/test/altair/block_processing/test_process_sync_committee.py @@ -138,7 +138,7 @@ def compute_sync_committee_proposer_reward(spec, state, committee, committee_bit spec, state, index, committee, committee_bits, ) proposer_reward_denominator = (spec.WEIGHT_DENOMINATOR - spec.PROPOSER_WEIGHT) * spec.WEIGHT_DENOMINATOR // spec.PROPOSER_WEIGHT - proposer_reward += spec.Gwei((inclusion_reward * spec.WEIGHT_DENOMINATOR) // proposer_denominator) + proposer_reward += spec.Gwei((inclusion_reward * spec.WEIGHT_DENOMINATOR) // proposer_reward_denominator) return proposer_reward From d773c6ae9ea18150442ceb1dc4a451ae8b304b01 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Fri, 26 Mar 2021 08:28:34 -0600 Subject: [PATCH 06/19] lint from pr --- .../altair/block_processing/test_process_sync_committee.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/altair/block_processing/test_process_sync_committee.py b/tests/core/pyspec/eth2spec/test/altair/block_processing/test_process_sync_committee.py index 340273a8f..aa602e389 100644 --- a/tests/core/pyspec/eth2spec/test/altair/block_processing/test_process_sync_committee.py +++ b/tests/core/pyspec/eth2spec/test/altair/block_processing/test_process_sync_committee.py @@ -137,7 +137,11 @@ def compute_sync_committee_proposer_reward(spec, state, committee, committee_bit inclusion_reward = compute_sync_committee_inclusion_reward( spec, state, index, committee, committee_bits, ) - proposer_reward_denominator = (spec.WEIGHT_DENOMINATOR - spec.PROPOSER_WEIGHT) * spec.WEIGHT_DENOMINATOR // spec.PROPOSER_WEIGHT + proposer_reward_denominator = ( + (spec.WEIGHT_DENOMINATOR - spec.PROPOSER_WEIGHT) + * spec.WEIGHT_DENOMINATOR + // spec.PROPOSER_WEIGHT + ) proposer_reward += spec.Gwei((inclusion_reward * spec.WEIGHT_DENOMINATOR) // proposer_reward_denominator) return proposer_reward From 88d8f80957f618d64a49d3314d0a330e6e1388d5 Mon Sep 17 00:00:00 2001 From: Justin Date: Fri, 2 Apr 2021 14:52:32 +0100 Subject: [PATCH 07/19] Fix two bugs (and some cleanups) Fix two bugs: 1) The participant reward (previously known as "inclusion reward") should not be proportional to `effective_balance` because a sync committee member is already chosen with probability proportional to the effective balance. Credit to @vbuterin. 2) The participant reward (previously known as "inclusion reward") was too large by a factor of `len(participant_indices)`, not taking into account the `for` loop. Fixing these two bugs actually makes the code significantly simpler and cleaner :) @barnabemonnot: Could you check the logic? :) If confirmed happy to update the tests. --- specs/altair/beacon-chain.md | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/specs/altair/beacon-chain.md b/specs/altair/beacon-chain.md index ac71dccf9..35122a6d1 100644 --- a/specs/altair/beacon-chain.md +++ b/specs/altair/beacon-chain.md @@ -91,7 +91,7 @@ Altair is the first beacon chain hard fork. Its main features are: | `PROPOSER_WEIGHT` | `uint64(8)` | | `WEIGHT_DENOMINATOR` | `uint64(64)` | -*Note*: The sum of the weight fractions (7/8) plus the proposer inclusion fraction (1/8) equals 1. +*Note*: The sum of the weights equal `WEIGHT_DENOMINATOR`. ### Misc @@ -531,30 +531,25 @@ def process_deposit(state: BeaconState, deposit: Deposit) -> None: ```python def process_sync_committee(state: BeaconState, aggregate: SyncAggregate) -> None: # Verify sync committee aggregate signature signing over the previous slot block root - previous_slot = Slot(max(int(state.slot), 1) - 1) - committee_indices = get_sync_committee_indices(state, get_current_epoch(state)) - included_indices = [index for index, bit in zip(committee_indices, aggregate.sync_committee_bits) if bit] committee_pubkeys = state.current_sync_committee.pubkeys - included_pubkeys = [pubkey for pubkey, bit in zip(committee_pubkeys, aggregate.sync_committee_bits) if bit] + participant_pubkeys = [pubkey for pubkey, bit in zip(committee_pubkeys, aggregate.sync_committee_bits) if bit] + previous_slot = max(state.slot, Slot(1)) - Slot(1) domain = get_domain(state, DOMAIN_SYNC_COMMITTEE, compute_epoch_at_slot(previous_slot)) signing_root = compute_signing_root(get_block_root_at_slot(state, previous_slot), domain) - assert eth2_fast_aggregate_verify(included_pubkeys, signing_root, aggregate.sync_committee_signature) + assert eth2_fast_aggregate_verify(participant_pubkeys, signing_root, aggregate.sync_committee_signature) - # Compute the maximum sync rewards for the slot + # Compute the participant reward total_active_increments = get_total_active_balance(state) // EFFECTIVE_BALANCE_INCREMENT total_base_rewards = Gwei(get_base_reward_per_increment(state) * total_active_increments) - max_epoch_rewards = Gwei(total_base_rewards * SYNC_REWARD_WEIGHT // WEIGHT_DENOMINATOR) - max_slot_rewards = Gwei(max_epoch_rewards * len(included_indices) // len(committee_indices) // SLOTS_PER_EPOCH) + max_participant_rewards = Gwei(total_base_rewards * SYNC_REWARD_WEIGHT // WEIGHT_DENOMINATOR // SLOTS_PER_EPOCH) + participant_reward = Gwei(max_participant_rewards // SYNC_COMMITTEE_SIZE) - # Compute the participant and proposer sync rewards - committee_effective_balance = sum([state.validators[index].effective_balance for index in included_indices]) - committee_effective_balance = max(EFFECTIVE_BALANCE_INCREMENT, committee_effective_balance) - for included_index in included_indices: - effective_balance = state.validators[included_index].effective_balance - inclusion_reward = Gwei(max_slot_rewards * effective_balance // committee_effective_balance) - increase_balance(state, included_index, inclusion_reward) - proposer_reward_denominator = (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT) * WEIGHT_DENOMINATOR // PROPOSER_WEIGHT - proposer_reward = Gwei(inclusion_reward * WEIGHT_DENOMINATOR // proposer_reward_denominator) + # Compute the sync sync committee participant reward and the block proposer inclusion reward + committee_indices = get_sync_committee_indices(state, get_current_epoch(state)) + participant_indices = [index for index, bit in zip(committee_indices, aggregate.sync_committee_bits) if bit] + for participant_index in participant_indices: + increase_balance(state, participant_index, participant_reward) + proposer_reward = Gwei(participant_reward * PROPOSER_WEIGHT // (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT)) increase_balance(state, get_beacon_proposer_index(state), proposer_reward) ``` From 48fb9c39c2155950304554ec1b2d6bc5858f1f5f Mon Sep 17 00:00:00 2001 From: Justin Date: Fri, 2 Apr 2021 15:05:54 +0100 Subject: [PATCH 08/19] Update beacon-chain.md --- specs/altair/beacon-chain.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specs/altair/beacon-chain.md b/specs/altair/beacon-chain.md index 35122a6d1..72d511b04 100644 --- a/specs/altair/beacon-chain.md +++ b/specs/altair/beacon-chain.md @@ -538,18 +538,18 @@ def process_sync_committee(state: BeaconState, aggregate: SyncAggregate) -> None signing_root = compute_signing_root(get_block_root_at_slot(state, previous_slot), domain) assert eth2_fast_aggregate_verify(participant_pubkeys, signing_root, aggregate.sync_committee_signature) - # Compute the participant reward + # Compute participant and proposer rewards total_active_increments = get_total_active_balance(state) // EFFECTIVE_BALANCE_INCREMENT total_base_rewards = Gwei(get_base_reward_per_increment(state) * total_active_increments) max_participant_rewards = Gwei(total_base_rewards * SYNC_REWARD_WEIGHT // WEIGHT_DENOMINATOR // SLOTS_PER_EPOCH) participant_reward = Gwei(max_participant_rewards // SYNC_COMMITTEE_SIZE) + proposer_reward = Gwei(participant_reward * PROPOSER_WEIGHT // (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT)) - # Compute the sync sync committee participant reward and the block proposer inclusion reward + # Apply participant and proposer rewards committee_indices = get_sync_committee_indices(state, get_current_epoch(state)) participant_indices = [index for index, bit in zip(committee_indices, aggregate.sync_committee_bits) if bit] for participant_index in participant_indices: increase_balance(state, participant_index, participant_reward) - proposer_reward = Gwei(participant_reward * PROPOSER_WEIGHT // (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT)) increase_balance(state, get_beacon_proposer_index(state), proposer_reward) ``` From 9aaf548c37c007e7c8c1d9547aefa5c84162573b Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Fri, 2 Apr 2021 18:28:12 -0700 Subject: [PATCH 09/19] Fix language with sync committee selection proofs --- specs/altair/p2p-interface.md | 2 +- specs/altair/validator.md | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/specs/altair/p2p-interface.md b/specs/altair/p2p-interface.md index 6d400c0a2..ee6ab8292 100644 --- a/specs/altair/p2p-interface.md +++ b/specs/altair/p2p-interface.md @@ -92,7 +92,7 @@ The following validations MUST pass before forwarding the `signed_contribution_a - _[REJECT]_ `contribution_and_proof.selection_proof` selects the validator as an aggregator for the slot -- i.e. `is_sync_committee_aggregator(state, contribution.slot, contribution_and_proof.selection_proof)` returns `True`. - _[REJECT]_ The aggregator's validator index is within the current sync committee -- i.e. `state.validators[contribution_and_proof.aggregator_index].pubkey in state.current_sync_committee.pubkeys`. -- _[REJECT]_ The `contribution_and_proof.selection_proof` is a valid signature of the `contribution.slot` by the validator with index `contribution_and_proof.aggregator_index`. +- _[REJECT]_ The `contribution_and_proof.selection_proof` is a valid signature of the `SyncCommitteeSigningData` derived from the `contribution` by the validator with index `contribution_and_proof.aggregator_index`. - _[REJECT]_ The aggregator signature, `signed_contribution_and_proof.signature`, is valid. - _[REJECT]_ The aggregate signature is valid for the message `beacon_block_root` and aggregate pubkey derived from the participation info in `aggregation_bits` for the subcommittee specified by the `subcommittee_index`. diff --git a/specs/altair/validator.md b/specs/altair/validator.md index c7b41dd8b..ae4c64d03 100644 --- a/specs/altair/validator.md +++ b/specs/altair/validator.md @@ -310,12 +310,12 @@ Each slot some sync committee members in each subcommittee are selected to aggre ##### Aggregation selection -A validator is selected to aggregate based on the computation in `is_sync_committee_aggregator` where `state` is a `BeaconState` as supplied to `get_sync_committee_slot_signature` and `signature` is the BLS signature returned by `get_sync_committee_slot_signature`. +A validator is selected to aggregate based on the computation in `is_sync_committee_aggregator` where `state` is a `BeaconState` as supplied to `get_sync_committee_selection_proof` and `signature` is the BLS signature returned by `get_sync_committee_selection_proof`. The signature function takes a `BeaconState` with the relevant sync committees for the queried `slot` (i.e. `state.slot` is within the span covered by the current or next sync committee period), the `subcommittee_index` equal to the `subnet_id`, and the `privkey` is the BLS private key associated with the validator. ```python -def get_sync_committee_slot_signature(state: BeaconState, slot: Slot, - subcommittee_index: uint64, privkey: int) -> BLSSignature: +def get_sync_committee_selection_proof(state: BeaconState, slot: Slot, + subcommittee_index: uint64, privkey: int) -> BLSSignature: domain = get_domain(state, DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF, compute_epoch_at_slot(slot)) signing_data = SyncCommitteeSigningData( slot=slot, @@ -378,7 +378,7 @@ def get_contribution_and_proof(state: BeaconState, aggregator_index: ValidatorIndex, contribution: SyncCommitteeContribution, privkey: int) -> ContributionAndProof: - selection_proof = get_sync_committee_slot_signature( + selection_proof = get_sync_committee_selection_proof( state, contribution.slot, contribution.subcommittee_index, From 1a8ff79a18b011cac5c9485580e634f0c97f9cef Mon Sep 17 00:00:00 2001 From: ericsson Date: Mon, 5 Apr 2021 16:51:26 +0300 Subject: [PATCH 10/19] Add backquotes around DASSample, since setup.py/get_spec fails w/o them --- specs/das/das-core.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/das/das-core.md b/specs/das/das-core.md index ee73a6150..d2f48fa47 100644 --- a/specs/das/das-core.md +++ b/specs/das/das-core.md @@ -45,7 +45,7 @@ We define the following Python custom types for type hinting and readability: ## New containers -### DASSample +### `DASSample` ```python class DASSample(Container): From 71a609464c29bcc05da09bea946bdbb55f265a2a Mon Sep 17 00:00:00 2001 From: ericsson Date: Mon, 5 Apr 2021 16:53:03 +0300 Subject: [PATCH 11/19] fixed some typos, which blocks Python parser --- specs/sharding/beacon-chain.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/specs/sharding/beacon-chain.md b/specs/sharding/beacon-chain.md index 673cd7744..67dd16e08 100644 --- a/specs/sharding/beacon-chain.md +++ b/specs/sharding/beacon-chain.md @@ -108,7 +108,7 @@ The following values are (non-configurable) constants used throughout the specif | - | - | | `G1_SETUP` | Type `List[G1]`. The G1-side trusted setup `[G, G*s, G*s**2....]`; note that the first point is the generator. | | `G2_SETUP` | Type `List[G2]`. The G2-side trusted setup `[G, G*s, G*s**2....]` | -| `ROOT_OF_UNITY` | `pow(PRIMITIVE_ROOT_OF_UNITY, (MODULUS - 1) // (MAX_SAMPLES_PER_BLOCK * POINTS_PER_SAMPLE, MODULUS)` | +| `ROOT_OF_UNITY` | `pow(PRIMITIVE_ROOT_OF_UNITY, (MODULUS - 1) // (MAX_SAMPLES_PER_BLOCK * POINTS_PER_SAMPLE), MODULUS)` | ### Gwei values @@ -514,7 +514,7 @@ def process_shard_header(state: BeaconState, assert header.degree_proof == G1_SETUP[0] assert ( bls.Pairing(header.degree_proof, G2_SETUP[0]) - == bls.Pairing(header.commitment.point, G2_SETUP[-header.commitment.length])) + == bls.Pairing(header.commitment.point, G2_SETUP[-header.commitment.length]) ) # Get the correct pending header list @@ -618,7 +618,7 @@ def process_pending_headers(state: BeaconState) -> None: for slot_index in range(SLOTS_PER_EPOCH): for shard in range(SHARD_COUNT): state.grandparent_epoch_confirmed_commitments[shard][slot_index] = DataCommitment() - confirmed_headers = [candidate in state.previous_epoch_pending_shard_headers if candidate.confirmed] + confirmed_headers = [candidate for candidate in state.previous_epoch_pending_shard_headers if candidate.confirmed] for header in confirmed_headers: state.grandparent_epoch_confirmed_commitments[c.shard][c.slot % SLOTS_PER_EPOCH] = c.commitment ``` @@ -666,7 +666,7 @@ def reset_pending_headers(state: BeaconState) -> None: next_epoch = get_current_epoch(state) + 1 next_epoch_start_slot = compute_start_slot_at_epoch(next_epoch) for slot in range(next_epoch_start_slot, next_epoch_start_slot + SLOTS_IN_EPOCH): - for index in range(get_committee_count_per_slot(next_epoch): + for index in range(get_committee_count_per_slot(next_epoch)): shard = compute_shard_from_committee_index(state, slot, index) committee_length = len(get_beacon_committee(state, slot, shard)) state.current_epoch_pending_shard_headers.append(PendingShardHeader( From 99c1b75e596fa6140f69d99a562d94f569beb017 Mon Sep 17 00:00:00 2001 From: ericsson Date: Mon, 5 Apr 2021 17:08:38 +0300 Subject: [PATCH 12/19] More backquotes to make DocToc happy --- specs/das/das-core.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/das/das-core.md b/specs/das/das-core.md index d2f48fa47..ce39565a1 100644 --- a/specs/das/das-core.md +++ b/specs/das/das-core.md @@ -12,7 +12,7 @@ - [Configuration](#configuration) - [Misc](#misc) - [New containers](#new-containers) - - [DASSample](#dassample) + - [`DASSample`](#dassample) - [Helper functions](#helper-functions) - [Reverse bit ordering](#reverse-bit-ordering) - [`reverse_bit_order`](#reverse_bit_order) From c0a2ab54f13536feee4aca55028f2414c41f5513 Mon Sep 17 00:00:00 2001 From: ericsson Date: Mon, 5 Apr 2021 17:39:04 +0300 Subject: [PATCH 13/19] Type fixed: made BLSCommitment descending from Bytes48 instead of bytes48 --- specs/sharding/beacon-chain.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/sharding/beacon-chain.md b/specs/sharding/beacon-chain.md index 67dd16e08..7adc5bb27 100644 --- a/specs/sharding/beacon-chain.md +++ b/specs/sharding/beacon-chain.md @@ -70,7 +70,7 @@ We define the following Python custom types for type hinting and readability: | Name | SSZ equivalent | Description | | - | - | - | | `Shard` | `uint64` | A shard number | -| `BLSCommitment` | `bytes48` | A G1 curve point | +| `BLSCommitment` | `Bytes48` | A G1 curve point | | `BLSPoint` | `uint256` | A number `x` in the range `0 <= x < MODULUS` | ## Constants From 01dc8c6624bc6cb2f724b0dbb0ffb9c1b1a56ee9 Mon Sep 17 00:00:00 2001 From: ericsson Date: Mon, 5 Apr 2021 18:22:53 +0300 Subject: [PATCH 14/19] Type fixed: `boolean` instead of `bool` in `PendingShardHeader` --- specs/sharding/beacon-chain.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/sharding/beacon-chain.md b/specs/sharding/beacon-chain.md index 7adc5bb27..c0dab3ad9 100644 --- a/specs/sharding/beacon-chain.md +++ b/specs/sharding/beacon-chain.md @@ -223,7 +223,7 @@ class PendingShardHeader(Container): # Who voted for the header votes: Bitlist[MAX_VALIDATORS_PER_COMMITTEE] # Has this header been confirmed? - confirmed: bool + confirmed: boolean ``` ## Helper functions From 4a1126d91684e506e09d2e7ad367a046e28f2c0d Mon Sep 17 00:00:00 2001 From: Meredith Baxter Date: Mon, 5 Apr 2021 11:34:06 -0400 Subject: [PATCH 15/19] Fix table formatting --- specs/altair/p2p-interface.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/specs/altair/p2p-interface.md b/specs/altair/p2p-interface.md index 6d400c0a2..9b28c0382 100644 --- a/specs/altair/p2p-interface.md +++ b/specs/altair/p2p-interface.md @@ -183,6 +183,7 @@ Request and Response remain unchanged. A `ForkDigest`-context is used to select Per `context = compute_fork_digest(fork_version, genesis_validators_root)`: | `fork_version` | Chunk SSZ type | +| ------------------------ | -------------------------- | | `GENESIS_FORK_VERSION` | `phase0.SignedBeaconBlock` | | `ALTAIR_FORK_VERSION` | `altair.SignedBeaconBlock` | @@ -195,6 +196,7 @@ Request and Response remain unchanged. A `ForkDigest`-context is used to select Per `context = compute_fork_digest(fork_version, genesis_validators_root)`: | `fork_version` | Chunk SSZ type | +| ------------------------ | -------------------------- | | `GENESIS_FORK_VERSION` | `phase0.SignedBeaconBlock` | | `ALTAIR_FORK_VERSION` | `altair.SignedBeaconBlock` | From 0bbef67efe5b76fb197d805fba6a06d1cf45923f Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Tue, 6 Apr 2021 00:08:30 +0800 Subject: [PATCH 16/19] Add ALTAIR_INVAIANT_CHECKS, checks the weight configurations --- setup.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/setup.py b/setup.py index 91baf978f..6d9147661 100644 --- a/setup.py +++ b/setup.py @@ -277,6 +277,12 @@ ALTAIR_HARDCODED_SSZ_DEP_CONSTANTS = { } +ALTAIR_INVAIANT_CHECKS = ''' +assert ( + TIMELY_HEAD_WEIGHT + TIMELY_SOURCE_WEIGHT + TIMELY_TARGET_WEIGHT + SYNC_REWARD_WEIGHT + PROPOSER_WEIGHT +) == WEIGHT_DENOMINATOR''' + + def is_phase0(fork): return fork == PHASE0 @@ -331,6 +337,7 @@ def objects_to_spec(spec_object: SpecObject, imports: str, fork: str, ordered_cl if is_altair(fork): altair_ssz_dep_constants_verification = '\n'.join(map(lambda x: 'assert %s == %s' % (x, spec_object.ssz_dep_constants[x]), ALTAIR_HARDCODED_SSZ_DEP_CONSTANTS)) spec += '\n\n\n' + altair_ssz_dep_constants_verification + spec += '\n' + ALTAIR_INVAIANT_CHECKS spec += '\n' return spec From 746d6453bc791aa14c96383916ed2ec69619f803 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Mon, 5 Apr 2021 16:56:13 -0700 Subject: [PATCH 17/19] Clean up unnecessary function arguments Some of the inputs to some functions in the Altair validator guide were required in earlier iterations of the aggregation scheme but are no longer required in the current version. This commit cleans up these functions. --- specs/altair/validator.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/specs/altair/validator.md b/specs/altair/validator.md index ae4c64d03..89262f9ba 100644 --- a/specs/altair/validator.md +++ b/specs/altair/validator.md @@ -220,8 +220,7 @@ Given a collection of the best seen `contributions` (with no repeating `subcommi the proposer processes them as follows: ```python -def process_sync_committee_contributions(state: BeaconState, - block: BeaconBlock, +def process_sync_committee_contributions(block: BeaconBlock, contributions: Set[SyncCommitteeContribution]) -> None: sync_aggregate = SyncAggregate() signatures = [] @@ -310,7 +309,7 @@ Each slot some sync committee members in each subcommittee are selected to aggre ##### Aggregation selection -A validator is selected to aggregate based on the computation in `is_sync_committee_aggregator` where `state` is a `BeaconState` as supplied to `get_sync_committee_selection_proof` and `signature` is the BLS signature returned by `get_sync_committee_selection_proof`. +A validator is selected to aggregate based on the computation in `is_sync_committee_aggregator` where `signature` is the BLS signature returned by `get_sync_committee_selection_proof`. The signature function takes a `BeaconState` with the relevant sync committees for the queried `slot` (i.e. `state.slot` is within the span covered by the current or next sync committee period), the `subcommittee_index` equal to the `subnet_id`, and the `privkey` is the BLS private key associated with the validator. ```python @@ -326,7 +325,7 @@ def get_sync_committee_selection_proof(state: BeaconState, slot: Slot, ``` ```python -def is_sync_committee_aggregator(state: BeaconState, signature: BLSSignature) -> bool: +def is_sync_committee_aggregator(signature: BLSSignature) -> bool: modulo = max(1, SYNC_COMMITTEE_SIZE // SYNC_COMMITTEE_SUBNET_COUNT // TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE) return bytes_to_uint64(hash(signature)[0:8]) % modulo == 0 ``` From b2f42bf4d79432ee21e2f2b3912ff4bbf7898ada Mon Sep 17 00:00:00 2001 From: terence tsao Date: Mon, 5 Apr 2021 17:05:59 -0700 Subject: [PATCH 18/19] broadast -> broadcast --- specs/altair/validator.md | 2 +- specs/phase0/validator.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/altair/validator.md b/specs/altair/validator.md index ae4c64d03..4e3d8cab7 100644 --- a/specs/altair/validator.md +++ b/specs/altair/validator.md @@ -391,7 +391,7 @@ def get_contribution_and_proof(state: BeaconState, ) ``` -Then `signed_contribution_and_proof = SignedContributionAndProof(message=contribution_and_proof, signature=signature)` is constructed and broadast. Where `signature` is obtained from: +Then `signed_contribution_and_proof = SignedContributionAndProof(message=contribution_and_proof, signature=signature)` is constructed and broadcast. Where `signature` is obtained from: ```python def get_contribution_and_proof_signature(state: BeaconState, diff --git a/specs/phase0/validator.md b/specs/phase0/validator.md index e09d7ce88..a548003e1 100644 --- a/specs/phase0/validator.md +++ b/specs/phase0/validator.md @@ -589,7 +589,7 @@ def get_aggregate_and_proof(state: BeaconState, ) ``` -Then `signed_aggregate_and_proof = SignedAggregateAndProof(message=aggregate_and_proof, signature=signature)` is constructed and broadast. Where `signature` is obtained from: +Then `signed_aggregate_and_proof = SignedAggregateAndProof(message=aggregate_and_proof, signature=signature)` is constructed and broadcast. Where `signature` is obtained from: ```python def get_aggregate_and_proof_signature(state: BeaconState, From 20b465e788d6cc120e2d63d9aa220666524f9e54 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Mon, 5 Apr 2021 18:07:59 -0600 Subject: [PATCH 19/19] bump VERSION.txt to 1.1.0-alpha.3 --- tests/core/pyspec/eth2spec/VERSION.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/VERSION.txt b/tests/core/pyspec/eth2spec/VERSION.txt index 5655aea02..57b7d37da 100644 --- a/tests/core/pyspec/eth2spec/VERSION.txt +++ b/tests/core/pyspec/eth2spec/VERSION.txt @@ -1 +1 @@ -1.1.0-alpha.1 \ No newline at end of file +1.1.0-alpha.3 \ No newline at end of file