Merge pull request #780 from ethereum/JustinDrake-patch-7
Simplify deposits
This commit is contained in:
commit
9bc1928bed
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue