Merge pull request #780 from ethereum/JustinDrake-patch-7

Simplify deposits
This commit is contained in:
Danny Ryan 2019-03-26 07:40:21 -06:00 committed by GitHub
commit 9bc1928bed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 25 additions and 54 deletions

View File

@ -29,7 +29,6 @@
- [`AttestationData`](#attestationdata) - [`AttestationData`](#attestationdata)
- [`AttestationDataAndCustodyBit`](#attestationdataandcustodybit) - [`AttestationDataAndCustodyBit`](#attestationdataandcustodybit)
- [`SlashableAttestation`](#slashableattestation) - [`SlashableAttestation`](#slashableattestation)
- [`DepositInput`](#depositinput)
- [`DepositData`](#depositdata) - [`DepositData`](#depositdata)
- [`BeaconBlockHeader`](#beaconblockheader) - [`BeaconBlockHeader`](#beaconblockheader)
- [`Validator`](#validator) - [`Validator`](#validator)
@ -384,7 +383,7 @@ The types are defined topologically to aid in facilitating an executable version
} }
``` ```
#### `DepositInput` #### `DepositData`
```python ```python
{ {
@ -392,21 +391,10 @@ The types are defined topologically to aid in facilitating an executable version
'pubkey': 'bytes48', 'pubkey': 'bytes48',
# Withdrawal credentials # Withdrawal credentials
'withdrawal_credentials': 'bytes32', 'withdrawal_credentials': 'bytes32',
# A BLS signature of this `DepositInput`
'proof_of_possession': 'bytes96',
}
```
#### `DepositData`
```python
{
# Amount in Gwei # Amount in Gwei
'amount': 'uint64', 'amount': 'uint64',
# Timestamp from deposit contract # Container self-signature
'timestamp': 'uint64', 'proof_of_possession': 'bytes96',
# Deposit input
'deposit_input': DepositInput,
} }
``` ```
@ -520,7 +508,7 @@ The types are defined topologically to aid in facilitating an executable version
# Index in the deposit tree # Index in the deposit tree
'index': 'uint64', 'index': 'uint64',
# Data # Data
'deposit_data': DepositData, 'data': DepositData,
} }
``` ```
@ -1340,19 +1328,12 @@ def process_deposit(state: BeaconState, deposit: Deposit) -> None:
Process a deposit from Ethereum 1.0. Process a deposit from Ethereum 1.0.
Note that this function mutates ``state``. 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 # Deposits must be processed in order
assert deposit.index == state.deposit_index assert deposit.index == state.deposit_index
# Verify the Merkle branch # Verify the Merkle branch
merkle_branch_is_valid = verify_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 serialization
proof=deposit.proof, proof=deposit.proof,
depth=DEPOSIT_CONTRACT_TREE_DEPTH, depth=DEPOSIT_CONTRACT_TREE_DEPTH,
index=deposit.index, index=deposit.index,
@ -1367,16 +1348,15 @@ def process_deposit(state: BeaconState, deposit: Deposit) -> None:
state.deposit_index += 1 state.deposit_index += 1
validator_pubkeys = [v.pubkey for v in state.validator_registry] validator_pubkeys = [v.pubkey for v in state.validator_registry]
pubkey = deposit_input.pubkey pubkey = deposit.data.pubkey
amount = deposit.deposit_data.amount amount = deposit.data.amount
withdrawal_credentials = deposit_input.withdrawal_credentials
if pubkey not in validator_pubkeys: if pubkey not in validator_pubkeys:
# Verify the proof of possession # Verify the proof of possession
proof_is_valid = bls_verify( proof_is_valid = bls_verify(
pubkey=deposit_input.pubkey, pubkey=pubkey,
message_hash=signed_root(deposit_input), message_hash=signed_root(deposit.data),
signature=deposit_input.proof_of_possession, signature=deposit.data.proof_of_possession,
domain=get_domain( domain=get_domain(
state.fork, state.fork,
get_current_epoch(state), get_current_epoch(state),
@ -1389,7 +1369,7 @@ def process_deposit(state: BeaconState, deposit: Deposit) -> None:
# Add new validator # Add new validator
validator = Validator( validator = Validator(
pubkey=pubkey, pubkey=pubkey,
withdrawal_credentials=withdrawal_credentials, withdrawal_credentials=deposit.data.withdrawal_credentials,
activation_epoch=FAR_FUTURE_EPOCH, activation_epoch=FAR_FUTURE_EPOCH,
exit_epoch=FAR_FUTURE_EPOCH, exit_epoch=FAR_FUTURE_EPOCH,
withdrawable_epoch=FAR_FUTURE_EPOCH, withdrawable_epoch=FAR_FUTURE_EPOCH,
@ -1491,11 +1471,11 @@ The initial deployment phases of Ethereum 2.0 are implemented without consensus
### Deposit arguments ### 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 ### 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] == BLS_WITHDRAWAL_PREFIX_BYTE`
* `withdrawal_credentials[1:] == hash(withdrawal_pubkey)[1:]` where `withdrawal_pubkey` is a BLS pubkey * `withdrawal_credentials[1:] == hash(withdrawal_pubkey)[1:]` where `withdrawal_pubkey` is a BLS pubkey

View File

@ -12,7 +12,6 @@ from build.phase0.spec import (
AttestationData, AttestationData,
BeaconBlockHeader, BeaconBlockHeader,
Deposit, Deposit,
DepositInput,
DepositData, DepositData,
Eth1Data, Eth1Data,
ProposerSlashing, 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): def create_mock_genesis_validator_deposits(num_validators, deposit_data_leaves=None):
if not deposit_data_leaves: if not deposit_data_leaves:
deposit_data_leaves = [] deposit_data_leaves = []
deposit_timestamp = 0
proof_of_possession = b'\x33' * 96 proof_of_possession = b'\x33' * 96
deposit_data_list = [] deposit_data_list = []
for i in range(num_validators): for i in range(num_validators):
pubkey = pubkeys[i] pubkey = pubkeys[i]
deposit_data = DepositData( 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, amount=spec.MAX_DEPOSIT_AMOUNT,
timestamp=deposit_timestamp, proof_of_possession=proof_of_possession,
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,
),
) )
item = hash(deposit_data.serialize()) item = hash(deposit_data.serialize())
deposit_data_leaves.append(item) 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( genesis_validator_deposits.append(Deposit(
proof=list(get_merkle_proof(tree, item_index=i)), proof=list(get_merkle_proof(tree, item_index=i)),
index=i, index=i,
deposit_data=deposit_data_list[i] data=deposit_data_list[i]
)) ))
return genesis_validator_deposits, root 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): def build_deposit_data(state, pubkey, privkey, amount):
deposit_input = DepositInput( deposit_data = DepositData(
pubkey=pubkey, pubkey=pubkey,
# insecurely use pubkey as withdrawal key as well # insecurely use pubkey as withdrawal key as well
withdrawal_credentials=spec.BLS_WITHDRAWAL_PREFIX_BYTE + hash(pubkey)[1:], withdrawal_credentials=spec.BLS_WITHDRAWAL_PREFIX_BYTE + hash(pubkey)[1:],
amount=amount,
proof_of_possession=EMPTY_SIGNATURE, proof_of_possession=EMPTY_SIGNATURE,
) )
proof_of_possession = bls.sign( proof_of_possession = bls.sign(
message_hash=signed_root(deposit_input), message_hash=signed_root(deposit_data),
privkey=privkey, privkey=privkey,
domain=get_domain( domain=get_domain(
state.fork, state.fork,
@ -127,12 +123,7 @@ def build_deposit_data(state, pubkey, privkey, amount):
spec.DOMAIN_DEPOSIT, spec.DOMAIN_DEPOSIT,
) )
) )
deposit_input.proof_of_possession = proof_of_possession deposit_data.proof_of_possession = proof_of_possession
deposit_data = DepositData(
amount=amount,
timestamp=0,
deposit_input=deposit_input,
)
return deposit_data return deposit_data
@ -201,7 +192,7 @@ def build_deposit(state,
deposit = Deposit( deposit = Deposit(
proof=list(proof), proof=list(proof),
index=index, index=index,
deposit_data=deposit_data, data=deposit_data,
) )
return deposit, root, deposit_data_leaves return deposit, root, deposit_data_leaves

View File

@ -163,7 +163,7 @@ def test_deposit_in_block(state):
deposit = Deposit( deposit = Deposit(
proof=list(proof), proof=list(proof),
index=index, index=index,
deposit_data=deposit_data, data=deposit_data,
) )
pre_state.latest_eth1_data.deposit_root = root pre_state.latest_eth1_data.deposit_root = root
@ -202,7 +202,7 @@ def test_deposit_top_up(state):
deposit = Deposit( deposit = Deposit(
proof=list(proof), proof=list(proof),
index=merkle_index, index=merkle_index,
deposit_data=deposit_data, data=deposit_data,
) )
pre_state.latest_eth1_data.deposit_root = root pre_state.latest_eth1_data.deposit_root = root