From 425f7d51c96f5b14a994267b668abacff4836ecd Mon Sep 17 00:00:00 2001 From: vbuterin Date: Sat, 15 Dec 2018 05:10:31 -0500 Subject: [PATCH 01/10] Keep randao mixes in the state Response to #295 Also a simplification, as two special cases get replaced: `state.randao_mix` -> `state.latest_randao_mixes[-1]`, and `state.next_seed` -> `state.latest_randao_mixes[-CYCLE_LENGTH-1]`. --- specs/core/0_beacon-chain.md | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 2097f6a0e..8d9f88d86 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -459,8 +459,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted 'validator_registry_delta_chain_tip': 'hash32', # For light clients to track deltas # Randomness and committees - 'randao_mix': 'hash32', - 'next_seed': 'hash32', + 'latest_randao_mixes': ['hash32'], 'shard_committees_at_slots': [[ShardCommittee]], 'persistent_committees': [['uint24']], 'persistent_committee_reassignments': [ShardReassignmentRecord], @@ -1154,8 +1153,7 @@ def get_initial_beacon_state(initial_validator_deposits: List[Deposit], validator_registry_delta_chain_tip=ZERO_HASH, # Randomness and committees - randao_mix=ZERO_HASH, - next_seed=ZERO_HASH, + latest_randao_mixes=[ZERO_HASH for _ in range(LATEST_BLOCK_ROOTS_LENGTH)], shard_committees_at_slots=[], persistent_committees=[], persistent_committee_reassignments=[], @@ -1415,7 +1413,7 @@ Below are the processing steps that happen at every `block`. * Let `repeat_hash(x, n) = x if n == 0 else repeat_hash(hash(x), n-1)`. * Let `proposer = state.validator_registry[get_beacon_proposer_index(state, state.slot)]`. * Verify that `repeat_hash(block.randao_reveal, proposer.randao_layers) == proposer.randao_commitment`. -* Set `state.randao_mix = xor(state.randao_mix, block.randao_reveal)`. +* Set `state.latest_randao_mixes = state.latest_randao_mixes[1:] + [xor(state.latest_randao_mixes[-1], block.randao_reveal)] * Set `proposer.randao_commitment = block.randao_reveal`. * Set `proposer.randao_layers = 0`. @@ -1749,15 +1747,14 @@ Also perform the following updates: * Set `state.validator_registry_latest_change_slot = state.slot`. * Set `state.shard_committees_at_slots[:EPOCH_LENGTH] = state.shard_committees_at_slots[EPOCH_LENGTH:]`. -* Set `state.shard_committees_at_slots[EPOCH_LENGTH:] = get_new_shuffling(state.next_seed, state.validator_registry, next_start_shard)` where `next_start_shard = (state.shard_committees_at_slots[-1][-1].shard + 1) % SHARD_COUNT`. -* Set `state.next_seed = state.randao_mix`. +* Set `state.shard_committees_at_slots[EPOCH_LENGTH:] = get_new_shuffling(state.latest_randao_mixes[-CYCLE_LENGTH-1], state.validator_registry, next_start_shard)` where `next_start_shard = (state.shard_committees_at_slots[-1][-1].shard + 1) % SHARD_COUNT`. If a validator registry update does _not_ happen do the following: * Set `state.shard_committees_at_slots[:EPOCH_LENGTH] = state.shard_committees_at_slots[EPOCH_LENGTH:]`. * Let `slots_since_finality = state.slot - state.validator_registry_latest_change_slot`. * Let `start_shard = state.shard_committees_at_slots[0][0].shard`. -* If `slots_since_finality * EPOCH_LENGTH <= MIN_VALIDATOR_REGISTRY_CHANGE_INTERVAL` or `slots_since_finality` is an exact power of 2, set `state.shard_committees_at_slots[EPOCH_LENGTH:] = get_new_shuffling(state.next_seed, state.validator_registry, start_shard)` and set `state.next_seed = state.randao_mix`. Note that `start_shard` is not changed from the last epoch. +* If `slots_since_finality * EPOCH_LENGTH <= MIN_VALIDATOR_REGISTRY_CHANGE_INTERVAL` or `slots_since_finality` is an exact power of 2, set `state.shard_committees_at_slots[EPOCH_LENGTH:] = get_new_shuffling(state.latest_randao_mixes[-CYCLE_LENGTH-1], state.validator_registry, start_shard)`. Note that `start_shard` is not changed from the last epoch. ### Proposer reshuffling @@ -1769,8 +1766,8 @@ num_validators_to_reshuffle = len(active_validator_indices) // SHARD_PERSISTENT_ for i in range(num_validators_to_reshuffle): # Multiplying i to 2 to ensure we have different input to all the required hashes in the shuffling # and none of the hashes used for entropy in this loop will be the same - validator_index = active_validator_indices[hash(state.randao_mix + bytes8(i * 2)) % len(active_validator_indices)] - new_shard = hash(state.randao_mix + bytes8(i * 2 + 1)) % SHARD_COUNT + validator_index = active_validator_indices[hash(state.latest_randao_mixes[-1] + bytes8(i * 2)) % len(active_validator_indices)] + new_shard = hash(state.latest_randao_mixes[-1] + bytes8(i * 2 + 1)) % SHARD_COUNT shard_reassignment_record = ShardReassignmentRecord( validator_index=validator_index, shard=new_shard, From d1aa3b4cd61f1e7ae00400eaa0002edf15025b5b Mon Sep 17 00:00:00 2001 From: vbuterin Date: Mon, 17 Dec 2018 04:44:49 -0500 Subject: [PATCH 02/10] Editing randao_mixes in place instead of as a queue Saves having to re-Merkelize an entire 8192-item list every block. --- specs/core/0_beacon-chain.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 8d9f88d86..e2748214d 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1413,7 +1413,7 @@ Below are the processing steps that happen at every `block`. * Let `repeat_hash(x, n) = x if n == 0 else repeat_hash(hash(x), n-1)`. * Let `proposer = state.validator_registry[get_beacon_proposer_index(state, state.slot)]`. * Verify that `repeat_hash(block.randao_reveal, proposer.randao_layers) == proposer.randao_commitment`. -* Set `state.latest_randao_mixes = state.latest_randao_mixes[1:] + [xor(state.latest_randao_mixes[-1], block.randao_reveal)] +* Set `state.latest_randao_mixes[block.slot % LATEST_BLOCK_ROOTS_LENGTH] = xor(state.latest_randao_mixes[(block.slot - 1) % LATEST_BLOCK_ROOTS_LENGTH], block.randao_reveal)` * Set `proposer.randao_commitment = block.randao_reveal`. * Set `proposer.randao_layers = 0`. @@ -1747,14 +1747,14 @@ Also perform the following updates: * Set `state.validator_registry_latest_change_slot = state.slot`. * Set `state.shard_committees_at_slots[:EPOCH_LENGTH] = state.shard_committees_at_slots[EPOCH_LENGTH:]`. -* Set `state.shard_committees_at_slots[EPOCH_LENGTH:] = get_new_shuffling(state.latest_randao_mixes[-CYCLE_LENGTH-1], state.validator_registry, next_start_shard)` where `next_start_shard = (state.shard_committees_at_slots[-1][-1].shard + 1) % SHARD_COUNT`. +* Set `state.shard_committees_at_slots[EPOCH_LENGTH:] = get_new_shuffling(state.latest_randao_mixes[(block.slot - CYCLE_LENGTH) % LATEST_BLOCK_ROOTS_LENGTH], state.validator_registry, next_start_shard)` where `next_start_shard = (state.shard_committees_at_slots[-1][-1].shard + 1) % SHARD_COUNT`. If a validator registry update does _not_ happen do the following: * Set `state.shard_committees_at_slots[:EPOCH_LENGTH] = state.shard_committees_at_slots[EPOCH_LENGTH:]`. * Let `slots_since_finality = state.slot - state.validator_registry_latest_change_slot`. * Let `start_shard = state.shard_committees_at_slots[0][0].shard`. -* If `slots_since_finality * EPOCH_LENGTH <= MIN_VALIDATOR_REGISTRY_CHANGE_INTERVAL` or `slots_since_finality` is an exact power of 2, set `state.shard_committees_at_slots[EPOCH_LENGTH:] = get_new_shuffling(state.latest_randao_mixes[-CYCLE_LENGTH-1], state.validator_registry, start_shard)`. Note that `start_shard` is not changed from the last epoch. +* If `slots_since_finality * EPOCH_LENGTH <= MIN_VALIDATOR_REGISTRY_CHANGE_INTERVAL` or `slots_since_finality` is an exact power of 2, set `state.shard_committees_at_slots[EPOCH_LENGTH:] = get_new_shuffling(state.latest_randao_mixes[(block.slot - CYCLE_LENGTH) % LATEST_BLOCK_ROOTS_LENGTH], state.validator_registry, start_shard)`. Note that `start_shard` is not changed from the last epoch. ### Proposer reshuffling From 365437d4c20c2db686ab7d11d5c6417ef263ae2b Mon Sep 17 00:00:00 2001 From: vbuterin Date: Mon, 17 Dec 2018 04:46:28 -0500 Subject: [PATCH 03/10] Forgot to update randao mixes in one place --- specs/core/0_beacon-chain.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index e2748214d..ee5c3ff2f 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1766,8 +1766,8 @@ num_validators_to_reshuffle = len(active_validator_indices) // SHARD_PERSISTENT_ for i in range(num_validators_to_reshuffle): # Multiplying i to 2 to ensure we have different input to all the required hashes in the shuffling # and none of the hashes used for entropy in this loop will be the same - validator_index = active_validator_indices[hash(state.latest_randao_mixes[-1] + bytes8(i * 2)) % len(active_validator_indices)] - new_shard = hash(state.latest_randao_mixes[-1] + bytes8(i * 2 + 1)) % SHARD_COUNT + validator_index = active_validator_indices[hash(state.latest_randao_mixes[block.slot % LATEST_BLOCK_ROOTS_LENGTH] + bytes8(i * 2)) % len(active_validator_indices)] + new_shard = hash(state.latest_randao_mixes[block.slot % LATEST_BLOCK_ROOTS_LENGTH] + bytes8(i * 2 + 1)) % SHARD_COUNT shard_reassignment_record = ShardReassignmentRecord( validator_index=validator_index, shard=new_shard, From 9c620d3853832d9b3b2ac8522239d0d318bc3eb2 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Mon, 17 Dec 2018 13:53:04 -0500 Subject: [PATCH 04/10] Update specs/core/0_beacon-chain.md Co-Authored-By: vbuterin --- specs/core/0_beacon-chain.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index ee5c3ff2f..01e30a488 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1747,7 +1747,7 @@ Also perform the following updates: * Set `state.validator_registry_latest_change_slot = state.slot`. * Set `state.shard_committees_at_slots[:EPOCH_LENGTH] = state.shard_committees_at_slots[EPOCH_LENGTH:]`. -* Set `state.shard_committees_at_slots[EPOCH_LENGTH:] = get_new_shuffling(state.latest_randao_mixes[(block.slot - CYCLE_LENGTH) % LATEST_BLOCK_ROOTS_LENGTH], state.validator_registry, next_start_shard)` where `next_start_shard = (state.shard_committees_at_slots[-1][-1].shard + 1) % SHARD_COUNT`. +* Set `state.shard_committees_at_slots[EPOCH_LENGTH:] = get_new_shuffling(state.latest_randao_mixes[(state.slot - CYCLE_LENGTH) % LATEST_BLOCK_ROOTS_LENGTH], state.validator_registry, next_start_shard)` where `next_start_shard = (state.shard_committees_at_slots[-1][-1].shard + 1) % SHARD_COUNT`. If a validator registry update does _not_ happen do the following: From eee26d7b69d611f7e142a4e28231d9439e8cf8ae Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Mon, 17 Dec 2018 13:53:17 -0500 Subject: [PATCH 05/10] Update specs/core/0_beacon-chain.md Co-Authored-By: vbuterin --- specs/core/0_beacon-chain.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 01e30a488..fdea52488 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1766,7 +1766,7 @@ num_validators_to_reshuffle = len(active_validator_indices) // SHARD_PERSISTENT_ for i in range(num_validators_to_reshuffle): # Multiplying i to 2 to ensure we have different input to all the required hashes in the shuffling # and none of the hashes used for entropy in this loop will be the same - validator_index = active_validator_indices[hash(state.latest_randao_mixes[block.slot % LATEST_BLOCK_ROOTS_LENGTH] + bytes8(i * 2)) % len(active_validator_indices)] + validator_index = active_validator_indices[hash(state.latest_randao_mixes[state.slot % LATEST_BLOCK_ROOTS_LENGTH] + bytes8(i * 2)) % len(active_validator_indices)] new_shard = hash(state.latest_randao_mixes[block.slot % LATEST_BLOCK_ROOTS_LENGTH] + bytes8(i * 2 + 1)) % SHARD_COUNT shard_reassignment_record = ShardReassignmentRecord( validator_index=validator_index, From e16c98b8540c0b23b609de3abbe7158d38430940 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Mon, 17 Dec 2018 13:53:35 -0500 Subject: [PATCH 06/10] Update specs/core/0_beacon-chain.md Co-Authored-By: vbuterin --- specs/core/0_beacon-chain.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index fdea52488..50adee4ed 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1754,7 +1754,7 @@ If a validator registry update does _not_ happen do the following: * Set `state.shard_committees_at_slots[:EPOCH_LENGTH] = state.shard_committees_at_slots[EPOCH_LENGTH:]`. * Let `slots_since_finality = state.slot - state.validator_registry_latest_change_slot`. * Let `start_shard = state.shard_committees_at_slots[0][0].shard`. -* If `slots_since_finality * EPOCH_LENGTH <= MIN_VALIDATOR_REGISTRY_CHANGE_INTERVAL` or `slots_since_finality` is an exact power of 2, set `state.shard_committees_at_slots[EPOCH_LENGTH:] = get_new_shuffling(state.latest_randao_mixes[(block.slot - CYCLE_LENGTH) % LATEST_BLOCK_ROOTS_LENGTH], state.validator_registry, start_shard)`. Note that `start_shard` is not changed from the last epoch. +* If `slots_since_finality * EPOCH_LENGTH <= MIN_VALIDATOR_REGISTRY_CHANGE_INTERVAL` or `slots_since_finality` is an exact power of 2, set `state.shard_committees_at_slots[EPOCH_LENGTH:] = get_new_shuffling(state.latest_randao_mixes[(state.slot - CYCLE_LENGTH) % LATEST_BLOCK_ROOTS_LENGTH], state.validator_registry, start_shard)`. Note that `start_shard` is not changed from the last epoch. ### Proposer reshuffling From 49ce718cc2e1ba4d56743b9fa593c53a8cad6f54 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Mon, 17 Dec 2018 13:53:42 -0500 Subject: [PATCH 07/10] Update specs/core/0_beacon-chain.md Co-Authored-By: vbuterin --- specs/core/0_beacon-chain.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 50adee4ed..afd39a0ec 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1767,7 +1767,7 @@ for i in range(num_validators_to_reshuffle): # Multiplying i to 2 to ensure we have different input to all the required hashes in the shuffling # and none of the hashes used for entropy in this loop will be the same validator_index = active_validator_indices[hash(state.latest_randao_mixes[state.slot % LATEST_BLOCK_ROOTS_LENGTH] + bytes8(i * 2)) % len(active_validator_indices)] - new_shard = hash(state.latest_randao_mixes[block.slot % LATEST_BLOCK_ROOTS_LENGTH] + bytes8(i * 2 + 1)) % SHARD_COUNT + new_shard = hash(state.latest_randao_mixes[state.slot % LATEST_BLOCK_ROOTS_LENGTH] + bytes8(i * 2 + 1)) % SHARD_COUNT shard_reassignment_record = ShardReassignmentRecord( validator_index=validator_index, shard=new_shard, From cc5cef52cb36ab84791c9d4fd1b3e577ab9bc538 Mon Sep 17 00:00:00 2001 From: vbuterin Date: Mon, 17 Dec 2018 14:04:04 -0500 Subject: [PATCH 08/10] Separated block roots and randao mixes length, and fixed per-slot randao updates --- specs/core/0_beacon-chain.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index afd39a0ec..1c9206a7f 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -166,6 +166,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted | `BLS_WITHDRAWAL_PREFIX_BYTE` | `0x00` | - | | `MAX_CASPER_VOTES` | `2**10` (= 1,024) | votes | | `LATEST_BLOCK_ROOTS_LENGTH` | `2**13` (= 8,192) | block roots | +| `LATEST_RANDAO_MIXES_LENGTH` | `2**13` (= 8,192) | block roots | | `EMPTY_SIGNATURE` | `[bytes48(0), bytes48(0)]` | - | * For the safety of crosslinks a minimum committee size of 111 is [recommended](https://vitalik.ca/files/Ithaca201807_Sharding.pdf). (Unbiasable randomness with a Verifiable Delay Function (VDF) will improve committee robustness and lower the safe minimum committee size.) The shuffling algorithm generally ensures (assuming sufficient validators) committee sizes at least `TARGET_COMMITTEE_SIZE // 2`. @@ -1153,7 +1154,7 @@ def get_initial_beacon_state(initial_validator_deposits: List[Deposit], validator_registry_delta_chain_tip=ZERO_HASH, # Randomness and committees - latest_randao_mixes=[ZERO_HASH for _ in range(LATEST_BLOCK_ROOTS_LENGTH)], + latest_randao_mixes=[ZERO_HASH for _ in range(LATEST_RANDAO_MIXES_LENGTH)], shard_committees_at_slots=[], persistent_committees=[], persistent_committee_reassignments=[], @@ -1387,11 +1388,12 @@ Below are the processing steps that happen at every slot. * Set `state.slot += 1`. * Set `state.validator_registry[get_beacon_proposer_index(state, state.slot)].randao_layers += 1`. +* Set `state.latest_randao_mixes = state.latest_randao_mixes[(block.slot - 1) % LATEST_RANDAO_MIXES_LENGTH]` ### Block roots * Let `previous_block_root` be the `hash_tree_root` of the previous beacon block processed in the chain. -* Set `state.latest_block_roots = state.latest_block_roots[1:] + [previous_block_root]`. +* Set `state.latest_block_roots[(block.slot - 1) % LATEST_BLOCK_ROOTS_LENGTH] = previous_block_root`. * If `state.slot % LATEST_BLOCK_ROOTS_LENGTH == 0` append `merkle_root(state.latest_block_roots)` to `state.batched_block_roots`. ## Per-block processing @@ -1413,7 +1415,7 @@ Below are the processing steps that happen at every `block`. * Let `repeat_hash(x, n) = x if n == 0 else repeat_hash(hash(x), n-1)`. * Let `proposer = state.validator_registry[get_beacon_proposer_index(state, state.slot)]`. * Verify that `repeat_hash(block.randao_reveal, proposer.randao_layers) == proposer.randao_commitment`. -* Set `state.latest_randao_mixes[block.slot % LATEST_BLOCK_ROOTS_LENGTH] = xor(state.latest_randao_mixes[(block.slot - 1) % LATEST_BLOCK_ROOTS_LENGTH], block.randao_reveal)` +* Set `state.latest_randao_mixes[block.slot % LATEST_RANDAO_MIXES_LENGTH] = xor(state.latest_randao_mixes[block.slot % LATEST_RANDAO_MIXES_LENGTH], block.randao_reveal)` * Set `proposer.randao_commitment = block.randao_reveal`. * Set `proposer.randao_layers = 0`. @@ -1747,14 +1749,14 @@ Also perform the following updates: * Set `state.validator_registry_latest_change_slot = state.slot`. * Set `state.shard_committees_at_slots[:EPOCH_LENGTH] = state.shard_committees_at_slots[EPOCH_LENGTH:]`. -* Set `state.shard_committees_at_slots[EPOCH_LENGTH:] = get_new_shuffling(state.latest_randao_mixes[(state.slot - CYCLE_LENGTH) % LATEST_BLOCK_ROOTS_LENGTH], state.validator_registry, next_start_shard)` where `next_start_shard = (state.shard_committees_at_slots[-1][-1].shard + 1) % SHARD_COUNT`. +* Set `state.shard_committees_at_slots[EPOCH_LENGTH:] = get_new_shuffling(state.latest_randao_mixes[(state.slot - EPOCH_LENGTH) % LATEST_RANDAO_MIXES_LENGTH], state.validator_registry, next_start_shard)` where `next_start_shard = (state.shard_committees_at_slots[-1][-1].shard + 1) % SHARD_COUNT`. If a validator registry update does _not_ happen do the following: * Set `state.shard_committees_at_slots[:EPOCH_LENGTH] = state.shard_committees_at_slots[EPOCH_LENGTH:]`. * Let `slots_since_finality = state.slot - state.validator_registry_latest_change_slot`. * Let `start_shard = state.shard_committees_at_slots[0][0].shard`. -* If `slots_since_finality * EPOCH_LENGTH <= MIN_VALIDATOR_REGISTRY_CHANGE_INTERVAL` or `slots_since_finality` is an exact power of 2, set `state.shard_committees_at_slots[EPOCH_LENGTH:] = get_new_shuffling(state.latest_randao_mixes[(state.slot - CYCLE_LENGTH) % LATEST_BLOCK_ROOTS_LENGTH], state.validator_registry, start_shard)`. Note that `start_shard` is not changed from the last epoch. +* If `slots_since_finality * EPOCH_LENGTH <= MIN_VALIDATOR_REGISTRY_CHANGE_INTERVAL` or `slots_since_finality` is an exact power of 2, set `state.shard_committees_at_slots[EPOCH_LENGTH:] = get_new_shuffling(state.latest_randao_mixes[(state.slot - CYCLE_LENGTH) % LATEST_RANDAO_MIXES_LENGTH], state.validator_registry, start_shard)`. Note that `start_shard` is not changed from the last epoch. ### Proposer reshuffling @@ -1766,8 +1768,8 @@ num_validators_to_reshuffle = len(active_validator_indices) // SHARD_PERSISTENT_ for i in range(num_validators_to_reshuffle): # Multiplying i to 2 to ensure we have different input to all the required hashes in the shuffling # and none of the hashes used for entropy in this loop will be the same - validator_index = active_validator_indices[hash(state.latest_randao_mixes[state.slot % LATEST_BLOCK_ROOTS_LENGTH] + bytes8(i * 2)) % len(active_validator_indices)] - new_shard = hash(state.latest_randao_mixes[state.slot % LATEST_BLOCK_ROOTS_LENGTH] + bytes8(i * 2 + 1)) % SHARD_COUNT + validator_index = active_validator_indices[hash(state.latest_randao_mixes[state.slot % LATEST_RANDAO_MIXES_LENGTH] + bytes8(i * 2)) % len(active_validator_indices)] + new_shard = hash(state.latest_randao_mixes[state.slot % LATEST_RANDAO_MIXES_LENGTH] + bytes8(i * 2 + 1)) % SHARD_COUNT shard_reassignment_record = ShardReassignmentRecord( validator_index=validator_index, shard=new_shard, From 261118011960bf636296dfd5fd79df5cfd111e03 Mon Sep 17 00:00:00 2001 From: vbuterin Date: Tue, 18 Dec 2018 05:33:03 -0500 Subject: [PATCH 09/10] Fixes as per Danny's comments --- specs/core/0_beacon-chain.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 1c9206a7f..75a96b48c 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -166,7 +166,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted | `BLS_WITHDRAWAL_PREFIX_BYTE` | `0x00` | - | | `MAX_CASPER_VOTES` | `2**10` (= 1,024) | votes | | `LATEST_BLOCK_ROOTS_LENGTH` | `2**13` (= 8,192) | block roots | -| `LATEST_RANDAO_MIXES_LENGTH` | `2**13` (= 8,192) | block roots | +| `LATEST_RANDAO_MIXES_LENGTH` | `2**13` (= 8,192) | randao mixes | | `EMPTY_SIGNATURE` | `[bytes48(0), bytes48(0)]` | - | * For the safety of crosslinks a minimum committee size of 111 is [recommended](https://vitalik.ca/files/Ithaca201807_Sharding.pdf). (Unbiasable randomness with a Verifiable Delay Function (VDF) will improve committee robustness and lower the safe minimum committee size.) The shuffling algorithm generally ensures (assuming sufficient validators) committee sizes at least `TARGET_COMMITTEE_SIZE // 2`. @@ -916,9 +916,8 @@ def get_block_root(state: BeaconState, """ Returns the block root at a recent ``slot``. """ - earliest_slot_in_array = state.slot - len(state.latest_block_roots) - assert earliest_slot_in_array <= slot < state.slot - return state.latest_block_roots[slot - earliest_slot_in_array] + assert slot > state.slot - LATEST_BLOCK_ROOTS_LENGTH + return state.latest_block_roots[slot % LATEST_BLOCK_ROOTS_LENGTH] ``` `get_block_root(_, s)` should always return `hash_tree_root` of the block in the beacon chain at slot `s`, and `get_shard_committees_at_slot(_, s)` should not change unless the [validator](#dfn-validator) registry changes. @@ -1388,12 +1387,12 @@ Below are the processing steps that happen at every slot. * Set `state.slot += 1`. * Set `state.validator_registry[get_beacon_proposer_index(state, state.slot)].randao_layers += 1`. -* Set `state.latest_randao_mixes = state.latest_randao_mixes[(block.slot - 1) % LATEST_RANDAO_MIXES_LENGTH]` +* Set `state.latest_randao_mixes[state.slot % LATEST_RANDAO_MIXES_LENGTH] = state.latest_randao_mixes[(state.slot - 1) % LATEST_RANDAO_MIXES_LENGTH]` ### Block roots * Let `previous_block_root` be the `hash_tree_root` of the previous beacon block processed in the chain. -* Set `state.latest_block_roots[(block.slot - 1) % LATEST_BLOCK_ROOTS_LENGTH] = previous_block_root`. +* Set `state.latest_block_roots[(state.slot - 1) % LATEST_BLOCK_ROOTS_LENGTH] = previous_block_root`. * If `state.slot % LATEST_BLOCK_ROOTS_LENGTH == 0` append `merkle_root(state.latest_block_roots)` to `state.batched_block_roots`. ## Per-block processing @@ -1415,7 +1414,7 @@ Below are the processing steps that happen at every `block`. * Let `repeat_hash(x, n) = x if n == 0 else repeat_hash(hash(x), n-1)`. * Let `proposer = state.validator_registry[get_beacon_proposer_index(state, state.slot)]`. * Verify that `repeat_hash(block.randao_reveal, proposer.randao_layers) == proposer.randao_commitment`. -* Set `state.latest_randao_mixes[block.slot % LATEST_RANDAO_MIXES_LENGTH] = xor(state.latest_randao_mixes[block.slot % LATEST_RANDAO_MIXES_LENGTH], block.randao_reveal)` +* Set `state.latest_randao_mixes[state.slot % LATEST_RANDAO_MIXES_LENGTH] = xor(state.latest_randao_mixes[state.slot % LATEST_RANDAO_MIXES_LENGTH], block.randao_reveal)` * Set `proposer.randao_commitment = block.randao_reveal`. * Set `proposer.randao_layers = 0`. From 36e26c86a37734b73a0fe503ac8f1d0acc9b9515 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Tue, 18 Dec 2018 12:53:48 -0600 Subject: [PATCH 10/10] fix assert conditions in get_block_hash --- specs/core/0_beacon-chain.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index d934ccc98..fa6ae338b 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -902,7 +902,8 @@ def get_block_root(state: BeaconState, """ Returns the block root at a recent ``slot``. """ - assert slot > state.slot - LATEST_BLOCK_ROOTS_LENGTH + assert state.slot <= slot + LATEST_BLOCK_ROOTS_LENGTH + assert slot < state.slot return state.latest_block_roots[slot % LATEST_BLOCK_ROOTS_LENGTH] ```