From 80940ddd37d850169bd68399c5d41ef91e35bb88 Mon Sep 17 00:00:00 2001 From: Justin Date: Mon, 21 Jan 2019 18:41:29 +0000 Subject: [PATCH 1/9] BLS-based RANDAO and custody (friendly to decentralised pools) Unlock decentralised pools using m-of-n threshold BLS signatures for both RANDAO and custody. We also simplify a bunch: * Remove `randao_commitment` and `custody_commitment` * Remove miscellaneous logic such as `repeat_hash` (Side note: Dfinity seems to be working to reduce the communication complexity of BLS DKG (Distributed Key Generation) so validator pools should also benefit from that.) --- specs/core/0_beacon-chain.md | 42 ++++++++---------------------------- 1 file changed, 9 insertions(+), 33 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 49db5fdb0..69575e100 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -250,6 +250,7 @@ Code snippets appearing in `this style` are to be interpreted as Python code. Be | `DOMAIN_ATTESTATION` | `1` | | `DOMAIN_PROPOSAL` | `2` | | `DOMAIN_EXIT` | `3` | +| `DOMAIN_RANDAO` | `4` | ## Data structures @@ -389,10 +390,6 @@ Code snippets appearing in `this style` are to be interpreted as Python code. Be 'pubkey': 'bytes48', # Withdrawal credentials 'withdrawal_credentials': 'bytes32', - # Initial RANDAO commitment - 'randao_commitment': 'bytes32', - # Initial custody commitment - 'custody_commitment': 'bytes32', # A BLS signature of this `DepositInput` 'proof_of_possession': 'bytes96', } @@ -423,7 +420,7 @@ Code snippets appearing in `this style` are to be interpreted as Python code. Be 'slot': 'uint64', 'parent_root': 'bytes32', 'state_root': 'bytes32', - 'randao_reveal': 'bytes32', + 'randao_reveal': 'bytes96', 'eth1_data': Eth1Data, 'signature': 'bytes96', @@ -520,8 +517,6 @@ Code snippets appearing in `this style` are to be interpreted as Python code. Be 'pubkey': 'bytes48', # Withdrawal credentials 'withdrawal_credentials': 'bytes32', - # RANDAO commitment - 'randao_commitment': 'bytes32', # Slots the proposer has skipped (i.e. layers of RANDAO expected) 'randao_layers': 'uint64', # Slot when validator activated @@ -536,8 +531,6 @@ Code snippets appearing in `this style` are to be interpreted as Python code. Be 'exit_count': 'uint64', # Status flags 'status_flags': 'uint64', - # Custody commitment - 'custody_commitment': 'bytes32', # Slot of latest custody reseed 'latest_custody_reseed_slot': 'uint64', # Slot of second-latest custody reseed @@ -946,7 +939,7 @@ def get_crosslink_committees_at_slot(state: BeaconState, """ Returns the list of ``(committee, shard)`` tuples for the ``slot``. """ - state_epoch_slot = state.slot - (state.slot % EPOCH_LENGTH) + state_epoch_slot = state.slot - (state.slot % EPOCH_LENGTH) assert state_epoch_slot <= slot + EPOCH_LENGTH assert slot < state_epoch_slot + EPOCH_LENGTH offset = slot % EPOCH_LENGTH @@ -1195,7 +1188,7 @@ A valid block with slot `GENESIS_SLOT` (a "genesis block") has the following val slot=GENESIS_SLOT, parent_root=ZERO_HASH, state_root=STARTUP_STATE_ROOT, - randao_reveal=ZERO_HASH, + randao_reveal=EMPTY_SIGNATURE, eth1_data=Eth1Data( deposit_root=ZERO_HASH, block_hash=ZERO_HASH @@ -1276,8 +1269,6 @@ def get_initial_beacon_state(initial_validator_deposits: List[Deposit], amount=deposit.deposit_data.amount, proof_of_possession=deposit.deposit_data.deposit_input.proof_of_possession, withdrawal_credentials=deposit.deposit_data.deposit_input.withdrawal_credentials, - randao_commitment=deposit.deposit_data.deposit_input.randao_commitment, - custody_commitment=deposit.deposit_data.deposit_input.custody_commitment, ) # Process initial activations @@ -1296,14 +1287,10 @@ First, a helper function: def validate_proof_of_possession(state: BeaconState, pubkey: Bytes48, proof_of_possession: Bytes96, - withdrawal_credentials: Bytes32, - randao_commitment: Bytes32, - custody_commitment: Bytes32) -> bool: + withdrawal_credentials: Bytes32) -> bool: proof_of_possession_data = DepositInput( pubkey=pubkey, withdrawal_credentials=withdrawal_credentials, - randao_commitment=randao_commitment, - custody_commitment=custody_commitment, proof_of_possession=EMPTY_SIGNATURE, ) @@ -1326,9 +1313,7 @@ def process_deposit(state: BeaconState, pubkey: Bytes48, amount: int, proof_of_possession: Bytes96, - withdrawal_credentials: Bytes32, - randao_commitment: Bytes32, - custody_commitment: Bytes32) -> None: + withdrawal_credentials: Bytes32) -> None: """ Process a deposit from Ethereum 1.0. Note that this function mutates ``state``. @@ -1339,8 +1324,6 @@ def process_deposit(state: BeaconState, pubkey, proof_of_possession, withdrawal_credentials, - randao_commitment, - custody_commitment, ) validator_pubkeys = [v.pubkey for v in state.validator_registry] @@ -1350,7 +1333,6 @@ def process_deposit(state: BeaconState, validator = Validator( pubkey=pubkey, withdrawal_credentials=withdrawal_credentials, - randao_commitment=randao_commitment, randao_layers=0, activation_slot=FAR_FUTURE_SLOT, exit_slot=FAR_FUTURE_SLOT, @@ -1358,7 +1340,6 @@ def process_deposit(state: BeaconState, penalized_slot=FAR_FUTURE_SLOT, exit_count=0, status_flags=0, - custody_commitment=custody_commitment, latest_custody_reseed_slot=GENESIS_SLOT, penultimate_custody_reseed_slot=GENESIS_SLOT, ) @@ -1474,12 +1455,9 @@ Below are the processing steps that happen at every `block`. ### RANDAO -* 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`. +* Verify that `bls_verify(pubkey=proposer.pubkey, message=proposer.randao_layers, signature=block.randao_reveal, domain=get_domain(state.fork, state.slot, DOMAIN_RANDAO))`. * 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`. ### Eth1 data @@ -1570,8 +1548,6 @@ process_deposit( amount=deposit.deposit_data.amount, proof_of_possession=deposit.deposit_data.deposit_input.proof_of_possession, withdrawal_credentials=deposit.deposit_data.deposit_input.withdrawal_credentials, - randao_commitment=deposit.deposit_data.deposit_input.randao_commitment, - custody_commitment=deposit.deposit_data.deposit_input.custody_commitment, ) ``` @@ -1856,10 +1832,10 @@ This section is divided into Normative and Informative references. Normative re ## Normative ## Informative - _**casper-ffg**_ + _**casper-ffg**_   _Casper the Friendly Finality Gadget_. V. Buterin and V. Griffith. URL: https://arxiv.org/abs/1710.09437 - _**python-poc**_ + _**python-poc**_   _Python proof-of-concept implementation_. Ethereum Foundation. URL: https://github.com/ethereum/beacon_chain # Copyright From 941dfed863d2339079116e1d52492b4a50fabd55 Mon Sep 17 00:00:00 2001 From: Justin Date: Mon, 21 Jan 2019 19:45:11 +0000 Subject: [PATCH 2/9] Update 0_beacon-chain.md --- specs/core/0_beacon-chain.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 69575e100..ed5cb713d 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1456,7 +1456,7 @@ Below are the processing steps that happen at every `block`. ### RANDAO * Let `proposer = state.validator_registry[get_beacon_proposer_index(state, state.slot)]`. -* Verify that `bls_verify(pubkey=proposer.pubkey, message=proposer.randao_layers, signature=block.randao_reveal, domain=get_domain(state.fork, state.slot, DOMAIN_RANDAO))`. +* Verify that `bls_verify(pubkey=proposer.pubkey, message=int_to_bytes32(proposer.randao_layers), signature=block.randao_reveal, domain=get_domain(state.fork, state.slot, DOMAIN_RANDAO))`. * 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))` ### Eth1 data @@ -1832,11 +1832,9 @@ This section is divided into Normative and Informative references. Normative re ## Normative ## Informative - _**casper-ffg**_ -   _Casper the Friendly Finality Gadget_. V. Buterin and V. Griffith. URL: https://arxiv.org/abs/1710.09437 + _**casper-ffg**_   _Casper the Friendly Finality Gadget_. V. Buterin and V. Griffith. URL: https://arxiv.org/abs/1710.09437 - _**python-poc**_ -   _Python proof-of-concept implementation_. Ethereum Foundation. URL: https://github.com/ethereum/beacon_chain + _**python-poc**_   _Python proof-of-concept implementation_. Ethereum Foundation. URL: https://github.com/ethereum/beacon_chain # Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). From a1b550a34f097f8471b671d63c8c20f097cb3265 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Mon, 21 Jan 2019 13:55:49 -0600 Subject: [PATCH 3/9] fix formatting of references --- 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 ed5cb713d..0aea057d0 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1832,9 +1832,9 @@ This section is divided into Normative and Informative references. Normative re ## Normative ## Informative - _**casper-ffg**_   _Casper the Friendly Finality Gadget_. V. Buterin and V. Griffith. URL: https://arxiv.org/abs/1710.09437 + _**casper-ffg**_
  _Casper the Friendly Finality Gadget_. V. Buterin and V. Griffith. URL: https://arxiv.org/abs/1710.09437 - _**python-poc**_   _Python proof-of-concept implementation_. Ethereum Foundation. URL: https://github.com/ethereum/beacon_chain + _**python-poc**_
  _Python proof-of-concept implementation_. Ethereum Foundation. URL: https://github.com/ethereum/beacon_chain # Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). From fb92d68bb98f75bed8403ca2c53f194daf0c47b1 Mon Sep 17 00:00:00 2001 From: Justin Date: Tue, 22 Jan 2019 09:27:47 +0000 Subject: [PATCH 4/9] Update 0_beacon-chain.md --- 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 0aea057d0..94b8e1f0f 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1457,7 +1457,7 @@ Below are the processing steps that happen at every `block`. * Let `proposer = state.validator_registry[get_beacon_proposer_index(state, state.slot)]`. * Verify that `bls_verify(pubkey=proposer.pubkey, message=int_to_bytes32(proposer.randao_layers), signature=block.randao_reveal, domain=get_domain(state.fork, state.slot, DOMAIN_RANDAO))`. -* 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 `state.latest_randao_mixes[state.slot % LATEST_RANDAO_MIXES_LENGTH] = hash(state.latest_randao_mixes[state.slot % LATEST_RANDAO_MIXES_LENGTH] + block.randao_reveal)`. ### Eth1 data From e52d3745219d287cff60754c9914f25b98999e4c Mon Sep 17 00:00:00 2001 From: Justin Date: Tue, 22 Jan 2019 10:30:31 +0000 Subject: [PATCH 5/9] Update 0_beacon-chain.md --- specs/core/0_beacon-chain.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 94b8e1f0f..56430cd56 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -517,8 +517,8 @@ Code snippets appearing in `this style` are to be interpreted as Python code. Be 'pubkey': 'bytes48', # Withdrawal credentials 'withdrawal_credentials': 'bytes32', - # Slots the proposer has skipped (i.e. layers of RANDAO expected) - 'randao_layers': 'uint64', + # Number of proposer slots since genesis + 'proposer_slots': 'uint64', # Slot when validator activated 'activation_slot': 'uint64', # Slot when validator exited @@ -1333,7 +1333,7 @@ def process_deposit(state: BeaconState, validator = Validator( pubkey=pubkey, withdrawal_credentials=withdrawal_credentials, - randao_layers=0, + proposer_slots=0, activation_slot=FAR_FUTURE_SLOT, exit_slot=FAR_FUTURE_SLOT, withdrawal_slot=FAR_FUTURE_SLOT, @@ -1430,7 +1430,7 @@ Below are the processing steps that happen at every slot. ### Misc counters * Set `state.slot += 1`. -* Set `state.validator_registry[get_beacon_proposer_index(state, state.slot)].randao_layers += 1`. +* Set `state.validator_registry[get_beacon_proposer_index(state, state.slot)].proposer_slots += 1`. * Set `state.latest_randao_mixes[state.slot % LATEST_RANDAO_MIXES_LENGTH] = state.latest_randao_mixes[(state.slot - 1) % LATEST_RANDAO_MIXES_LENGTH]` ### Block roots @@ -1456,7 +1456,7 @@ Below are the processing steps that happen at every `block`. ### RANDAO * Let `proposer = state.validator_registry[get_beacon_proposer_index(state, state.slot)]`. -* Verify that `bls_verify(pubkey=proposer.pubkey, message=int_to_bytes32(proposer.randao_layers), signature=block.randao_reveal, domain=get_domain(state.fork, state.slot, DOMAIN_RANDAO))`. +* Verify that `bls_verify(pubkey=proposer.pubkey, message=int_to_bytes32(proposer.proposer_slots), signature=block.randao_reveal, domain=get_domain(state.fork, state.slot, DOMAIN_RANDAO))`. * Set `state.latest_randao_mixes[state.slot % LATEST_RANDAO_MIXES_LENGTH] = hash(state.latest_randao_mixes[state.slot % LATEST_RANDAO_MIXES_LENGTH] + block.randao_reveal)`. ### Eth1 data From 1bc6c19dca555271537ace0534521b0f62936e9e Mon Sep 17 00:00:00 2001 From: terence tsao Date: Tue, 22 Jan 2019 10:56:01 -0800 Subject: [PATCH 6/9] Update 0_beacon-chain.md --- 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 56430cd56..24486ddd3 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1715,6 +1715,7 @@ First, update `previous_epoch_calculation_slot` and `previous_epoch_start_shard` * Set `state.previous_epoch_calculation_slot = state.current_epoch_calculation_slot` * Set `state.previous_epoch_start_shard = state.current_epoch_start_shard` +* Set `state.previous_epoch_randao_mix = state.current_epoch_randao_mix` If the following are satisfied: @@ -1769,7 +1770,6 @@ def update_validator_registry(state: BeaconState) -> None: and perform the following updates: -* Set `state.previous_epoch_randao_mix = state.current_epoch_randao_mix` * Set `state.current_epoch_calculation_slot = state.slot` * Set `state.current_epoch_start_shard = (state.current_epoch_start_shard + get_current_epoch_committee_count_per_slot(state) * EPOCH_LENGTH) % SHARD_COUNT` * Set `state.current_epoch_randao_mix = get_randao_mix(state, state.current_epoch_calculation_slot - SEED_LOOKAHEAD)` From 947e1b9520bd3075272b3fd8d3238c6552689c36 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Tue, 22 Jan 2019 11:31:13 -0800 Subject: [PATCH 7/9] Update 0_beacon-chain.md --- 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 56430cd56..d8fb36f4d 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1777,7 +1777,7 @@ and perform the following updates: If a validator registry update does _not_ happen do the following: * Let `epochs_since_last_registry_change = (state.slot - state.validator_registry_update_slot) // EPOCH_LENGTH`. -* If `epochs_since_last_registry_change` is an exact power of 2, set `state.current_epoch_calculation_slot = state.slot` and `state.current_epoch_randao_mix = state.latest_randao_mixes[(state.current_epoch_calculation_slot - SEED_LOOKAHEAD) % LATEST_RANDAO_MIXES_LENGTH]`. Note that `state.current_epoch_start_shard` is left unchanged. +* If `epochs_since_last_registry_change` is an exact power of 2, set `state.current_epoch_calculation_slot = state.slot` and `state.current_epoch_randao_mix = get_randao_mix(state, state.current_epoch_calculation_slot - SEED_LOOKAHEAD)`. Note that `state.current_epoch_start_shard` is left unchanged. Regardless of whether or not a validator set change happens, run the following: From 071537469e1da16f6af0214eebbd910d457a13bd Mon Sep 17 00:00:00 2001 From: Dean Eigenmann Date: Tue, 22 Jan 2019 23:09:28 +0100 Subject: [PATCH 8/9] Update 0_beacon-chain.md --- 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 d8fb36f4d..296426175 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1040,7 +1040,7 @@ def get_attestation_participants(state: BeaconState, assert attestation_data.shard in [shard for _, shard in crosslink_committees] crosslink_committee = [committee for committee, shard in crosslink_committees if shard == attestation_data.shard][0] - assert len(aggregation_bitfield) == (len(committee) + 7) // 8 + assert len(aggregation_bitfield) == (len(crosslink_committee[0]) + 7) // 8 # Find the participating attesters in the committee participants = [] From 34a4396fa703dc12ad0f708f374f05cb46e962f2 Mon Sep 17 00:00:00 2001 From: Dean Eigenmann Date: Tue, 22 Jan 2019 23:10:12 +0100 Subject: [PATCH 9/9] Update 0_beacon-chain.md --- 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 296426175..0facc0a85 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1040,7 +1040,7 @@ def get_attestation_participants(state: BeaconState, assert attestation_data.shard in [shard for _, shard in crosslink_committees] crosslink_committee = [committee for committee, shard in crosslink_committees if shard == attestation_data.shard][0] - assert len(aggregation_bitfield) == (len(crosslink_committee[0]) + 7) // 8 + assert len(aggregation_bitfield) == (len(crosslink_committee) + 7) // 8 # Find the participating attesters in the committee participants = []