From 10a8ba2d9e66957a17c805ff26315ae2d4575f1f Mon Sep 17 00:00:00 2001 From: terence tsao Date: Fri, 28 Dec 2018 09:04:00 -0800 Subject: [PATCH 01/14] rewording for validator registry precondition --- 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 045a914b0..6e054853b 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1726,7 +1726,7 @@ def process_ejections(state: BeaconState) -> None: If the following are satisfied: * `state.finalized_slot > state.validator_registry_latest_change_slot` -* `state.latest_crosslinks[shard].slot > state.validator_registry_latest_change_slot` for every shard number `shard` in `state.shard_committees_at_slots` +* `state.latest_crosslinks[shard].slot > state.validator_registry_latest_change_slot` for every shard number `shard` in `shard_committee` from `shard_committee_at_slot` in `state.shard_committees_at_slots` update the validator registry and associated fields by running From 429e5721f224c5ac61e55aa9eb277f34bef7700d Mon Sep 17 00:00:00 2001 From: Justin Date: Wed, 2 Jan 2019 14:20:01 +0000 Subject: [PATCH 02/14] RANDAO hash chain and no stale shuffles * Make RANDAO into a hash chain (this makes it easy for applications to prove the intermediate RANDAO reveals). * Include `state.slot` when shuffle to avoid stale shuffles with skip slots --- specs/core/0_beacon-chain.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index beafa9372..97f4ea97c 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -187,6 +187,7 @@ Unless otherwise indicated, code appearing in `this style` is to be interpreted | - | - | | `INITIAL_FORK_VERSION` | `0` | | `INITIAL_SLOT_NUMBER` | `0` | +| `GENESIS_START_SHARD` | `0` | | `ZERO_HASH` | `bytes([0] * 32)` | ### Time parameters @@ -863,10 +864,11 @@ def split(values: List[Any], split_count: int) -> List[Any]: ```python def get_new_shuffling(seed: Hash32, + slot: int, validators: List[ValidatorRecord], crosslinking_start_shard: int) -> List[List[ShardCommittee]]: """ - Shuffles ``validators`` into shard committees using ``seed`` as entropy. + Shuffles ``validators`` into shard committees using ``seed`` and ``slot`` as entropy. """ active_validator_indices = get_active_validator_indices(validators) @@ -879,7 +881,7 @@ def get_new_shuffling(seed: Hash32, ) # Shuffle with seed - shuffled_active_validator_indices = shuffle(active_validator_indices, seed) + shuffled_active_validator_indices = shuffle(active_validator_indices, xor(seed, Hash32(slot)) # Split the shuffled list into epoch_length pieces validators_per_slot = split(shuffled_active_validator_indices, EPOCH_LENGTH) @@ -1221,7 +1223,7 @@ def get_initial_beacon_state(initial_validator_deposits: List[Deposit], update_validator_status(state, validator_index, ACTIVE) # set initial committee shuffling - initial_shuffling = get_new_shuffling(ZERO_HASH, state.validator_registry, 0) + initial_shuffling = get_new_shuffling(ZERO_HASH, state.slot, state.validator_registry, GENESIS_START_SHARD) state.shard_committees_at_slots = initial_shuffling + initial_shuffling return state @@ -1458,7 +1460,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.slot % LATEST_RANDAO_MIXES_LENGTH] = xor(state.latest_randao_mixes[state.slot % LATEST_RANDAO_MIXES_LENGTH], block.randao_reveal)` +* Set `state.latest_randao_mixes[state.slot % LATEST_RANDAO_MIXES_LENGTH] = hash(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`. @@ -1783,14 +1785,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 - 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`. +* Set `state.shard_committees_at_slots[EPOCH_LENGTH:] = get_new_shuffling(state.latest_randao_mixes[(state.slot - EPOCH_LENGTH) % LATEST_RANDAO_MIXES_LENGTH], state.slot, 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 `epochs_since_last_registry_change = (state.slot - state.validator_registry_latest_change_slot) // EPOCH_LENGTH`. * Let `start_shard = state.shard_committees_at_slots[0][0].shard`. -* If `epochs_since_last_registry_change` is an exact power of 2, 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, start_shard)`. Note that `start_shard` is not changed from the last epoch. +* If `epochs_since_last_registry_change` is an exact power of 2, set `state.shard_committees_at_slots[EPOCH_LENGTH:] = get_new_shuffling(state.latest_randao_mixes[(state.slot - EPOCH_LENGTH) % LATEST_RANDAO_MIXES_LENGTH], state.slot, state.validator_registry, start_shard)`. Note that `start_shard` is not changed from the last epoch. ### Final updates From 3efe1b3b6cd28f1c6dffabec0da50c5ff9ceca4f Mon Sep 17 00:00:00 2001 From: Justin Date: Wed, 2 Jan 2019 15:21:22 +0000 Subject: [PATCH 03/14] Update 0_beacon-chain.md --- specs/core/0_beacon-chain.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 97f4ea97c..30f9047c6 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -863,12 +863,12 @@ def split(values: List[Any], split_count: int) -> List[Any]: #### `get_new_shuffling` ```python -def get_new_shuffling(seed: Hash32, +def get_new_shuffling(randao_mix: Hash32, slot: int, validators: List[ValidatorRecord], crosslinking_start_shard: int) -> List[List[ShardCommittee]]: """ - Shuffles ``validators`` into shard committees using ``seed`` and ``slot`` as entropy. + Shuffles ``validators`` into shard committees seeded by ``randao_mix`` and ``slot``. """ active_validator_indices = get_active_validator_indices(validators) @@ -880,8 +880,9 @@ def get_new_shuffling(seed: Hash32, ) ) - # Shuffle with seed - shuffled_active_validator_indices = shuffle(active_validator_indices, xor(seed, Hash32(slot)) + # Shuffle + seed = xor(randao_mix, Hash32(slot)) + shuffled_active_validator_indices = shuffle(active_validator_indices, seed) # Split the shuffled list into epoch_length pieces validators_per_slot = split(shuffled_active_validator_indices, EPOCH_LENGTH) From a0e454d86ce625aa122ca770d72a5a0eaad035ca Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Fri, 4 Jan 2019 09:48:50 -0600 Subject: [PATCH 04/14] Fixes bug with Merkle proof branch selection This code determines the order in which the next branch element and the current value should be hashed to produce the parent node in the Merkle tree. The existing code fails to verify branches constructed in the standard way. This patch fixes the spec code so that it works properly by using an appropriate parity calculation. Example code here to illustrate it working: https://gist.github.com/ralexstokes/9d82e188bd3286ff74a1fa1dcb5068e0 --- 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 f65ddb050..736a587e1 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1518,7 +1518,7 @@ For each `deposit` in `block.body.deposits`: def verify_merkle_branch(leaf: Hash32, branch: [Hash32], depth: int, index: int, root: Hash32) -> bool: value = leaf for i in range(depth): - if index % 2: + if index // (2**i) % 2: value = hash(branch[i] + value) else: value = hash(value + branch[i]) From fb17be0e9ba1aeae203709593a1add0224ef6db1 Mon Sep 17 00:00:00 2001 From: Cayman Date: Fri, 4 Jan 2019 11:14:27 -0600 Subject: [PATCH 05/14] Fix deserialize uint bounds logic Array accesses should be relative to uint byte length, not bit length. --- specs/simple-serialize.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specs/simple-serialize.md b/specs/simple-serialize.md index 63a4d4e31..e3700a2cd 100644 --- a/specs/simple-serialize.md +++ b/specs/simple-serialize.md @@ -248,10 +248,10 @@ size as the integer length. (e.g. ``uint16 == 2 bytes``) All integers are interpreted as **big endian**. ```python -assert(len(rawbytes) >= current_index + int_size) byte_length = int_size / 8 -new_index = current_index + int_size -return int.from_bytes(rawbytes[current_index:current_index+int_size], 'big'), new_index +new_index = current_index + byte_length +assert(len(rawbytes) >= new_index) +return int.from_bytes(rawbytes[current_index:new_index], 'big'), new_index ``` #### Bool From cebbe7b7c5322aae26d4f9eb31cd4951fd645ead Mon Sep 17 00:00:00 2001 From: Cayman Date: Sun, 6 Jan 2019 13:05:27 -0600 Subject: [PATCH 06/14] Fix minor variable name mismatch --- specs/simple-serialize.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/simple-serialize.md b/specs/simple-serialize.md index 63a4d4e31..ceacb6469 100644 --- a/specs/simple-serialize.md +++ b/specs/simple-serialize.md @@ -384,7 +384,7 @@ values = {} for field_name in get_field_names(typ): field_name_type = get_type_for_field_name(typ, field_name) values[field_name], item_index = deserialize(data, item_index, field_name_type) -assert item_index == start + LENGTH_BYTES + length +assert item_index == new_index return typ(**values), item_index ``` From 31d4ca594dce1c7beb3c076b62beb4665f181005 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Mon, 7 Jan 2019 08:13:26 -0700 Subject: [PATCH 07/14] conform to standard --- specs/simple-serialize.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/simple-serialize.md b/specs/simple-serialize.md index e3700a2cd..82ac8f809 100644 --- a/specs/simple-serialize.md +++ b/specs/simple-serialize.md @@ -251,7 +251,7 @@ All integers are interpreted as **big endian**. byte_length = int_size / 8 new_index = current_index + byte_length assert(len(rawbytes) >= new_index) -return int.from_bytes(rawbytes[current_index:new_index], 'big'), new_index +return int.from_bytes(rawbytes[current_index:current_index+byte_length], 'big'), new_index ``` #### Bool From b78458bbb2ae16e3b49fb691f262b0f2160e21fd Mon Sep 17 00:00:00 2001 From: Akhila Raju Date: Mon, 7 Jan 2019 13:06:44 -0500 Subject: [PATCH 08/14] Removes naming conflict in get_shuffling. The variable name 'slot' in the for-loop in 'get_shuffling' conflicts with the get_shuffling argument name 'slot'. Renames 'slot' in for-loop to 'slot_num'. --- 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 a88d8c3c5..3d61898e4 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -885,11 +885,11 @@ def get_shuffling(seed: Hash32, validators_per_slot = split(shuffled_active_validator_indices, EPOCH_LENGTH) output = [] - for slot, slot_indices in enumerate(validators_per_slot): + for slot_num, slot_indices in enumerate(validators_per_slot): # Split the shuffled list into committees_per_slot pieces shard_indices = split(slot_indices, committees_per_slot) - shard_id_start = crosslinking_start_shard + slot * committees_per_slot + shard_id_start = crosslinking_start_shard + slot_num * committees_per_slot shard_committees = [ ShardCommittee( From 4dab5fc72c1fbec4576853172c5955a3c073768b Mon Sep 17 00:00:00 2001 From: terence tsao Date: Mon, 7 Jan 2019 15:55:05 -0800 Subject: [PATCH 09/14] Update 0_beacon-chain.md --- specs/core/0_beacon-chain.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index a88d8c3c5..d4116e93e 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1562,6 +1562,9 @@ For every `shard_committee_at_slot` in `state.shard_committees_at_slots` and for * Let `attesting_validators(shard_committee)` be equal to `attesting_validator_indices(shard_committee, winning_root(shard_committee))` for convenience. * Let `total_attesting_balance(shard_committee) = sum([get_effective_balance(state, i) for i in attesting_validators(shard_committee)])`. * Let `total_balance(shard_committee) = sum([get_effective_balance(state, i) for i in shard_committee.committee])`. + +Define the following helpers to process attestation inclusion rewards and inclusion distance reward/penalty. For every attestation `a` in `previous_epoch_attestations`: + * Let `inclusion_slot(state, index) = a.slot_included` for the attestation `a` where `index` is in `get_attestation_participants(state, a.data, a.participation_bitfield)`. * Let `inclusion_distance(state, index) = a.slot_included - a.data.slot` where `a` is the above attestation. From fff0989b8c22acf7d27de12b6ed2cfd3be542663 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Tue, 8 Jan 2019 09:35:51 -0700 Subject: [PATCH 10/14] fix call to hash (from Hash32) --- 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 b58f819b5..56a02eca4 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -880,7 +880,7 @@ def get_shuffling(seed: Hash32, ) # Shuffle - seed = xor(randao_mix, Hash32(slot)) + seed = xor(randao_mix, hash(slot)) shuffled_active_validator_indices = shuffle(active_validator_indices, seed) # Split the shuffled list into epoch_length pieces From 78ee210d5662e51f0b530e2c9bd2ffb70117f4b9 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Tue, 8 Jan 2019 09:51:12 -0700 Subject: [PATCH 11/14] fix seed xor in get_shuffling using bytes32 --- 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 56a02eca4..d18e8137c 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -880,7 +880,7 @@ def get_shuffling(seed: Hash32, ) # Shuffle - seed = xor(randao_mix, hash(slot)) + seed = xor(randao_mix, bytes32(slot)) shuffled_active_validator_indices = shuffle(active_validator_indices, seed) # Split the shuffled list into epoch_length pieces From 609082c1af546ae5e5b953117122e0345b784dc8 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Tue, 8 Jan 2019 09:57:15 -0700 Subject: [PATCH 12/14] change slot_num to slot_position --- 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 3d61898e4..17e683e2a 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -885,11 +885,11 @@ def get_shuffling(seed: Hash32, validators_per_slot = split(shuffled_active_validator_indices, EPOCH_LENGTH) output = [] - for slot_num, slot_indices in enumerate(validators_per_slot): + for slot_position, slot_indices in enumerate(validators_per_slot): # Split the shuffled list into committees_per_slot pieces shard_indices = split(slot_indices, committees_per_slot) - shard_id_start = crosslinking_start_shard + slot_num * committees_per_slot + shard_id_start = crosslinking_start_shard + slot_position * committees_per_slot shard_committees = [ ShardCommittee( From 61f7e37eff777179c51551627a783a374ace21ea Mon Sep 17 00:00:00 2001 From: Ben Edgington Date: Tue, 8 Jan 2019 19:41:40 +0000 Subject: [PATCH 13/14] Replace numeric constant with symbolic in Vyper contract Vyper v0.1.0-beta.6 supports ranges with symbolic constants. --- 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 23b35fc6f..2f5b1b3f9 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -675,7 +675,7 @@ def deposit(deposit_input: bytes[2048]): # add deposit to merkle tree self.deposit_tree[index] = sha3(deposit_data) - for i in range(32): # DEPOSIT_CONTRACT_TREE_DEPTH (range of constant var not yet supported) + for i in range(DEPOSIT_CONTRACT_TREE_DEPTH): index /= 2 self.deposit_tree[index] = sha3(concat(self.deposit_tree[index * 2], self.deposit_tree[index * 2 + 1])) From c589f8273b56e6d7dda5aa57800cd91dc2c11f1b Mon Sep 17 00:00:00 2001 From: terence tsao Date: Thu, 10 Jan 2019 08:19:56 -0800 Subject: [PATCH 14/14] Update 0_beacon-chain.md --- specs/core/0_beacon-chain.md | 1 - 1 file changed, 1 deletion(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 2f5b1b3f9..9a3a73ff8 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1742,7 +1742,6 @@ def process_penalties_and_exits(state: BeaconState) -> None: sorted_indices = sorted(eligible_indices, key=lambda index: state.validator_registry[index].exit_count) withdrawn_so_far = 0 for index in sorted_indices: - validator = state.validator_registry[index] prepare_validator_for_withdrawal(state, index) withdrawn_so_far += 1 if withdrawn_so_far >= MAX_WITHDRAWALS_PER_EPOCH: