예제 #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 get_logs(self, block_number: BlockNumber) -> Tuple[DepositLog, ...]:
     block_hash = block_number.to_bytes(32, byteorder='big')
     if block_number == self.start_block_number:
         logs = (
             DepositLog(
                 block_hash=Hash32(block_hash),
                 pubkey=deposit.pubkey,
                 withdrawal_credentials=deposit.withdrawal_credentials,
                 signature=deposit.signature,
                 amount=deposit.amount,
             )
             for deposit in self.deposits
         )
         return tuple(logs)
     else:
         logs = (
             DepositLog(
                 block_hash=Hash32(block_hash),
                 pubkey=BLSPubkey(b'\x12' * 48),
                 withdrawal_credentials=Hash32(b'\x23' * 32),
                 signature=BLSSignature(b'\x34' * 96),
                 amount=Gwei(32 * GWEI_PER_ETH),
             )
             for _ in range(self.num_deposits_per_block)
         )
         return tuple(logs)
예제 #3
0
def sample_deposit_data_params(sample_signature):
    return {
        "pubkey": BLSPubkey(b"\x67" * 48),
        "withdrawal_credentials": b"\11" * 32,
        "amount": Gwei(56),
        "signature": sample_signature,
    }
예제 #4
0
파일: conftest.py 프로젝트: s0b0lev/trinity
def sample_deposit_data_params(sample_signature):
    return {
        'pubkey': BLSPubkey(b'\x67' * 48),
        'withdrawal_credentials': b'\11' * 32,
        'amount': Gwei(56),
        'signature': sample_signature,
    }
예제 #5
0
async def _get_attestation(context: Context, request: Request) -> Response:
    if not isinstance(request, dict):
        return {}

    public_key = BLSPubkey(decode_hex(request["validator_pubkey"]))
    slot = Slot(int(request["slot"]))
    committee_index = CommitteeIndex(int(request["committee_index"]))
    attestation = context.get_attestation(public_key, slot, committee_index)
    return to_formatted_dict(attestation)
예제 #6
0
def load_genesis_key_map(
    encoded_key_map: Tuple[Dict[str, Any]],
    public_key_codec: Callable[
        [str], BLSPubkey] = lambda key: BLSPubkey(decode_hex(key)),
    private_key_codec: Callable[[str], int] = _decode_private_key_from_hex,
) -> Iterable[Tuple[BLSPubkey, int]]:
    for key_pair in encoded_key_map:
        public_key = public_key_codec(key_pair["public_key"])
        private_key = private_key_codec(key_pair["private_key"])
        yield public_key, private_key
예제 #7
0
 def _is_valid_pubkey(cls, pubkey: bytes) -> bool:
     """
     Note: PopVerify is a precondition for -Verify APIs
     However, it's difficult to verify it with the API interface in runtime.
     To ensure KeyValidate has been checked, we check it in the input validation.
     See https://github.com/cfrg/draft-irtf-cfrg-bls-signature/issues/27 for the discussion.
     """
     if not super()._is_valid_pubkey(pubkey):
         return False
     return cls.KeyValidate(BLSPubkey(pubkey))
예제 #8
0
 def _load_key_file(self, key_file: Path) -> Tuple[BLSPubkey, BLSPrivateKey, str]:
     with open(key_file) as key_file_handle:
         keyfile_json = json.load(key_file_handle)
         public_key = BLSPubkey(decode_hex(keyfile_json["public_key"]))
         password = self._password_provider(public_key)
         try:
             private_key = eth_keyfile.decode_keyfile_json(keyfile_json, password)
         except ValueError:
             self.logger.error(
                 "password was incorrect for public key %s", encode_hex(public_key)
             )
             raise
         return (public_key, private_key, keyfile_json["id"])
