diff --git a/specs/core/1_beacon_chain_misc.md b/specs/core/1_beacon_chain_misc.md index 09e3c2c61..b5b76a9a9 100644 --- a/specs/core/1_beacon_chain_misc.md +++ b/specs/core/1_beacon_chain_misc.md @@ -50,6 +50,65 @@ def committee_to_compact_committee(state: BeaconState, committee: Sequence[Valid return CompactCommittee(pubkeys=pubkeys, compact_validators=compact_validators) ``` +#### `get_previous_power_of_2` + +```python +def get_previous_power_of_2(x: int) -> int: + return x if x <= 2 else 2 * get_previous_power_of_2(x // 2) +``` + + +#### `concat_generalized_indices` + +```python +def concat_generalized_indices(*indices: Sequence[GeneralizedIndex]) -> GeneralizedIndex: + o = GeneralizedIndex(1) + for i in indices: + o = o * get_previous_power_of_2(i) + i + return o +``` + +#### `compute_historical_state_generalized_index` + +```python +def compute_historical_state_generalized_index(frm: ShardSlot, to: ShardSlot) -> GeneralizedIndex: + o = GeneralizedIndex(1) + for i in range(63, -1, -1): + if (to-1) & 2**i > (frm-1) & 2**i: + to = to - ((to-1) % 2**i) - 1 + o = concat_generalized_indices(o, get_generalized_index(ShardState, 'history_acc', i)) + return o +``` + +#### `get_generalized_index_of_crosslink_header` + +```python +def get_generalized_index_of_crosslink_header(index: int) -> GeneralizedIndex: + MAX_CROSSLINK_SIZE = SHARD_BLOCK_SIZE_LIMIT * SHARD_SLOTS_PER_BEACON_SLOT * SLOTS_PER_EPOCH * MAX_EPOCHS_PER_CROSSLINK + assert MAX_CROSSLINK_SIZE == get_previous_power_of_2(MAX_CROSSLINK_SIZE) + return GeneralizedIndex(MAX_CROSSLINK_SIZE // SHARD_HEADER_SIZE + index) +``` + +#### `process_shard_receipt` + +```python +def process_shard_receipt(state: BeaconState, shard: Shard, proof: List[Hash, PLACEHOLDER], receipt: List[ShardReceiptDelta, PLACEHOLDER]): + receipt_slot = state.next_shard_receipt_period[shard] * SLOTS_PER_EPOCH * EPOCHS_PER_SHARD_PERIOD + first_slot_in_last_crosslink = state.current_crosslinks[shard].start_epoch * SLOTS_PER_EPOCH + gindex = concat_generalized_indices( + get_generalized_index_of_crosslink_header(0), + get_generalized_index(ShardBlockHeader, 'state_root') + compute_historical_state_generalized_index(receipt_slot, first_slot_in_last_crosslink) + get_generalized_index(ShardState, 'receipt_root') + ) + assert verify_merkle_proof( + leaf=hash_tree_root(receipt), + proof=proof, + index=gindex, + root=state.current_crosslinks[shard].data_root + ) +``` + ## Changes ### Persistent committees @@ -59,6 +118,7 @@ Add to the beacon state the following fields: * `previous_persistent_committee_root: Hash` * `current_persistent_committee_root: Hash` * `next_persistent_committee_root: Hash` +* `next_shard_receipt_period: Vector[uint, SHARD_COUNT]`, values initialized to `PHASE_1_FORK_SLOT // SLOTS_PER_EPOCH // EPOCHS_PER_SHARD_PERIOD` Process the following function before `process_final_updates`: