示例#1
0
def compute_shuffled_index(index: int, index_count: int, seed: Hash32,
                           shuffle_round_count: int) -> int:
    """
    Return `p(index)` in a pseudorandom permutation `p` of `0...index_count-1`
    with ``seed`` as entropy.

    Utilizes 'swap or not' shuffling found in
    https://link.springer.com/content/pdf/10.1007%2F978-3-642-32009-5_1.pdf
    See the 'generalized domain' algorithm on page 3.
    """
    if index >= index_count:
        raise ValidationError(
            f"The given `index` ({index}) should be less than `index_count` ({index_count}"
        )

    if index_count > MAX_INDEX_COUNT:
        raise ValidationError(
            f"The given `index_count` ({index_count}) should be equal to or less than "
            f"`MAX_INDEX_COUNT` ({MAX_INDEX_COUNT}")

    new_index = index
    for current_round in range(shuffle_round_count):
        pivot = int.from_bytes(
            hash_eth2(seed + current_round.to_bytes(1, 'little'))[0:8],
            'little',
        ) % index_count

        flip = (pivot + index_count - new_index) % index_count
        position = max(new_index, flip)
        source = hash_eth2(seed + current_round.to_bytes(1, 'little') +
                           (position // 256).to_bytes(4, 'little'))
        byte = source[(position % 256) // 8]
        bit = (byte >> (position % 8)) % 2
        new_index = flip if bit else new_index

    return new_index
示例#2
0
文件: helpers.py 项目: onyb/trinity
def _get_seed(
    state: "BeaconState",
    epoch: Epoch,
    domain_type: DomainType,
    randao_provider: RandaoProvider,
    epoch_provider: Callable[[Epoch], Hash32],
    committee_config: CommitteeConfig,
) -> Hash32:
    randao_mix = randao_provider(
        state,
        Epoch(epoch + committee_config.EPOCHS_PER_HISTORICAL_VECTOR -
              committee_config.MIN_SEED_LOOKAHEAD - 1),
        committee_config.EPOCHS_PER_HISTORICAL_VECTOR,
    )
    epoch_as_bytes = epoch_provider(epoch)

    return hash_eth2(domain_type + epoch_as_bytes + randao_mix)
示例#3
0
def _find_proposer_in_committee(
    validators: Sequence[Validator],
    committee: Sequence[ValidatorIndex],
    epoch: Epoch,
    seed: Hash32,
    max_effective_balance: Gwei,
) -> ValidatorIndex:
    base = int(epoch)
    i = 0
    committee_len = len(committee)
    while True:
        candidate_index = committee[(base + i) % committee_len]
        random_byte = hash_eth2(seed + (i // 32).to_bytes(8, "little"))[i % 32]
        effective_balance = validators[candidate_index].effective_balance
        if effective_balance * MAX_RANDOM_BYTE >= max_effective_balance * random_byte:
            return candidate_index
        i += 1
示例#4
0
def _main():
    config_type = Minimal
    config = _load_config(config_type)
    override_lengths(config)

    key_set = load_yaml_at(KEY_DIR / KEY_SET_FILE)

    pubkeys = ()
    privkeys = ()
    withdrawal_credentials = ()
    keymap = {}
    for key_pair in key_set:
        pubkey = decode_hex(key_pair["pubkey"])
        privkey = int.from_bytes(decode_hex(key_pair["privkey"]), "big")
        withdrawal_credential = (
            config.BLS_WITHDRAWAL_PREFIX.to_bytes(1, byteorder="big") +
            hash_eth2(pubkey)[1:])

        pubkeys += (pubkey, )
        privkeys += (privkey, )
        withdrawal_credentials += (withdrawal_credential, )
        keymap[pubkey] = privkey

    deposits, _ = create_mock_deposits_and_root(pubkeys, keymap, config,
                                                withdrawal_credentials)

    eth1_block_hash = b"\x42" * 32
    # NOTE: this timestamp is a placeholder
    eth1_timestamp = 10000
    state = initialize_beacon_state_from_eth1(
        eth1_block_hash=eth1_block_hash,
        eth1_timestamp=eth1_timestamp,
        deposits=deposits,
        config=config,
    )

    genesis_time = int(time.time())
    print(f"creating genesis at time {genesis_time}")
    genesis_state = state.copy(genesis_time=genesis_time)
    print(genesis_state.hash_tree_root.hex())

    genesis_file_path = RESOURCE_DIR / GENESIS_FILE
    output_file = open(genesis_file_path, "wb")
    output_file.write(ssz.encode(genesis_state))
    output_file.close()
    print(f"genesis is saved in {genesis_file_path}")
示例#5
0
def test_get_seed(
    genesis_state,
    committee_config,
    slots_per_epoch,
    min_seed_lookahead,
    activation_exit_delay,
    epochs_per_historical_vector,
):
    def mock_get_randao_mix(state, epoch, epochs_per_historical_vector):
        return hash_eth2(
            state.hash_tree_root + epoch.to_bytes(32, byteorder="little") +
            epochs_per_historical_vector.to_bytes(32, byteorder="little"))

    def mock_get_active_index_root(state, epoch, epochs_per_historical_vector):
        return hash_eth2(
            state.hash_tree_root + epoch.to_bytes(32, byteorder="little") +
            slots_per_epoch.to_bytes(32, byteorder="little") +
            epochs_per_historical_vector.to_bytes(32, byteorder="little"))

    state = genesis_state
    epoch = 1
    state = state.copy(slot=compute_start_slot_of_epoch(
        epoch, committee_config.SLOTS_PER_EPOCH))

    epoch_as_bytes = epoch.to_bytes(32, "little")

    seed = _get_seed(
        state=state,
        epoch=epoch,
        randao_provider=mock_get_randao_mix,
        active_index_root_provider=mock_get_active_index_root,
        epoch_provider=lambda *_: epoch_as_bytes,
        committee_config=committee_config,
    )
    assert seed == hash_eth2(
        mock_get_randao_mix(
            state=state,
            epoch=(epoch + epochs_per_historical_vector - min_seed_lookahead -
                   1),
            epochs_per_historical_vector=epochs_per_historical_vector,
        ) + mock_get_active_index_root(
            state=state,
            epoch=epoch,
            epochs_per_historical_vector=epochs_per_historical_vector,
        ) + epoch_as_bytes)
示例#6
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)
示例#7
0
def verify_merkle_proof(root: Hash32, item: Union[bytes, bytearray],
                        item_index: int, proof: MerkleProof) -> bool:
    """
    Verify a Merkle proof against a root hash.
    """
    leaf = hash_eth2(item)
    branch_indices = get_branch_indices(item_index, len(proof))
    node_orderers = [
        identity if branch_index % 2 == 0 else reversed
        for branch_index in branch_indices
    ]
    proof_root = reduce(
        lambda n1, n2_and_order: _calc_parent_hash(*n2_and_order[1]
                                                   ([n1, n2_and_order[0]])),
        zip(proof, node_orderers),
        leaf,
    )
    return proof_root == root
示例#8
0
def _get_seed(state: 'BeaconState', epoch: Epoch,
              randao_provider: RandaoProvider,
              active_index_root_provider: ActiveIndexRootProvider,
              epoch_provider: Callable[[Epoch], Hash32],
              committee_config: CommitteeConfig) -> Hash32:
    randao_mix = randao_provider(
        state,
        Epoch(epoch + committee_config.EPOCHS_PER_HISTORICAL_VECTOR -
              committee_config.MIN_SEED_LOOKAHEAD - 1),
        committee_config.EPOCHS_PER_HISTORICAL_VECTOR,
    )
    active_index_root = active_index_root_provider(
        state,
        epoch,
        committee_config.EPOCHS_PER_HISTORICAL_VECTOR,
    )
    epoch_as_bytes = epoch_provider(epoch)

    return hash_eth2(randao_mix + active_index_root + epoch_as_bytes)
示例#9
0
def test_get_seed(
    genesis_state,
    config,
    slots_per_epoch,
    min_seed_lookahead,
    max_seed_lookahead,
    epochs_per_historical_vector,
):
    def mock_get_randao_mix(state, epoch, epochs_per_historical_vector):
        return hash_eth2(
            state.hash_tree_root
            + epoch.to_bytes(32, byteorder="little")
            + epochs_per_historical_vector.to_bytes(32, byteorder="little")
        )

    state = genesis_state
    epoch = 1
    state = state.set(
        "slot", compute_start_slot_at_epoch(epoch, config.SLOTS_PER_EPOCH)
    )

    epoch_as_bytes = epoch.to_bytes(32, "little")
    domain_type = signature_domain_to_domain_type(
        SignatureDomain.DOMAIN_BEACON_PROPOSER
    )
    seed = _get_seed(
        state=state,
        epoch=epoch,
        domain_type=domain_type,
        randao_provider=mock_get_randao_mix,
        epoch_provider=lambda *_: epoch_as_bytes,
        config=config,
    )
    assert seed == hash_eth2(
        domain_type
        + epoch_as_bytes
        + mock_get_randao_mix(
            state=state,
            epoch=(epoch + epochs_per_historical_vector - min_seed_lookahead - 1),
            epochs_per_historical_vector=epochs_per_historical_vector,
        )
    )
示例#10
0
def get_beacon_proposer_index(state: BeaconState,
                              config: Eth2Config) -> ValidatorIndex:
    """
    Return the current beacon proposer index.
    """
    current_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)
    domain_type = signature_domain_to_domain_type(
        SignatureDomain.DOMAIN_BEACON_PROPOSER)

    seed = hash_eth2(
        get_seed(state, current_epoch, domain_type, config) +
        state.slot.to_bytes(8, "little"))
    indices = get_active_validator_indices(state.validators, current_epoch)
    return compute_proposer_index(
        state.validators,
        indices,
        seed,
        config.MAX_EFFECTIVE_BALANCE,
        config.SHUFFLE_ROUND_COUNT,
    )
示例#11
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)
示例#12
0
def _main():
    config_type = Minimal
    config = _load_config(config_type)
    override_lengths(config)

    key_set = load_yaml_at(ROOT_DIR / KEY_SET_FILE)

    pubkeys = ()
    privkeys = ()
    withdrawal_credentials = ()
    keymap = {}
    for key_pair in key_set:
        pubkey = key_pair["pubkey"].to_bytes(48, byteorder="big")
        privkey = key_pair["privkey"]
        withdrawal_credential = (
            config.BLS_WITHDRAWAL_PREFIX.to_bytes(1, byteorder="big") +
            hash_eth2(pubkey)[1:])

        pubkeys += (pubkey, )
        privkeys += (privkey, )
        withdrawal_credentials += (withdrawal_credential, )
        keymap[pubkey] = privkey

    deposits, _ = create_mock_deposits_and_root(pubkeys, keymap, config,
                                                withdrawal_credentials)

    eth1_block_hash = b"\x42" * 32
    # NOTE: this timestamp is a placeholder
    eth1_timestamp = 10000
    state = initialize_beacon_state_from_eth1(
        eth1_block_hash=eth1_block_hash,
        eth1_timestamp=eth1_timestamp,
        deposits=deposits,
        config=config,
    )

    genesis_time = int(time.time())
    print(f"creating genesis at time {genesis_time}")
    genesis_state = state.copy(genesis_time=genesis_time)
    print(genesis_state.hash_tree_root.hex())
示例#13
0
def generate_seed(state: 'BeaconState', epoch: Epoch,
                  committee_config: CommitteeConfig) -> Hash32:
    """
    Generate a seed for the given ``epoch``.
    """
    randao_mix = get_randao_mix(
        state=state,
        epoch=Epoch(epoch - committee_config.MIN_SEED_LOOKAHEAD),
        slots_per_epoch=committee_config.SLOTS_PER_EPOCH,
        latest_randao_mixes_length=committee_config.LATEST_RANDAO_MIXES_LENGTH,
    )
    active_index_root = get_active_index_root(
        state=state,
        epoch=epoch,
        slots_per_epoch=committee_config.SLOTS_PER_EPOCH,
        activation_exit_delay=committee_config.ACTIVATION_EXIT_DELAY,
        latest_active_index_roots_length=committee_config.
        LATEST_ACTIVE_INDEX_ROOTS_LENGTH,
    )
    epoch_as_bytes = epoch.to_bytes(32, byteorder="little")

    return hash_eth2(randao_mix + active_index_root + epoch_as_bytes)
示例#14
0
def create_mock_genesis_validator_deposits_and_root(
        num_validators: int, config: Eth2Config, pubkeys: Sequence[BLSPubkey],
        keymap: Dict[BLSPubkey, int]) -> Tuple[Tuple[Deposit, ...], Hash32]:
    # Mock data
    withdrawal_credentials = Hash32(b'\x22' * 32)
    fork = Fork(
        previous_version=config.GENESIS_FORK_VERSION.to_bytes(4, 'little'),
        current_version=config.GENESIS_FORK_VERSION.to_bytes(4, 'little'),
        epoch=config.GENESIS_EPOCH,
    )

    deposit_data_array = tuple()  # type: Tuple[DepositData, ...]
    deposit_data_leaves = tuple()  # type: Tuple[Hash32, ...]

    for i in range(num_validators):
        deposit_data = create_mock_deposit_data(
            config=config,
            pubkeys=pubkeys,
            keymap=keymap,
            validator_index=ValidatorIndex(i),
            withdrawal_credentials=withdrawal_credentials,
            fork=fork,
        )
        item = hash_eth2(ssz.encode(deposit_data))
        deposit_data_leaves += (item, )
        deposit_data_array += (deposit_data, )

    tree = calc_merkle_tree_from_leaves(deposit_data_leaves)
    root = get_merkle_root(deposit_data_leaves)

    genesis_validator_deposits = tuple(
        Deposit(
            proof=get_merkle_proof(tree, item_index=i),
            index=i,
            deposit_data=deposit_data_array[i],
        ) for i in range(num_validators))

    return genesis_validator_deposits, root
示例#15
0
def create_mock_deposit(config, sample_beacon_state_params, keymap, pubkeys,
                        withdrawal_credentials, validator_index):
    state = BeaconState(**sample_beacon_state_params).copy(
        slot=1,
        validator_registry=(),
    )
    fork = Fork(
        previous_version=config.GENESIS_FORK_VERSION.to_bytes(4, 'little'),
        current_version=config.GENESIS_FORK_VERSION.to_bytes(4, 'little'),
        epoch=config.GENESIS_EPOCH,
    )
    deposit_data = create_mock_deposit_data(
        config=config,
        pubkeys=pubkeys,
        keymap=keymap,
        validator_index=validator_index,
        withdrawal_credentials=withdrawal_credentials,
        fork=fork,
    )

    item = hash_eth2(ssz.encode(deposit_data))
    test_deposit_data_leaves = (item, )
    tree = calc_merkle_tree_from_leaves(test_deposit_data_leaves)
    root = get_merkle_root(test_deposit_data_leaves)
    proof = list(get_merkle_proof(tree, item_index=validator_index))

    state = state.copy(latest_eth1_data=state.latest_eth1_data.copy(
        deposit_root=root, ), )

    deposit = Deposit(
        proof=proof,
        index=validator_index,
        deposit_data=deposit_data,
    )

    return state, deposit
示例#16
0
def _find_proposer_in_committee(
    validators: Sequence[Validator],
    committee: Sequence[ValidatorIndex],
    epoch: Epoch,
    seed: Hash32,
    max_effective_balance: Gwei,
) -> ValidatorIndex:
    """
    Loop through the validators in the committee one by one.
    A validator with higher balance would be chosen as the proposer more likely.
    It is expected to end in just 1 or 2 rounds.
    More than `MAX_ROUNDS` rounds is rare and could consider as a bug.

    Detail:
    The committee passed in here should consist 'active' validators.
    An active validator has a balance of at least 17 Ether and at most 32 Ether.
    This function choose a number between 0 and 1, which is represented by
    `random_byte / MAX_RANDOM_BYTE`. The probability of a validator chosen as
    a proposer is `effective_balance/max_effective_balance`.
    The worst/easiest possible scenario for the loop to reach more rounds is when every
    validator has 17 Ether and has the 17/32 probability of being chosen.
    This requires 1 out of (17/32)^100 chance to reach 100 rounds.
    """
    base = int(epoch)
    committee_len = len(committee)
    i = 0
    while i < MAX_ROUNDS:
        candidate_index = committee[(base + i) % committee_len]
        random_byte = hash_eth2(seed + (i // 32).to_bytes(8, "little"))[i % 32]
        effective_balance = validators[candidate_index].effective_balance
        if effective_balance * MAX_RANDOM_BYTE >= max_effective_balance * random_byte:
            return candidate_index
        i += 1
    else:
        raise ImprobableToReach(
            f"Search for a proposer failed after {MAX_ROUNDS} rounds.")
示例#17
0
 def mock_get_randao_mix(state, epoch, epochs_per_historical_vector):
     return hash_eth2(
         state.hash_tree_root
         + epoch.to_bytes(32, byteorder="little")
         + epochs_per_historical_vector.to_bytes(32, byteorder="little")
     )
示例#18
0
def test_chaindb_persist_block_and_unknown_parent(chaindb, block,
                                                  fork_choice_scoring, seed):
    n_block = block.transform(("message", "parent_root"), hash_eth2(seed))
    with pytest.raises(ParentNotFound):
        chaindb.persist_block(n_block, n_block.__class__, fork_choice_scoring)
示例#19
0
def calc_merkle_tree(items: Sequence[Union[bytes, bytearray]]) -> MerkleTree:
    """
    Calculate the Merkle tree corresponding to a list of items.
    """
    leaves = tuple(hash_eth2(item) for item in items)
    return calc_merkle_tree_from_leaves(leaves)
示例#20
0
def generate_privkey_from_index(index: int) -> int:
    return (int.from_bytes(hash_eth2(index.to_bytes(32, "little")), "little") %
            BLS12_381_CURVE_ORDER)
示例#21
0
def test_hash():
    output = hash_eth2(b'helloworld')
    assert len(output) == 32
示例#22
0
from eth2._utils.bls import bls
from eth2._utils.hash import hash_eth2
from eth2.beacon.chains.base import BaseBeaconChain
from eth2.beacon.chains.testnet import TestnetChain
from eth2.beacon.state_machines.forks.serenity.blocks import SerenityBeaconBlock
from eth2.beacon.state_machines.forks.xiao_long_bao.configs import XIAO_LONG_BAO_CONFIG
from eth2.beacon.tools.builder.initializer import create_mock_genesis
from eth2.beacon.tools.misc.ssz_vector import override_lengths
from eth2.beacon.typing import Timestamp
from eth2.configs import Eth2GenesisConfig

NUM_VALIDATORS = 8


privkeys = tuple(
    int.from_bytes(hash_eth2(str(i).encode("utf-8"))[:4], "big")
    for i in range(NUM_VALIDATORS)
)
index_to_pubkey = {}
keymap = {}  # pub -> priv
for i, k in enumerate(privkeys):
    pubkey = bls.privtopub(k)
    index_to_pubkey[i] = pubkey
    keymap[pubkey] = k

override_lengths(XIAO_LONG_BAO_CONFIG)

genesis_state, genesis_block = create_mock_genesis(
    config=XIAO_LONG_BAO_CONFIG,
    pubkeys=tuple(keymap.keys()),
    keymap=keymap,
示例#23
0
def mk_key_pair_from_seed_index(seed_index: int) -> Tuple[BLSPubkey, int]:
    privkey = int.from_bytes(
        hash_eth2(str(seed_index).encode("utf-8"))[:4], "big")
    pubkey = bls.privtopub(privkey)
    return (pubkey, privkey)
示例#24
0
from eth2._utils.hash import hash_eth2
from eth2._utils.merkle.normal import (
    calc_merkle_tree,
    get_merkle_proof,
    get_merkle_root,
    get_merkle_root_from_items,
    get_root,
    verify_merkle_proof,
)


@pytest.mark.parametrize(
    "leaves,tree",
    [
        ((b"single leaf", ), ((hash_eth2(b"single leaf"), ), )),
        (
            (b"left", b"right"),
            (
                (hash_eth2(hash_eth2(b"left") + hash_eth2(b"right")), ),
                (hash_eth2(b"left"), hash_eth2(b"right")),
            ),
        ),
        (
            (b"1", b"2", b"3", b"4"),
            (
                (hash_eth2(
                    hash_eth2(hash_eth2(b"1") + hash_eth2(b"2")) +
                    hash_eth2(hash_eth2(b"3") + hash_eth2(b"4"))), ),
                (
                    hash_eth2(hash_eth2(b"1") + hash_eth2(b"2")),
示例#25
0
文件: common.py 项目: wschwab/trinity
def _calc_parent_hash(left_node: Hash32, right_node: Hash32) -> Hash32:
    """
    Calculate the parent hash of a node and its sibling.
    """
    return hash_eth2(left_node + right_node)
示例#26
0
 def _get_privkey_for(self, index):
     # Want privkey an intger slightly less than the curve order
     privkey = int.from_bytes(hash_eth2(index.to_bytes(32, 'little')),
                              'little') % 2**254
     self.all_privkeys_by_index[index] = privkey
     return privkey
示例#27
0
def mk_withdrawal_credentials_from(prefix: bytes,
                                   public_key: BLSPubkey) -> Hash32:
    return Hash32(prefix + hash_eth2(public_key)[1:])
示例#28
0
def test_hash_is_keccak256():
    assert hash_eth2(b'foo') == keccak(b'foo')
示例#29
0
def test_chaindb_persist_block_and_unknown_parent(
    chaindb, block, fork_choice_scoring, seed
):
    n_block = block.copy(parent_root=hash_eth2(seed))
    with pytest.raises(ParentNotFound):
        chaindb.persist_block(n_block, n_block.__class__, fork_choice_scoring)
示例#30
0
def test_chaindb_persist_block_and_unknown_parent(chaindb, block, seed):
    n_block = block.copy(previous_block_root=hash_eth2(seed))
    with pytest.raises(ParentNotFound):
        chaindb.persist_block(n_block, n_block.__class__)