예제 #9
0
def create_keypair_and_mock_withdraw_credentials(
    config: Eth2Config, key_set: Sequence[Dict[str, Any]]
) -> Tuple[Tuple[BLSPubkey, ...], Tuple[int, ...], Tuple[Hash32, ...]]:
    pubkeys: Tuple[BLSPubkey, ...] = ()
    privkeys: Tuple[int, ...] = ()
    withdrawal_credentials: Tuple[Hash32, ...] = ()
    for key_pair in key_set:
        pubkey = BLSPubkey(decode_hex(key_pair["pubkey"]))
        privkey = int.from_bytes(decode_hex(key_pair["privkey"]), "big")
        withdrawal_credential = Hash32(
            config.BLS_WITHDRAWAL_PREFIX.to_bytes(1, byteorder="big") +
            hash_eth2(pubkey)[1:])

        pubkeys += (pubkey, )
        privkeys += (privkey, )
        withdrawal_credentials += (withdrawal_credential, )

    return (pubkeys, privkeys, withdrawal_credentials)
예제 #10
0
def create_keypair_and_mock_withdraw_credentials(
    config: Eth2Config, key_set: Sequence[Dict[str, Any]]
) -> Tuple[Tuple[BLSPubkey, ...], Tuple[int, ...], Tuple[Hash32, ...]]:
    """
    NOTE: this function mixes the parsing of keying material with the generation of derived values.
    Prefer other functions in this module that do the derivation directly.
    """
    pubkeys: Tuple[BLSPubkey, ...] = ()
    privkeys: Tuple[int, ...] = ()
    withdrawal_credentials: Tuple[Hash32, ...] = ()
    for key_pair in key_set:
        pubkey = BLSPubkey(decode_hex(key_pair["pubkey"]))
        privkey = int.from_bytes(decode_hex(key_pair["privkey"]), "big")
        withdrawal_credential = Hash32(config.BLS_WITHDRAWAL_PREFIX +
                                       hash_eth2(pubkey)[1:])

        pubkeys += (pubkey, )
        privkeys += (privkey, )
        withdrawal_credentials += (withdrawal_credential, )

    return (pubkeys, privkeys, withdrawal_credentials)
예제 #11
0
from eth.constants import ZERO_HASH32
from eth_typing import BLSPubkey, BLSSignature

from eth2.beacon.typing import Epoch, HashTreeRoot, SigningRoot, Timestamp

EMPTY_SIGNATURE = BLSSignature(b"\x00" * 96)
EMPTY_PUBKEY = BLSPubkey(b"\x00" * 48)
GWEI_PER_ETH = 10 ** 9
FAR_FUTURE_EPOCH = Epoch(2 ** 64 - 1)

ZERO_SIGNING_ROOT = SigningRoot(ZERO_HASH32)
ZERO_HASH_TREE_ROOT = HashTreeRoot(ZERO_HASH32)
GENESIS_PARENT_ROOT = ZERO_SIGNING_ROOT

ZERO_TIMESTAMP = Timestamp(0)

MAX_INDEX_COUNT = 2 ** 40

MAX_RANDOM_BYTE = 2 ** 8 - 1

BASE_REWARDS_PER_EPOCH = 4

DEPOSIT_CONTRACT_TREE_DEPTH = 2 ** 5

SECONDS_PER_DAY = 86400

JUSTIFICATION_BITS_LENGTH = 4
예제 #12
0
def _parse_bls_pubkey(encoded_public_key: str) -> BLSPubkey:
    return BLSPubkey(decode_hex(encoded_public_key))
예제 #13
0
def G1_to_pubkey(pt: G1Uncompressed) -> BLSPubkey:
    z = compress_G1(pt)
    return BLSPubkey(i2osp(z, 48))
