From 88d8f80957f618d64a49d3314d0a330e6e1388d5 Mon Sep 17 00:00:00 2001 From: Justin Date: Fri, 2 Apr 2021 14:52:32 +0100 Subject: [PATCH] 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) ```