diff --git a/scripts/build_spec.py b/scripts/build_spec.py index ffdbda505..f35332e64 100644 --- a/scripts/build_spec.py +++ b/scripts/build_spec.py @@ -37,7 +37,7 @@ from eth2spec.utils.bls import ( from eth2spec.utils.hash_function import hash ''' PHASE1_IMPORTS = '''from typing import ( - Any, Dict, Optional, Set, Sequence, MutableSequence, NewType, Tuple, Union, + Any, Dict, Set, Sequence, MutableSequence, NewType, Tuple, Union, ) from math import ( log2, diff --git a/specs/core/1_beacon-chain-misc.md b/specs/core/1_beacon-chain-misc.md index 5bb0f6da0..6dd6e19c3 100644 --- a/specs/core/1_beacon-chain-misc.md +++ b/specs/core/1_beacon-chain-misc.md @@ -34,6 +34,7 @@ | `MAX_SHARD_RECEIPT_PROOFS` | `2**0` (= 1) | - | - | | `PERIOD_COMMITTEE_ROOT_LENGTH` | `2**8` (= 256) | periods | ~9 months | | `MINOR_REWARD_QUOTIENT` | `2**8` (=256) | - | - | +| `REWARD_COEFFICIENT_BASE` | **TBD** | - | - | ## Containers @@ -45,6 +46,16 @@ class CompactCommittee(Container): compact_validators: List[uint64, MAX_VALIDATORS_PER_COMMITTEE] ``` +#### `ShardReceiptDelta` + +```python +class ShardReceiptDelta(Container): + index: ValidatorIndex + reward_coefficient: uint64 + block_fee: Gwei +``` + + #### `ShardReceiptProof` ```python @@ -112,16 +123,17 @@ def verify_merkle_proof(leaf: Hash, proof: Sequence[Hash], index: GeneralizedInd ```python def compute_historical_state_generalized_index(earlier: ShardSlot, later: ShardSlot) -> GeneralizedIndex: """ - Computes the generalized index of the state root of slot `frm` based on the state root of slot `to`. - Relies on the `history_acc` in the `ShardState`, where `history_acc[i]` maintains the most recent 2**i'th - slot state. Works by tracing a `log(later-earlier)` step path from `later` to `earlier` through intermediate - blocks at the next available multiples of descending powers of two. + Computes the generalized index of the state root of slot `earlier` based on the state root of slot `later`. + Relies on the `history_accumulator` in the `ShardState`, where `history_accumulator[i]` maintains the most + recent 2**i'th slot state. Works by tracing a `log(later-earlier)` step path from `later` to `earlier` + through intermediate blocks at the next available multiples of descending powers of two. """ o = GeneralizedIndex(1) - for i in range(HISTORY_ACCUMULATOR_VECTOR - 1, -1, -1): + for i in range(HISTORY_ACCUMULATOR_DEPTH - 1, -1, -1): if (later - 1) & 2**i > (earlier - 1) & 2**i: later = later - ((later - 1) % 2**i) - 1 - o = concat_generalized_indices(o, GeneralizedIndex(get_generalized_index(ShardState, ['history_acc', i]))) + gindex = GeneralizedIndex(get_generalized_index(ShardState, ['history_accumulator', i])) + o = concat_generalized_indices(o, gindex) return o ``` @@ -133,7 +145,7 @@ def get_generalized_index_of_crosslink_header(index: int) -> GeneralizedIndex: Gets the generalized index for the root of the index'th header in a crosslink. """ MAX_CROSSLINK_SIZE = ( - SHARD_BLOCK_SIZE_LIMIT * SHARD_SLOTS_PER_BEACON_SLOT * SLOTS_PER_EPOCH * MAX_EPOCHS_PER_CROSSLINK + MAX_SHARD_BLOCK_SIZE * SHARD_SLOTS_PER_EPOCH * MAX_EPOCHS_PER_CROSSLINK ) assert MAX_CROSSLINK_SIZE == get_previous_power_of_two(MAX_CROSSLINK_SIZE) return GeneralizedIndex(MAX_CROSSLINK_SIZE // SHARD_HEADER_SIZE + index) @@ -146,10 +158,9 @@ def process_shard_receipt_proof(state: BeaconState, receipt_proof: ShardReceiptP """ Processes a ShardReceipt object. """ - SHARD_SLOTS_PER_EPOCH = SHARD_SLOTS_PER_BEACON_SLOT * SLOTS_PER_EPOCH receipt_slot = ( state.next_shard_receipt_period[receipt_proof.shard] * - SHARD_SLOTS_PER_BEACON_SLOT * SLOTS_PER_EPOCH * EPOCHS_PER_SHARD_PERIOD + SHARD_SLOTS_PER_EPOCH * EPOCHS_PER_SHARD_PERIOD ) first_slot_in_last_crosslink = state.current_crosslinks[receipt_proof.shard].start_epoch * SHARD_SLOTS_PER_EPOCH gindex = concat_generalized_indices( @@ -215,16 +226,18 @@ def update_period_committee(state: BeaconState) -> None: """ Updates period committee roots at boundary blocks. """ - if (get_current_epoch(state) + 1) % EPOCHS_PER_SHARD_PERIOD == 0: - period = (get_current_epoch(state) + 1) // EPOCHS_PER_SHARD_PERIOD - committees = Vector[CompactCommittee, SHARD_COUNT]([ - committee_to_compact_committee( - state, - get_period_committee(state, Epoch(get_current_epoch(state) + 1), Shard(shard)), - ) - for shard in range(SHARD_COUNT) - ]) - state.period_committee_roots[period % PERIOD_COMMITTEE_ROOT_LENGTH] = hash_tree_root(committees) + if (get_current_epoch(state) + 1) % EPOCHS_PER_SHARD_PERIOD != 0: + return + + period = (get_current_epoch(state) + 1) // EPOCHS_PER_SHARD_PERIOD + committees = Vector[CompactCommittee, SHARD_COUNT]([ + committee_to_compact_committee( + state, + get_period_committee(state, Shard(shard), Epoch(get_current_epoch(state) + 1)), + ) + for shard in range(SHARD_COUNT) + ]) + state.period_committee_roots[period % PERIOD_COMMITTEE_ROOT_LENGTH] = hash_tree_root(committees) ``` ### Shard receipt processing diff --git a/specs/core/1_shard-data-chains.md b/specs/core/1_shard-data-chains.md index 595909745..9293a50da 100644 --- a/specs/core/1_shard-data-chains.md +++ b/specs/core/1_shard-data-chains.md @@ -202,12 +202,11 @@ def get_shard_committee(beacon_state: BeaconState, shard: Shard, epoch: Epoch) - #### `get_shard_proposer_index` ```python -def get_shard_proposer_index(beacon_state: BeaconState, shard: Shard, slot: ShardSlot) -> Optional[ValidatorIndex]: +def get_shard_proposer_index(beacon_state: BeaconState, shard: Shard, slot: ShardSlot) -> ValidatorIndex: epoch = get_current_epoch(beacon_state) shard_committee = get_shard_committee(beacon_state, shard, epoch) active_indices = [i for i in shard_committee if is_active_validator(beacon_state.validators[i], epoch)] - if not any(active_indices): - return None + assert any(active_indices) epoch_seed = get_seed(beacon_state, epoch, DOMAIN_SHARD_PROPOSER) seed = hash(epoch_seed + int_to_bytes(slot, length=8) + int_to_bytes(shard, length=8)) @@ -224,7 +223,7 @@ def process_delta(beacon_state: BeaconState, index: ValidatorIndex, delta: Gwei, positive: bool=True) -> None: - epoch = compute_epoch_of_shard_slot(beacon_state.slot) + epoch = compute_epoch_of_shard_slot(shard_state.slot) older_committee = get_period_committee(beacon_state, shard_state.shard, compute_shard_period_start_epoch(epoch, 2)) newer_committee = get_period_committee(beacon_state, shard_state.shard, compute_shard_period_start_epoch(epoch, 1)) if index in older_committee: @@ -355,7 +354,8 @@ def process_shard_block_header(beacon_state: BeaconState, shard_state: ShardStat shard_state.block_size_sum += SHARD_HEADER_SIZE + len(block.body) assert block.block_size_sum == shard_state.block_size_sum # Verify proposer is not slashed - proposer = beacon_state.validators[get_shard_proposer_index(beacon_state, shard_state.shard, block.slot)] + proposer_index = get_shard_proposer_index(beacon_state, shard_state.shard, block.slot) + proposer = beacon_state.validators[proposer_index] assert not proposer.slashed # Verify proposer signature domain = get_domain(beacon_state, DOMAIN_SHARD_PROPOSER, compute_epoch_of_shard_slot(block.slot)) @@ -384,7 +384,7 @@ def process_shard_attestations(beacon_state: BeaconState, shard_state: ShardStat # Proposer micro-reward proposer_index = get_shard_proposer_index(beacon_state, shard_state.shard, block.slot) reward = attestation_count * get_base_reward(beacon_state, proposer_index) // PROPOSER_REWARD_QUOTIENT - process_delta(beacon_state, shard_state, proposer_index, reward) + process_delta(beacon_state, shard_state, proposer_index, Gwei(reward)) ``` #### Block body @@ -396,8 +396,8 @@ def process_shard_block_body(beacon_state: BeaconState, shard_state: ShardState, # Apply proposer block body fee block_body_fee = shard_state.block_body_price * len(block.body) // MAX_SHARD_BLOCK_SIZE proposer_index = get_shard_proposer_index(beacon_state, shard_state.shard, block.slot) - process_delta(beacon_state, shard_state, proposer_index, block_body_fee, positive=False) # Burn - process_delta(beacon_state, shard_state, proposer_index, block_body_fee // PROPOSER_REWARD_QUOTIENT) # Reward + process_delta(beacon_state, shard_state, proposer_index, Gwei(block_body_fee), positive=False) # Burn + process_delta(beacon_state, shard_state, proposer_index, Gwei(block_body_fee // PROPOSER_REWARD_QUOTIENT)) # Reward # Calculate new block body price block_size = SHARD_HEADER_SIZE + len(block.body) QUOTIENT = MAX_SHARD_BLOCK_SIZE * BLOCK_BODY_PRICE_QUOTIENT