예제 #14
0
def _mini_stf(state: BeaconState, block: Optional[BeaconBlock],
              config: Eth2Config) -> BeaconState:
    """
    A simplified state transition for testing state storage.

    - updates ``state_roots`` with the previous slot's state root
    - updates ``block_roots`` with the previous slot's block root
    - updates ``randao_mixes`` with an arbitrary mix at the current epoch
    - creates a new ``latest_block_header`` and adds it to the state
    - fills in the rest of the attributes with arbitrary values
    """
    current_slot = state.slot + 1
    current_epoch = current_slot // config.SLOTS_PER_EPOCH

    if block:
        latest_block_header = block.header
    else:
        latest_block_header = state.latest_block_header

    # state changes that depend on the previous state for retrieval
    randao_mix = Root(Hash32(current_slot.to_bytes(32, byteorder="little")))
    state = (state.transform(
        ("state_roots", state.slot % config.SLOTS_PER_HISTORICAL_ROOT),
        state.hash_tree_root,
    ).transform(
        ("block_roots", state.slot % config.SLOTS_PER_HISTORICAL_ROOT),
        state.latest_block_header.hash_tree_root,
    ).transform(
        ("randao_mixes", current_epoch % config.EPOCHS_PER_HISTORICAL_VECTOR),
        randao_mix,
    ).mset("slot", current_slot, "latest_block_header", latest_block_header))

    # state changes that do not depend on the previous state for retrieval
    new_validators = [
        Validator.create(pubkey=BLSPubkey(n.to_bytes(48, byteorder="little")))
        for n in range(current_slot, current_slot + 20)
    ]
    new_eth1_data_votes = [
        Eth1Data.create(
            deposit_root=Root(Hash32(n.to_bytes(32, byteorder="little"))))
        for n in range(current_slot, current_slot + 7)
    ]
    new_previous_epoch_attestations = [
        PendingAttestation.create(proposer_index=ValidatorIndex(n))
        for n in range(current_slot, current_slot + 5)
    ]
    new_current_epoch_attestations = [
        PendingAttestation.create(proposer_index=ValidatorIndex(n))
        for n in range(current_slot + 5, current_slot + 10)
    ]
    state = state.mset(
        "validators",
        new_validators,
        "balances",
        (32, ) * len(new_validators),
        "eth1_data_votes",
        new_eth1_data_votes,
        "eth1_data",
        new_eth1_data_votes[0],
        "previous_epoch_attestations",
        new_previous_epoch_attestations,
        "current_epoch_attestations",
        new_current_epoch_attestations,
        "previous_justified_checkpoint",
        Checkpoint.create(epoch=Epoch(current_slot + 42)),
        "current_justified_checkpoint",
        Checkpoint.create(epoch=Epoch(current_slot + 43)),
        "finalized_checkpoint",
        Checkpoint.create(epoch=Epoch(current_slot + 44)),
    )

    return state
예제 #15
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
예제 #16
0
 def SkToPk(k: int) -> BLSPubkey:
     return BLSPubkey(k.to_bytes(48, "little"))
예제 #17
0
파일: loading.py 프로젝트: s0b0lev/trinity
def get_input_bls_pubkeys(
        test_case: Dict[str, Any]) -> Dict[str, Tuple[BLSPubkey, ...]]:
    return {
        'pubkeys':
        tuple(BLSPubkey(decode_hex(item)) for item in test_case['input'])
    }
예제 #18
0
파일: noop.py 프로젝트: wschwab/trinity
 def privtopub(k: int) -> BLSPubkey:
     return BLSPubkey(k.to_bytes(48, "little"))
예제 #19
0
from eth.constants import (
    ZERO_HASH32,
)
from eth_typing import (
    BLSSignature,
    BLSPubkey,
)
from eth2.beacon.typing import (
    Epoch,
    Timestamp,
)


EMPTY_SIGNATURE = BLSSignature(b'\x00' * 96)
EMPTY_PUBKEY = BLSPubkey(b'\x00' * 48)
GWEI_PER_ETH = 10**9
FAR_FUTURE_EPOCH = Epoch(2**64 - 1)

GENESIS_PARENT_ROOT = ZERO_HASH32

ZERO_TIMESTAMP = Timestamp(0)

MAX_INDEX_COUNT = 2**40

MAX_RANDOM_BYTE = 2**8 - 1

BASE_REWARDS_PER_EPOCH = 5

DEPOSIT_CONTRACT_TREE_DEPTH = 2**5
예제 #20
0
파일: loading.py 프로젝트: s0b0lev/trinity
def get_output_bls_pubkey(test_case: Dict[str, Any]) -> BLSPubkey:
    return BLSPubkey(decode_hex(test_case['output']))
예제 #21
0
def G1_to_pubkey(pt: G1Uncompressed) -> BLSPubkey:
    z = compress_G1(pt)
    return BLSPubkey(z.to_bytes(48, "big"))