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.
This commit is contained in:
vbuterin 2018-10-11 13:57:30 -04:00 committed by GitHub
parent fe74c7e299
commit c827a26ecf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -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 | | `WITHDRAWAL_PERIOD` | 2**19 (= 524,288) | slots | ~97 days |
| `BASE_REWARD_QUOTIENT` | 2**15 (= 32,768) | — | | `BASE_REWARD_QUOTIENT` | 2**15 (= 32,768) | — |
| `MAX_VALIDATOR_CHURN_QUOTIENT` | 2**5 (= 32) | — | | `MAX_VALIDATOR_CHURN_QUOTIENT` | 2**5 (= 32) | — |
| `RANDAO_SLOTS_PER_LAYER` | 2**12 (=4096) | slots | ~18 hours |
| `LOGOUT_MESSAGE` | `"LOGOUT"` | — | | `LOGOUT_MESSAGE` | `"LOGOUT"` | — |
**Notes** **Notes**
@ -224,6 +225,8 @@ A `ValidatorRecord` has the following fields:
'withdrawal_address': 'address', 'withdrawal_address': 'address',
# RANDAO commitment # RANDAO commitment
'randao_commitment': 'hash32', 'randao_commitment': 'hash32',
# Slot the RANDAO was last changed
'randao_last_change': 'int64',
# Balance # Balance
'balance': 'int64', 'balance': 'int64',
# Status code # Status code
@ -479,7 +482,8 @@ def on_startup(initial_validator_entries: List[Any]) -> Tuple[CrystallizedState,
proof_of_possession=proof_of_possession, proof_of_possession=proof_of_possession,
withdrawal_shard=withdrawal_shard, withdrawal_shard=withdrawal_shard,
withdrawal_address=withdrawal_address, withdrawal_address=withdrawal_address,
randao_commitment=randao_commitment randao_commitment=randao_commitment,
current_slot=0
) )
# Setup crystallized state # Setup crystallized state
x = get_new_shuffling(bytes([0] * 32), validators, 0) x = get_new_shuffling(bytes([0] * 32), validators, 0)
@ -536,7 +540,8 @@ def add_validator(validators: List[ValidatorRecord],
proof_of_possession: bytes, proof_of_possession: bytes,
withdrawal_shard: int, withdrawal_shard: int,
withdrawal_address: Address, withdrawal_address: Address,
randao_commitment: Hash32) -> int: randao_commitment: Hash32,
current_slot: int) -> int:
# if following assert fails, validator induction failed # if following assert fails, validator induction failed
# move on to next validator registration log # move on to next validator registration log
assert BLSVerify(pub=pubkey, assert BLSVerify(pub=pubkey,
@ -547,6 +552,7 @@ def add_validator(validators: List[ValidatorRecord],
withdrawal_shard=withdrawal_shard, withdrawal_shard=withdrawal_shard,
withdrawal_address=withdrawal_address, withdrawal_address=withdrawal_address,
randao_commitment=randao_commitment, randao_commitment=randao_commitment,
randao_last_change=current_slot,
balance=DEPOSIT_SIZE * GWEI_PER_ETH, # in Gwei balance=DEPOSIT_SIZE * GWEI_PER_ETH, # in Gwei
status=PENDING_ACTIVATION, status=PENDING_ACTIVATION,
exit_slot=0 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. 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) ### State recalculations (every `CYCLE_LENGTH` slots)