예제 #1
0
def verify_deposit(deposit_data_dict: Dict[str, Any]) -> bool:
    '''
    Checks whether a deposit is valid based on the eth2 rules.
    https://github.com/ethereum/eth2.0-specs/blob/dev/specs/phase0/beacon-chain.md#deposits
    '''
    pubkey = BLSPubkey(bytes.fromhex(deposit_data_dict['pubkey']))
    withdrawal_credentials = bytes.fromhex(deposit_data_dict['withdrawal_credentials'])
    amount = deposit_data_dict['amount']
    signature = BLSSignature(bytes.fromhex(deposit_data_dict['signature']))
    deposit_data_root = bytes.fromhex(deposit_data_dict['signed_deposit_data_root'])

    # Verify deposit amount
    if not MIN_DEPOSIT_AMOUNT < amount <= MAX_DEPOSIT_AMOUNT:
        return False

    # Verify deposit signature && pubkey
    deposit_message = DepositMessage(pubkey=pubkey, withdrawal_credentials=withdrawal_credentials, amount=amount)
    domain = compute_domain(domain_type=DOMAIN_DEPOSIT)
    signing_root = compute_signing_root(deposit_message, domain)
    if not bls.Verify(pubkey, signing_root, signature):
        return False

    # Verify Deposit Root
    deposit = Deposit(pubkey=pubkey, withdrawal_credentials=withdrawal_credentials, amount=amount, signature=signature)
    return deposit.hash_tree_root == deposit_data_root
예제 #2
0
 def deposit_message(self) -> DepositMessage:
     if not MIN_DEPOSIT_AMOUNT <= self.amount <= MAX_DEPOSIT_AMOUNT:
         raise ValidationError(
             f"{self.amount / ETH2GWEI} ETH deposits are not within the bounds of this cli."
         )
     return DepositMessage(
         pubkey=self.signing_pk,
         withdrawal_credentials=self.withdrawal_credentials,
         amount=self.amount,
     )
예제 #3
0
def sign_deposit_data(deposit_data: DepositMessage, sk: int) -> Deposit:
    '''
    Given a DepositMessage, it signs its root and returns a Deposit
    '''
    assert bls.PrivToPub(sk) == deposit_data.pubkey
    domain = compute_domain()
    signing_root = compute_signing_root(deposit_data, domain)
    signed_deposit_data = Deposit(**deposit_data.as_dict(),
                                  signature=bls.Sign(sk, signing_root))
    return signed_deposit_data
예제 #4
0
def test_compute_signing_root(domain, valid, result):
    deposit_message = DepositMessage(
        pubkey=b'\x12' * 48,
        withdrawal_credentials=b'\x12' * 32,
        amount=100,
    )
    if valid:
        assert compute_signing_root(deposit_message, domain) == result
    else:
        with pytest.raises(ValueError):
            compute_signing_root(deposit_message, domain)
예제 #5
0
def export_deposit_data_json(*, credentials: List[ValidatorCredentials],
                             folder: str):
    deposit_data: List[dict] = []
    for credential in credentials:
        deposit_datum = DepositMessage(
            pubkey=credential.signing_pk,
            withdrawal_credentials=SHA256(credential.withdrawal_pk),
            amount=credential.amount,
        )
        signed_deposit_datum = sign_deposit_data(deposit_datum,
                                                 credential.signing_sk)
        datum_dict = signed_deposit_datum.as_dict()
        datum_dict.update({'deposit_data_root': deposit_datum.hash_tree_root})
        datum_dict.update(
            {'signed_deposit_data_root': signed_deposit_datum.hash_tree_root})
        deposit_data.append(datum_dict)

    filefolder = os.path.join(folder, 'deposit_data-%i.json' % time.time())
    with open(filefolder, 'w') as f:
        json.dump(deposit_data, f, default=lambda x: x.hex())
    return filefolder
예제 #6
0
def validate_deposit(deposit_data_dict: Dict[str, Any],
                     credential: Credential) -> bool:
    '''
    Checks whether a deposit is valid based on the eth2 rules.
    https://github.com/ethereum/eth2.0-specs/blob/dev/specs/phase0/beacon-chain.md#deposits
    '''
    pubkey = BLSPubkey(bytes.fromhex(deposit_data_dict['pubkey']))
    withdrawal_credentials = bytes.fromhex(
        deposit_data_dict['withdrawal_credentials'])
    amount = deposit_data_dict['amount']
    signature = BLSSignature(bytes.fromhex(deposit_data_dict['signature']))
    deposit_message_root = bytes.fromhex(
        deposit_data_dict['deposit_data_root'])
    fork_version = bytes.fromhex(deposit_data_dict['fork_version'])

    # Verify pubkey
    if len(pubkey) != 48:
        return False
    if pubkey != credential.signing_pk:
        return False

    # Verify withdrawal credential
    if len(withdrawal_credentials) != 32:
        return False
    if withdrawal_credentials[:
                              1] == BLS_WITHDRAWAL_PREFIX == credential.withdrawal_prefix:
        if withdrawal_credentials[1:] != SHA256(credential.withdrawal_pk)[1:]:
            return False
    elif withdrawal_credentials[:
                                1] == ETH1_ADDRESS_WITHDRAWAL_PREFIX == credential.withdrawal_prefix:
        if withdrawal_credentials[1:12] != b'\x00' * 11:
            return False
        if credential.eth1_withdrawal_address is None:
            return False
        if withdrawal_credentials[12:] != credential.eth1_withdrawal_address:
            return False
    else:
        return False

    # Verify deposit amount
    if not MIN_DEPOSIT_AMOUNT < amount <= MAX_DEPOSIT_AMOUNT:
        return False

    # Verify deposit signature && pubkey
    deposit_message = DepositMessage(
        pubkey=pubkey,
        withdrawal_credentials=withdrawal_credentials,
        amount=amount)
    domain = compute_deposit_domain(fork_version)
    signing_root = compute_signing_root(deposit_message, domain)
    if not bls.Verify(pubkey, signing_root, signature):
        return False

    # Verify Deposit Root
    signed_deposit = DepositData(
        pubkey=pubkey,
        withdrawal_credentials=withdrawal_credentials,
        amount=amount,
        signature=signature,
    )
    return signed_deposit.hash_tree_root == deposit_message_root
예제 #7
0
 def deposit_message(self) -> DepositMessage:
     return DepositMessage(
         pubkey=self.signing_pk,
         withdrawal_credentials=self.withdrawal_credentials,
         amount=self.amount,
     )