From c827a26ecf4a7fb5fa7c347990f0358a22750549 Mon Sep 17 00:00:00 2001 From: vbuterin Date: Thu, 11 Oct 2018 13:57:30 -0400 Subject: [PATCH 1/5] Add RANDAO multi-hashing Requires more hashes in a RANDAO reveal the more time passes. This greatly reduces the chance that a RANDAO reveal accidentally revealed during an orphaned block will be usable for future blocks. --- specs/beacon-chain.md | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/specs/beacon-chain.md b/specs/beacon-chain.md index d5ca0c648..1dba44dcf 100644 --- a/specs/beacon-chain.md +++ b/specs/beacon-chain.md @@ -42,6 +42,7 @@ The primary source of load on the beacon chain are "attestations". Attestations | `WITHDRAWAL_PERIOD` | 2**19 (= 524,288) | slots | ~97 days | | `BASE_REWARD_QUOTIENT` | 2**15 (= 32,768) | — | | `MAX_VALIDATOR_CHURN_QUOTIENT` | 2**5 (= 32) | — | +| `RANDAO_SLOTS_PER_LAYER` | 2**12 (=4096) | slots | ~18 hours | | `LOGOUT_MESSAGE` | `"LOGOUT"` | — | **Notes** @@ -224,6 +225,8 @@ A `ValidatorRecord` has the following fields: 'withdrawal_address': 'address', # RANDAO commitment 'randao_commitment': 'hash32', + # Slot the RANDAO was last changed + 'randao_last_change': 'int64', # Balance 'balance': 'int64', # Status code @@ -479,7 +482,8 @@ def on_startup(initial_validator_entries: List[Any]) -> Tuple[CrystallizedState, proof_of_possession=proof_of_possession, withdrawal_shard=withdrawal_shard, withdrawal_address=withdrawal_address, - randao_commitment=randao_commitment + randao_commitment=randao_commitment, + current_slot=0 ) # Setup crystallized state x = get_new_shuffling(bytes([0] * 32), validators, 0) @@ -536,7 +540,8 @@ def add_validator(validators: List[ValidatorRecord], proof_of_possession: bytes, withdrawal_shard: int, withdrawal_address: Address, - randao_commitment: Hash32) -> int: + randao_commitment: Hash32, + current_slot: int) -> int: # if following assert fails, validator induction failed # move on to next validator registration log assert BLSVerify(pub=pubkey, @@ -547,6 +552,7 @@ def add_validator(validators: List[ValidatorRecord], withdrawal_shard=withdrawal_shard, withdrawal_address=withdrawal_address, randao_commitment=randao_commitment, + randao_last_change=current_slot, balance=DEPOSIT_SIZE * GWEI_PER_ETH, # in Gwei status=PENDING_ACTIVATION, exit_slot=0 @@ -605,7 +611,11 @@ Extend the list of `AttestationRecord` objects in the `active_state` with those Let `proposer_index` be the validator index of the `parent.slot % len(get_shards_and_committees_for_slot(crystallized_state, parent.slot)[0].committee)`'th attester in `get_shards_and_committees_for_slot(crystallized_state, parent.slot)[0]`. Verify that an attestation from this validator is part of the first (ie. item 0 in the array) `AttestationRecord` object; this attester can be considered to be the proposer of the parent block. In general, when a block is produced, it is broadcasted at the network layer along with the attestation from its proposer. -Additionally, verify that `hash(block.randao_reveal) == crystallized_state.validators[proposer_index].randao_commitment`, and set `active_state.randao_mix = xor(active_state.randao_mix, block.randao_reveal)` and append to `ActiveState.pending_specials` a `SpecialObject(kind=RANDAO_CHANGE, data=[bytes8(proposer_index), block.randao_reveal])`. +Additionally, we need to verify and update the RANDAO reveal. This is done as follows: + +* Let `repeat_hash(x, n) = x if n == 0 else repeat_hash(hash(x), n-1)`. +* Let `V = crystallized_state.validators[proposer_index]`. +* Verify that `repeat_hash(block.randao_reveal, (current_slot - V.randao_last_reveal) // RANDAO_SLOTS_PER_LAYER + 1) == V.randao_commitment`, and set `active_state.randao_mix = xor(active_state.randao_mix, block.randao_reveal)` and append to `ActiveState.pending_specials` a `SpecialObject(kind=RANDAO_CHANGE, data=[bytes8(proposer_index), block.randao_reveal])`. ### State recalculations (every `CYCLE_LENGTH` slots) From 48d5c1d12c52db1dd992fc7d0183a1726a436d20 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Sun, 14 Oct 2018 08:55:01 -0500 Subject: [PATCH 2/5] minor change to comment --- specs/beacon-chain.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/beacon-chain.md b/specs/beacon-chain.md index 1dba44dcf..893be6131 100644 --- a/specs/beacon-chain.md +++ b/specs/beacon-chain.md @@ -225,7 +225,7 @@ A `ValidatorRecord` has the following fields: 'withdrawal_address': 'address', # RANDAO commitment 'randao_commitment': 'hash32', - # Slot the RANDAO was last changed + # Slot the RANDAO commitment was last changed 'randao_last_change': 'int64', # Balance 'balance': 'int64', From 17ba99ed8f0e5267aef1ab90842d902eab744c5e Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Sun, 14 Oct 2018 09:20:51 -0500 Subject: [PATCH 3/5] minor change in language --- specs/beacon-chain.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/beacon-chain.md b/specs/beacon-chain.md index 893be6131..290ead31f 100644 --- a/specs/beacon-chain.md +++ b/specs/beacon-chain.md @@ -611,7 +611,7 @@ Extend the list of `AttestationRecord` objects in the `active_state` with those Let `proposer_index` be the validator index of the `parent.slot % len(get_shards_and_committees_for_slot(crystallized_state, parent.slot)[0].committee)`'th attester in `get_shards_and_committees_for_slot(crystallized_state, parent.slot)[0]`. Verify that an attestation from this validator is part of the first (ie. item 0 in the array) `AttestationRecord` object; this attester can be considered to be the proposer of the parent block. In general, when a block is produced, it is broadcasted at the network layer along with the attestation from its proposer. -Additionally, we need to verify and update the RANDAO reveal. This is done as follows: +Additionally, verify and update the RANDAO reveal. This is done as follows: * Let `repeat_hash(x, n) = x if n == 0 else repeat_hash(hash(x), n-1)`. * Let `V = crystallized_state.validators[proposer_index]`. From 2f2fbcabeef53c15ddc1ca754c870535074541be Mon Sep 17 00:00:00 2001 From: vbuterin Date: Sun, 14 Oct 2018 21:08:35 -0400 Subject: [PATCH 4/5] Update beacon-chain.md --- specs/beacon-chain.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specs/beacon-chain.md b/specs/beacon-chain.md index 290ead31f..a471b5e2e 100644 --- a/specs/beacon-chain.md +++ b/specs/beacon-chain.md @@ -609,13 +609,13 @@ For each one of these attestations: Extend the list of `AttestationRecord` objects in the `active_state` with those included in the block, ordering the new additions in the same order as they came in the block. Similarly extend the list of `SpecialRecord` objects in the `active_state` with those included in the block. -Let `proposer_index` be the validator index of the `parent.slot % len(get_shards_and_committees_for_slot(crystallized_state, parent.slot)[0].committee)`'th attester in `get_shards_and_committees_for_slot(crystallized_state, parent.slot)[0]`. Verify that an attestation from this validator is part of the first (ie. item 0 in the array) `AttestationRecord` object; this attester can be considered to be the proposer of the parent block. In general, when a block is produced, it is broadcasted at the network layer along with the attestation from its proposer. +Let `curblock_proposer_index` be the validator index of the `block.slot % len(get_shards_and_committees_for_slot(crystallized_state, block.slot)[0].committee)`'th attester in `get_shards_and_committees_for_slot(crystallized_state, block.slot)[0]`, and `parent_proposer_index` be the validator index of the parent block, calculated similarly. Verify that an attestation from the `parent_proposer_index`'th validator is part of the first (ie. item 0 in the array) `AttestationRecord` object; this attester can be considered to be the proposer of the parent block. In general, when a block is produced, it is broadcasted at the network layer along with the attestation from its proposer. Additionally, verify and update the RANDAO reveal. This is done as follows: * Let `repeat_hash(x, n) = x if n == 0 else repeat_hash(hash(x), n-1)`. -* Let `V = crystallized_state.validators[proposer_index]`. -* Verify that `repeat_hash(block.randao_reveal, (current_slot - V.randao_last_reveal) // RANDAO_SLOTS_PER_LAYER + 1) == V.randao_commitment`, and set `active_state.randao_mix = xor(active_state.randao_mix, block.randao_reveal)` and append to `ActiveState.pending_specials` a `SpecialObject(kind=RANDAO_CHANGE, data=[bytes8(proposer_index), block.randao_reveal])`. +* Let `V = crystallized_state.validators[curblock_proposer_index]`. +* Verify that `repeat_hash(block.randao_reveal, (current_slot - V.randao_last_reveal) // RANDAO_SLOTS_PER_LAYER + 1) == V.randao_commitment`, and set `active_state.randao_mix = xor(active_state.randao_mix, block.randao_reveal)` and append to `ActiveState.pending_specials` a `SpecialObject(kind=RANDAO_CHANGE, data=[bytes8(curblock_proposer_index), block.randao_reveal])`. ### State recalculations (every `CYCLE_LENGTH` slots) From 6aeb3821323829bac44815945dc83c89e1a3e6f7 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Mon, 15 Oct 2018 13:14:45 -0500 Subject: [PATCH 5/5] change current_block to block.slot --- specs/beacon-chain.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/beacon-chain.md b/specs/beacon-chain.md index a471b5e2e..6b27855ef 100644 --- a/specs/beacon-chain.md +++ b/specs/beacon-chain.md @@ -615,7 +615,7 @@ Additionally, verify and update the RANDAO reveal. This is done as follows: * Let `repeat_hash(x, n) = x if n == 0 else repeat_hash(hash(x), n-1)`. * Let `V = crystallized_state.validators[curblock_proposer_index]`. -* Verify that `repeat_hash(block.randao_reveal, (current_slot - V.randao_last_reveal) // RANDAO_SLOTS_PER_LAYER + 1) == V.randao_commitment`, and set `active_state.randao_mix = xor(active_state.randao_mix, block.randao_reveal)` and append to `ActiveState.pending_specials` a `SpecialObject(kind=RANDAO_CHANGE, data=[bytes8(curblock_proposer_index), block.randao_reveal])`. +* Verify that `repeat_hash(block.randao_reveal, (block.slot - V.randao_last_reveal) // RANDAO_SLOTS_PER_LAYER + 1) == V.randao_commitment`, and set `active_state.randao_mix = xor(active_state.randao_mix, block.randao_reveal)` and append to `ActiveState.pending_specials` a `SpecialObject(kind=RANDAO_CHANGE, data=[bytes8(curblock_proposer_index), block.randao_reveal])`. ### State recalculations (every `CYCLE_LENGTH` slots)