-
Notifications
You must be signed in to change notification settings - Fork 678
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1640 from hwwhww/on_startup_4
Routine for processing deposits
- Loading branch information
Showing
11 changed files
with
596 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
from typing import ( | ||
Sequence, | ||
Tuple, | ||
) | ||
|
||
from eth_typing import ( | ||
Hash32, | ||
) | ||
from eth_utils import ( | ||
ValidationError, | ||
) | ||
|
||
from eth._utils import bls | ||
|
||
from eth.beacon.constants import ( | ||
EMPTY_SIGNATURE, | ||
) | ||
from eth.beacon.enums import ( | ||
SignatureDomain, | ||
) | ||
from eth.beacon.exceptions import ( | ||
MinEmptyValidatorIndexNotFound, | ||
) | ||
from eth.beacon.types.deposit_input import DepositInput | ||
from eth.beacon.types.states import BeaconState | ||
from eth.beacon.types.validator_records import ValidatorRecord | ||
from eth.beacon.helpers import ( | ||
get_domain, | ||
) | ||
|
||
|
||
def get_min_empty_validator_index(validators: Sequence[ValidatorRecord], | ||
current_slot: int, | ||
zero_balance_validator_ttl: int) -> int: | ||
for index, validator in enumerate(validators): | ||
is_empty = ( | ||
validator.balance == 0 and | ||
validator.latest_status_change_slot + zero_balance_validator_ttl <= current_slot | ||
) | ||
if is_empty: | ||
return index | ||
raise MinEmptyValidatorIndexNotFound() | ||
|
||
|
||
def validate_proof_of_possession(state: BeaconState, | ||
pubkey: int, | ||
proof_of_possession: bytes, | ||
withdrawal_credentials: Hash32, | ||
randao_commitment: Hash32) -> None: | ||
deposit_input = DepositInput( | ||
pubkey=pubkey, | ||
withdrawal_credentials=withdrawal_credentials, | ||
randao_commitment=randao_commitment, | ||
proof_of_possession=EMPTY_SIGNATURE, | ||
) | ||
|
||
is_valid_signature = bls.verify( | ||
pubkey=pubkey, | ||
# TODO: change to hash_tree_root(deposit_input) when we have SSZ tree hashing | ||
message=deposit_input.root, | ||
signature=proof_of_possession, | ||
domain=get_domain( | ||
state.fork_data, | ||
state.slot, | ||
SignatureDomain.DOMAIN_DEPOSIT, | ||
), | ||
) | ||
|
||
if not is_valid_signature: | ||
raise ValidationError( | ||
"BLS signature verification error" | ||
) | ||
|
||
|
||
def add_pending_validator(state: BeaconState, | ||
validator: ValidatorRecord, | ||
zero_balance_validator_ttl: int) -> Tuple[BeaconState, int]: | ||
""" | ||
Add a validator to the existing minimum empty validator index or | ||
append to ``validator_registry``. | ||
""" | ||
# Check if there's empty validator index in `validator_registry` | ||
try: | ||
index = get_min_empty_validator_index( | ||
state.validator_registry, | ||
state.slot, | ||
zero_balance_validator_ttl, | ||
) | ||
except MinEmptyValidatorIndexNotFound: | ||
index = None | ||
|
||
# Append to the validator_registry | ||
validator_registry = state.validator_registry + (validator,) | ||
state = state.copy( | ||
validator_registry=validator_registry, | ||
) | ||
index = len(state.validator_registry) - 1 | ||
else: | ||
# Use the empty validator index | ||
state = state.update_validator(index, validator) | ||
|
||
return state, index | ||
|
||
|
||
def process_deposit(*, | ||
state: BeaconState, | ||
pubkey: int, | ||
deposit: int, | ||
proof_of_possession: bytes, | ||
withdrawal_credentials: Hash32, | ||
randao_commitment: Hash32, | ||
zero_balance_validator_ttl: int) -> Tuple[BeaconState, int]: | ||
""" | ||
Process a deposit from Ethereum 1.0. | ||
""" | ||
validate_proof_of_possession( | ||
state, | ||
pubkey, | ||
proof_of_possession, | ||
withdrawal_credentials, | ||
randao_commitment, | ||
) | ||
|
||
validator_pubkeys = tuple(v.pubkey for v in state.validator_registry) | ||
if pubkey not in validator_pubkeys: | ||
validator = ValidatorRecord.get_pending_validator( | ||
pubkey=pubkey, | ||
withdrawal_credentials=withdrawal_credentials, | ||
randao_commitment=randao_commitment, | ||
balance=deposit, | ||
latest_status_change_slot=state.slot, | ||
) | ||
|
||
state, index = add_pending_validator( | ||
state, | ||
validator, | ||
zero_balance_validator_ttl, | ||
) | ||
else: | ||
# Top-up - increase balance by deposit | ||
index = validator_pubkeys.index(pubkey) | ||
validator = state.validator_registry[index] | ||
|
||
if validator.withdrawal_credentials != withdrawal_credentials: | ||
raise ValidationError( | ||
"`withdrawal_credentials` are incorrect:\n" | ||
"\texpected: %s, found: %s" % ( | ||
validator.withdrawal_credentials, | ||
validator.withdrawal_credentials, | ||
) | ||
) | ||
|
||
# Update validator's balance and state | ||
validator = validator.copy( | ||
balance=validator.balance + deposit, | ||
) | ||
state = state.update_validator(index, validator) | ||
|
||
return state, index |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
from eth.exceptions import ( | ||
PyEVMError, | ||
) | ||
|
||
|
||
class MinEmptyValidatorIndexNotFound(PyEVMError): | ||
""" | ||
No empty slot in the validator registry | ||
""" | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.