Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify deposits #780

Merged
merged 4 commits into from
Mar 26, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 13 additions & 33 deletions specs/core/0_beacon-chain.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
- [`AttestationData`](#attestationdata)
- [`AttestationDataAndCustodyBit`](#attestationdataandcustodybit)
- [`SlashableAttestation`](#slashableattestation)
- [`DepositInput`](#depositinput)
- [`DepositData`](#depositdata)
- [`BeaconBlockHeader`](#beaconblockheader)
- [`Validator`](#validator)
Expand Down Expand Up @@ -384,29 +383,18 @@ The types are defined topologically to aid in facilitating an executable version
}
```

#### `DepositInput`
#### `DepositData`

```python
{
# BLS pubkey
'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',
}
```

Expand Down Expand Up @@ -520,7 +508,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,
}
```

Expand Down Expand Up @@ -1340,19 +1328,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 serialization
proof=deposit.proof,
depth=DEPOSIT_CONTRACT_TREE_DEPTH,
index=deposit.index,
Expand All @@ -1367,16 +1348,15 @@ 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
amount = deposit.data.amount

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),
Expand All @@ -1389,7 +1369,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,
Expand Down Expand Up @@ -1491,11 +1471,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
Expand Down
29 changes: 10 additions & 19 deletions tests/phase0/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
AttestationData,
BeaconBlockHeader,
Deposit,
DepositInput,
DepositData,
Eth1Data,
ProposerSlashing,
Expand Down Expand Up @@ -43,21 +42,17 @@
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)
Expand All @@ -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

Expand Down Expand Up @@ -112,27 +107,23 @@ 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,
get_current_epoch(state),
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


Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions tests/phase0/test_sanity.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down