From dac43eb564a3da19bf878364295486d0b7c03fb2 Mon Sep 17 00:00:00 2001 From: Justin Date: Fri, 15 Mar 2019 11:18:06 +0000 Subject: [PATCH 1/3] Simplify deposits Fix #760 --- specs/core/0_beacon-chain.md | 49 +++++++++++------------------------- 1 file changed, 14 insertions(+), 35 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index daa1bc108..2d168cfc2 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -29,7 +29,6 @@ - [`AttestationData`](#attestationdata) - [`AttestationDataAndCustodyBit`](#attestationdataandcustodybit) - [`SlashableAttestation`](#slashableattestation) - - [`DepositInput`](#depositinput) - [`DepositData`](#depositdata) - [`BeaconBlockHeader`](#beaconblockheader) - [`Validator`](#validator) @@ -377,7 +376,7 @@ The types are defined topologically to aid in facilitating an executable version } ``` -#### `DepositInput` +#### `DepositData` ```python { @@ -385,21 +384,10 @@ The types are defined topologically to aid in facilitating an executable version 'pubkey': 'bytes48', # Withdrawal credentials 'withdrawal_credentials': 'bytes32', - # A BLS signature of this `DepositInput` - 'proof_of_possession': 'bytes96', -} -``` - -#### `DepositData` - -```python -{ # Amount in Gwei 'amount': 'uint64', - # Timestamp from deposit contract - 'timestamp': 'uint64', - # Deposit input - 'deposit_input': DepositInput, + # Container self-signature + 'proof_of_possession': 'bytes96', } ``` @@ -512,7 +500,7 @@ The types are defined topologically to aid in facilitating an executable version # Index in the deposit tree 'index': 'uint64', # Data - 'deposit_data': DepositData, + 'data': DepositData, } ``` @@ -1278,19 +1266,12 @@ def process_deposit(state: BeaconState, deposit: Deposit) -> None: Process a deposit from Ethereum 1.0. Note that this function mutates ``state``. """ - deposit_input = deposit.deposit_data.deposit_input - - # Should equal 8 bytes for deposit_data.amount + - # 8 bytes for deposit_data.timestamp + - # 176 bytes for deposit_data.deposit_input - # It should match the deposit_data in the eth1.0 deposit contract - serialized_deposit_data = serialize(deposit.deposit_data) # Deposits must be processed in order assert deposit.index == state.deposit_index # Verify the Merkle branch merkle_branch_is_valid = verify_merkle_branch( - leaf=hash(serialized_deposit_data), + leaf=hash(serialize(deposit.data)), # 48 + 32 + 8 + 96 = 184 bytes serialisation proof=deposit.proof, depth=DEPOSIT_CONTRACT_TREE_DEPTH, index=deposit.index, @@ -1305,16 +1286,14 @@ def process_deposit(state: BeaconState, deposit: Deposit) -> None: state.deposit_index += 1 validator_pubkeys = [v.pubkey for v in state.validator_registry] - pubkey = deposit_input.pubkey - amount = deposit.deposit_data.amount - withdrawal_credentials = deposit_input.withdrawal_credentials + pubkey = deposit.data.pubkey if pubkey not in validator_pubkeys: # Verify the proof of possession proof_is_valid = bls_verify( - pubkey=deposit_input.pubkey, - message_hash=signed_root(deposit_input), - signature=deposit_input.proof_of_possession, + pubkey=pubkey, + message_hash=signed_root(deposit.data), + signature=deposit.data.proof_of_possession, domain=get_domain( state.fork, get_current_epoch(state), @@ -1327,7 +1306,7 @@ def process_deposit(state: BeaconState, deposit: Deposit) -> None: # Add new validator validator = Validator( pubkey=pubkey, - withdrawal_credentials=withdrawal_credentials, + withdrawal_credentials=deposit.data.withdrawal_credentials, activation_epoch=FAR_FUTURE_EPOCH, exit_epoch=FAR_FUTURE_EPOCH, withdrawable_epoch=FAR_FUTURE_EPOCH, @@ -1337,10 +1316,10 @@ def process_deposit(state: BeaconState, deposit: Deposit) -> None: # Note: In phase 2 registry indices that have been withdrawn for a long time will be recycled. state.validator_registry.append(validator) - state.validator_balances.append(amount) + state.validator_balances.append(deposit.data.amount) else: # Increase balance by deposit amount - state.validator_balances[validator_pubkeys.index(pubkey)] += amount + state.validator_balances[validator_pubkeys.index(pubkey)] += deposit.data.amount ``` ### Routines for updating validator status @@ -1430,11 +1409,11 @@ The initial deployment phases of Ethereum 2.0 are implemented without consensus ### Deposit arguments -The deposit contract has a single `deposit` function which takes as argument a SimpleSerialize'd `DepositInput`. +The deposit contract has a single `deposit` function which takes as argument a SimpleSerialize'd `DepositData`. ### Withdrawal credentials -One of the `DepositInput` fields is `withdrawal_credentials`. It is a commitment to credentials for withdrawals to shards. The first byte of `withdrawal_credentials` is a version number. As of now the only expected format is as follows: +One of the `DepositData` fields is `withdrawal_credentials`. It is a commitment to credentials for withdrawals to shards. The first byte of `withdrawal_credentials` is a version number. As of now the only expected format is as follows: * `withdrawal_credentials[:1] == BLS_WITHDRAWAL_PREFIX_BYTE` * `withdrawal_credentials[1:] == hash(withdrawal_pubkey)[1:]` where `withdrawal_pubkey` is a BLS pubkey From 58603f276e3dc137599d6684b7e47650f03871b7 Mon Sep 17 00:00:00 2001 From: Justin Date: Fri, 15 Mar 2019 11:28:55 +0000 Subject: [PATCH 2/3] 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 2d168cfc2..9f8bec933 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1271,7 +1271,7 @@ def process_deposit(state: BeaconState, deposit: Deposit) -> None: # Verify the Merkle branch merkle_branch_is_valid = verify_merkle_branch( - leaf=hash(serialize(deposit.data)), # 48 + 32 + 8 + 96 = 184 bytes serialisation + leaf=hash(serialize(deposit.data)), # 48 + 32 + 8 + 96 = 184 bytes serialization proof=deposit.proof, depth=DEPOSIT_CONTRACT_TREE_DEPTH, index=deposit.index, From 5a708bae348221bfe1926775b31a4de05b23a090 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Tue, 26 Mar 2019 07:38:51 -0600 Subject: [PATCH 3/3] fix tests --- tests/phase0/helpers.py | 29 ++++++++++------------------- tests/phase0/test_sanity.py | 4 ++-- 2 files changed, 12 insertions(+), 21 deletions(-) diff --git a/tests/phase0/helpers.py b/tests/phase0/helpers.py index a0ede04e5..3c68c2c8c 100644 --- a/tests/phase0/helpers.py +++ b/tests/phase0/helpers.py @@ -12,7 +12,6 @@ from build.phase0.spec import ( AttestationData, BeaconBlockHeader, Deposit, - DepositInput, DepositData, Eth1Data, ProposerSlashing, @@ -43,21 +42,17 @@ pubkey_to_privkey = {pubkey: privkey for privkey, pubkey in zip(privkeys, pubkey def create_mock_genesis_validator_deposits(num_validators, deposit_data_leaves=None): if not deposit_data_leaves: deposit_data_leaves = [] - deposit_timestamp = 0 proof_of_possession = b'\x33' * 96 deposit_data_list = [] for i in range(num_validators): pubkey = pubkeys[i] deposit_data = DepositData( + pubkey=pubkey, + # insecurely use pubkey as withdrawal key as well + withdrawal_credentials=spec.BLS_WITHDRAWAL_PREFIX_BYTE + hash(pubkey)[1:], amount=spec.MAX_DEPOSIT_AMOUNT, - timestamp=deposit_timestamp, - deposit_input=DepositInput( - pubkey=pubkey, - # insecurely use pubkey as withdrawal key as well - withdrawal_credentials=spec.BLS_WITHDRAWAL_PREFIX_BYTE + hash(pubkey)[1:], - proof_of_possession=proof_of_possession, - ), + proof_of_possession=proof_of_possession, ) item = hash(deposit_data.serialize()) deposit_data_leaves.append(item) @@ -72,7 +67,7 @@ def create_mock_genesis_validator_deposits(num_validators, deposit_data_leaves=N genesis_validator_deposits.append(Deposit( proof=list(get_merkle_proof(tree, item_index=i)), index=i, - deposit_data=deposit_data_list[i] + data=deposit_data_list[i] )) return genesis_validator_deposits, root @@ -112,14 +107,15 @@ def build_empty_block_for_next_slot(state): def build_deposit_data(state, pubkey, privkey, amount): - deposit_input = DepositInput( + deposit_data = DepositData( pubkey=pubkey, # insecurely use pubkey as withdrawal key as well withdrawal_credentials=spec.BLS_WITHDRAWAL_PREFIX_BYTE + hash(pubkey)[1:], + amount=amount, proof_of_possession=EMPTY_SIGNATURE, ) proof_of_possession = bls.sign( - message_hash=signed_root(deposit_input), + message_hash=signed_root(deposit_data), privkey=privkey, domain=get_domain( state.fork, @@ -127,12 +123,7 @@ def build_deposit_data(state, pubkey, privkey, amount): spec.DOMAIN_DEPOSIT, ) ) - deposit_input.proof_of_possession = proof_of_possession - deposit_data = DepositData( - amount=amount, - timestamp=0, - deposit_input=deposit_input, - ) + deposit_data.proof_of_possession = proof_of_possession return deposit_data @@ -201,7 +192,7 @@ def build_deposit(state, deposit = Deposit( proof=list(proof), index=index, - deposit_data=deposit_data, + data=deposit_data, ) return deposit, root, deposit_data_leaves diff --git a/tests/phase0/test_sanity.py b/tests/phase0/test_sanity.py index 0b195fe96..19e75f672 100644 --- a/tests/phase0/test_sanity.py +++ b/tests/phase0/test_sanity.py @@ -163,7 +163,7 @@ def test_deposit_in_block(state): deposit = Deposit( proof=list(proof), index=index, - deposit_data=deposit_data, + data=deposit_data, ) pre_state.latest_eth1_data.deposit_root = root @@ -202,7 +202,7 @@ def test_deposit_top_up(state): deposit = Deposit( proof=list(proof), index=merkle_index, - deposit_data=deposit_data, + data=deposit_data, ) pre_state.latest_eth1_data.deposit_root = root