예제 #1
0
def compute_proposer_index(
    validators: Sequence[Validator],
    indices: Sequence[ValidatorIndex],
    seed: Hash32,
    max_effective_balance: Gwei,
    shuffle_round_count: int,
) -> ValidatorIndex:
    """
    Return from ``indices`` a random index sampled by effective balance.
    """
    if len(indices) == 0:
        raise ValidationError("There is no any active validator.")

    i = 0
    while True:
        candidate_index = indices[compute_shuffled_index(
            ValidatorIndex(i % len(indices)),
            len(indices),
            seed,
            shuffle_round_count,
        )]
        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 ValidatorIndex(candidate_index)

        # Log the warning message in case it happends.
        if i % len(indices) == 0 and i > 0:
            logger.warning(
                "Tried over %d times in compute_proposer_index while loop.", i)

        i += 1
예제 #2
0
 def get_validator_index_for_public_key(
         self, public_key: BLSPubkey) -> Optional[ValidatorIndex]:
     for index, validator in enumerate(self.validators):
         if validator.pubkey == public_key:
             return ValidatorIndex(index)
     else:
         return None
예제 #3
0
def _churn_validators(state: BeaconState, config: BeaconConfig,
                      check_should_churn_fn: Callable[..., Any],
                      churn_fn: Callable[..., Any],
                      max_balance_churn: int) -> BeaconState:
    """
    Churn the validators. The number of the churning validators is based on
    the given ``max_balance_churn``.

    :param check_should_churn_fn: the funcation to determine if the validator should be churn
    :param churn_fn``: the function to churn the validators; it could be ``activate_validator`` or
    ``exit_validator``
    """
    balance_churn = 0
    for index in range(len(state.validator_registry)):
        index = ValidatorIndex(index)
        should_churn = check_should_churn_fn(
            state,
            index,
        )
        if should_churn:
            # Check the balance churn would be within the allowance
            balance_churn += get_effective_balance(
                state.validator_balances,
                index,
                config.MAX_DEPOSIT_AMOUNT,
            )
            if balance_churn > max_balance_churn:
                break

            state = churn_fn(state, index)
    return state
예제 #4
0
def sample_pending_attestation_record_params(sample_attestation_data_params):
    return {
        "aggregation_bits": (True, False) * 4 * 16,
        "data": AttestationData.create(**sample_attestation_data_params),
        "inclusion_delay": 1,
        "proposer_index": ValidatorIndex(12),
    }
예제 #5
0
파일: conftest.py 프로젝트: s0b0lev/trinity
def sample_pending_attestation_record_params(sample_attestation_data_params):
    return {
        'aggregation_bits': (True, False) * 4 * 16,
        'data': AttestationData(**sample_attestation_data_params),
        'inclusion_delay': 1,
        'proposer_index': ValidatorIndex(12),
    }
예제 #6
0
def create_mock_slashable_attestation(
    state: BeaconState,
    config: Eth2Config,
    keymap: Dict[BLSPubkey, int],
    attestation_slot: Slot,
) -> IndexedAttestation:
    """
    Create an `IndexedAttestation` that is signed by one attester.
    """
    attester_index = ValidatorIndex(0)
    committee = (attester_index, )
    shard = Shard(0)

    # Use genesis block root as `beacon_block_root`, only for tests.
    beacon_block_root = get_block_root_at_slot(
        state, attestation_slot, config.SLOTS_PER_HISTORICAL_ROOT)

    # Get `target_root`
    target_root = _get_target_root(state, config, beacon_block_root)
    # Get `source_root`
    source_root = get_block_root_at_slot(
        state,
        compute_start_slot_of_epoch(state.current_justified_checkpoint.epoch,
                                    config.SLOTS_PER_EPOCH),
        config.SLOTS_PER_HISTORICAL_ROOT,
    )
    previous_crosslink = state.current_crosslinks[shard]

    attestation_data = AttestationData(
        beacon_block_root=beacon_block_root,
        source=Checkpoint(epoch=state.current_justified_checkpoint.epoch,
                          root=source_root),
        target=Checkpoint(
            epoch=compute_epoch_of_slot(attestation_slot,
                                        config.SLOTS_PER_EPOCH),
            root=target_root,
        ),
        crosslink=previous_crosslink,
    )

    message_hash = _get_mock_message(attestation_data)
    attesting_indices = _get_mock_attesting_indices(committee,
                                                    num_voted_attesters=1)

    signature = sign_transaction(
        message_hash=message_hash,
        privkey=keymap[state.validators[attesting_indices[0]].pubkey],
        state=state,
        slot=attestation_slot,
        signature_domain=SignatureDomain.DOMAIN_ATTESTATION,
        slots_per_epoch=config.SLOTS_PER_EPOCH,
    )
    validator_indices = tuple(committee[i] for i in attesting_indices)

    return IndexedAttestation(
        custody_bit_0_indices=validator_indices,
        custody_bit_1_indices=tuple(),
        data=attestation_data,
        signature=signature,
    )
예제 #7
0
def process_rewards_and_penalties(
    state: BeaconState, config: Eth2Config
) -> BeaconState:
    current_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)
    if current_epoch == config.GENESIS_EPOCH:
        return state

    rewards_for_attestations, penalties_for_attestations = get_attestation_deltas(
        state, config
    )
    rewards_for_crosslinks, penalties_for_crosslinks = get_crosslink_deltas(
        state, config
    )

    for index in range(len(state.validators)):
        index = ValidatorIndex(index)
        state = increase_balance(
            state,
            index,
            Gwei(rewards_for_attestations[index] + rewards_for_crosslinks[index]),
        )
        state = decrease_balance(
            state,
            index,
            Gwei(penalties_for_attestations[index] + penalties_for_crosslinks[index]),
        )

    return state
예제 #8
0
파일: helpers.py 프로젝트: onyb/trinity
def get_active_validator_indices(validators: Sequence[Validator],
                                 epoch: Epoch) -> Tuple[ValidatorIndex, ...]:
    """
    Get indices of active validators from ``validators``.
    """
    return tuple(
        ValidatorIndex(index) for index, validator in enumerate(validators)
        if validator.is_active(epoch))
예제 #9
0
def process_deposit(state: BeaconState, deposit: Deposit, slots_per_epoch: int,
                    deposit_contract_tree_depth: int) -> BeaconState:
    """
    Process a deposit from Ethereum 1.0.
    """
    validate_deposit(state, deposit, deposit_contract_tree_depth)

    # Increment the next deposit index we are expecting. Note that this
    # needs to be done here because while the deposit contract will never
    # create an invalid Merkle branch, it may admit an invalid deposit
    # object, and we need to be able to skip over it
    state = state.copy(deposit_index=state.deposit_index + 1, )

    validator_pubkeys = tuple(v.pubkey for v in state.validator_registry)
    deposit_input = deposit.deposit_data.deposit_input
    pubkey = deposit_input.pubkey
    amount = deposit.deposit_data.amount
    withdrawal_credentials = deposit_input.withdrawal_credentials

    if pubkey not in validator_pubkeys:
        # Verify the proof of possession
        proof_is_valid = bls.verify(
            pubkey=pubkey,
            message_hash=deposit_input.signing_root,
            signature=deposit_input.signature,
            domain=get_domain(
                state.fork,
                state.current_epoch(slots_per_epoch),
                SignatureDomain.DOMAIN_DEPOSIT,
            ),
        )
        if not proof_is_valid:
            return state

        validator = Validator.create_pending_validator(
            pubkey=pubkey,
            withdrawal_credentials=withdrawal_credentials,
        )

        # Note: In phase 2 registry indices that has been withdrawn for a long time
        # will be recycled.
        state = add_pending_validator(
            state,
            validator,
            amount,
        )
    else:
        # Top-up - increase balance by deposit
        index = ValidatorIndex(validator_pubkeys.index(pubkey))
        validator = state.validator_registry[index]

        # Update validator's balance and state
        state = state.update_validator_balance(
            validator_index=index,
            balance=state.validator_balances[index] + amount,
        )

    return state
예제 #10
0
파일: helpers.py 프로젝트: Agreene/trinity
def get_active_validator_indices(
        validators: Sequence['ValidatorRecord'],
        slot: SlotNumber) -> Tuple[ValidatorIndex, ...]:
    """
    Get indices of active validators from ``validators``.
    """
    return tuple(
        ValidatorIndex(index) for index, validator in enumerate(validators)
        if validator.is_active(slot))
예제 #11
0
def _process_rewards_and_penalties_for_crosslinks(
    state: BeaconState, config: Eth2Config,
    effective_balances: Dict[ValidatorIndex,
                             Gwei], base_rewards: Dict[ValidatorIndex, Gwei]
) -> Tuple[Dict[ValidatorIndex, Gwei], Dict[ValidatorIndex,
                                            Gwei]]:  # noqa: E501
    previous_epoch_start_slot = get_epoch_start_slot(
        state.previous_epoch(config.SLOTS_PER_EPOCH),
        config.SLOTS_PER_EPOCH,
    )
    current_epoch_start_slot = get_epoch_start_slot(
        state.current_epoch(config.SLOTS_PER_EPOCH),
        config.SLOTS_PER_EPOCH,
    )
    rewards_received = {
        ValidatorIndex(index): Gwei(0)
        for index in range(len(state.validator_registry))
    }
    penalties_received = rewards_received.copy()
    for slot in range(previous_epoch_start_slot, current_epoch_start_slot):
        crosslink_committees_at_slot = get_crosslink_committees_at_slot(
            state,
            slot,
            CommitteeConfig(config),
        )
        for crosslink_committee, shard in crosslink_committees_at_slot:
            winning_root, attesting_validator_indices = get_winning_root_and_participants(
                state=state,
                shard=shard,
                effective_balances=effective_balances,
                committee_config=CommitteeConfig(config),
            )
            total_attesting_balance = get_total_balance(
                state.validator_balances,
                attesting_validator_indices,
                config.MAX_DEPOSIT_AMOUNT,
            )
            total_balance = get_total_balance_from_effective_balances(
                effective_balances,
                crosslink_committee,
            )
            for index in attesting_validator_indices:
                rewards_received = _update_rewards_or_penalies(
                    index,
                    base_rewards[index] * total_attesting_balance //
                    total_balance,
                    rewards_received,
                )
            for index in set(crosslink_committee).difference(
                    attesting_validator_indices):
                penalties_received = _update_rewards_or_penalies(
                    index,
                    base_rewards[index],
                    penalties_received,
                )
    return (rewards_received, penalties_received)
예제 #12
0
def process_deposit(state: BeaconState,
                    deposit: Deposit,
                    config: Eth2Config) -> BeaconState:
    """
    Process a deposit from Ethereum 1.0.
    """
    validate_deposit_proof(state, deposit, DEPOSIT_CONTRACT_TREE_DEPTH)

    # Increment the next deposit index we are expecting. Note that this
    # needs to be done here because while the deposit contract will never
    # create an invalid Merkle branch, it may admit an invalid deposit
    # object, and we need to be able to skip over it
    state = state.copy(
        eth1_deposit_index=state.eth1_deposit_index + 1,
    )

    pubkey = deposit.data.pubkey
    amount = deposit.data.amount
    validator_pubkeys = tuple(v.pubkey for v in state.validators)
    if pubkey not in validator_pubkeys:
        # Verify the deposit signature (proof of possession) for new validators.
        # Note: The deposit contract does not check signatures.
        # Note: Deposits are valid across forks, thus the deposit domain
        # is retrieved directly from `compute_domain`.
        is_valid_proof_of_possession = bls.verify(
            message_hash=deposit.data.signing_root,
            pubkey=pubkey,
            signature=deposit.data.signature,
            domain=compute_domain(
                SignatureDomain.DOMAIN_DEPOSIT,
            ),
        )
        if not is_valid_proof_of_possession:
            return state

        withdrawal_credentials = deposit.data.withdrawal_credentials
        validator = Validator.create_pending_validator(
            pubkey,
            withdrawal_credentials,
            amount,
            config,
        )

        return state.copy(
            validators=state.validators + (validator,),
            balances=state.balances + (amount, ),
        )
    else:
        index = ValidatorIndex(validator_pubkeys.index(pubkey))
        return increase_balance(
            state,
            index,
            amount,
        )
예제 #13
0
def process_deposit(*, state: BeaconState, pubkey: BLSPubkey, amount: Gwei,
                    proof_of_possession: BLSSignature,
                    withdrawal_credentials: Hash32, randao_commitment: Hash32,
                    custody_commitment: Hash32,
                    epoch_length: int) -> BeaconState:
    """
    Process a deposit from Ethereum 1.0.
    """
    validate_proof_of_possession(
        state=state,
        pubkey=pubkey,
        proof_of_possession=proof_of_possession,
        withdrawal_credentials=withdrawal_credentials,
        randao_commitment=randao_commitment,
        custody_commitment=custody_commitment,
        epoch_length=epoch_length,
    )

    validator_pubkeys = tuple(v.pubkey for v in state.validator_registry)
    if pubkey not in validator_pubkeys:
        validator = ValidatorRecord.create_pending_validator(
            pubkey=pubkey,
            withdrawal_credentials=withdrawal_credentials,
            randao_commitment=randao_commitment,
            custody_commitment=custody_commitment,
        )

        # Note: In phase 2 registry indices that has been withdrawn for a long time
        # will be recycled.
        state = add_pending_validator(
            state,
            validator,
            amount,
        )
    else:
        # Top-up - increase balance by deposit
        index = ValidatorIndex(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
        state = state.update_validator_balance(
            validator_index=index,
            balance=state.validator_balances[index] + amount,
        )

    return state
예제 #14
0
def initialize_beacon_state_from_eth1(*, eth1_block_hash: Hash32,
                                      eth1_timestamp: Timestamp,
                                      deposits: Sequence[Deposit],
                                      config: Eth2Config) -> BeaconState:
    fork = Fork.create(
        previous_version=config.GENESIS_FORK_VERSION,
        current_version=config.GENESIS_FORK_VERSION,
        epoch=GENESIS_EPOCH,
    )

    state = BeaconState.create(
        genesis_time=_genesis_time_from_eth1_timestamp(eth1_timestamp,
                                                       config.GENESIS_DELAY),
        fork=fork,
        eth1_data=Eth1Data.create(block_hash=eth1_block_hash,
                                  deposit_count=len(deposits)),
        latest_block_header=BeaconBlockHeader.create(
            body_root=BeaconBlockBody.create().hash_tree_root),
        block_roots=(ZERO_ROOT, ) * config.SLOTS_PER_HISTORICAL_ROOT,
        state_roots=(ZERO_HASH32, ) * config.SLOTS_PER_HISTORICAL_ROOT,
        randao_mixes=(eth1_block_hash, ) * config.EPOCHS_PER_HISTORICAL_VECTOR,
        slashings=(Gwei(0), ) * config.EPOCHS_PER_SLASHINGS_VECTOR,
        config=config,
    )

    # Process genesis deposits
    for index, deposit in enumerate(deposits):
        deposit_data_list = tuple(deposit.data
                                  for deposit in deposits[:index + 1])
        deposit_root = ssz.get_hash_tree_root(
            deposit_data_list,
            ssz.List(DepositData, 2**DEPOSIT_CONTRACT_TREE_DEPTH))
        state = state.transform(("eth1_data", "deposit_root"), deposit_root)
        state = process_deposit(state=state, deposit=deposit, config=config)

    # Process genesis activations
    for validator_index in range(len(state.validators)):
        validator_index = ValidatorIndex(validator_index)
        balance = state.balances[validator_index]
        effective_balance = calculate_effective_balance(balance, config)

        state = state.transform(
            ("validators", validator_index, "effective_balance"),
            effective_balance)

        if effective_balance == config.MAX_EFFECTIVE_BALANCE:
            activated_validator = activate_validator(
                state.validators[validator_index], GENESIS_EPOCH)
            state = state.transform(("validators", validator_index),
                                    activated_validator)

    return state.set("genesis_validators_root",
                     state.validators.hash_tree_root)
예제 #15
0
def process_exit_queue(state: BeaconState,
                       config: BeaconConfig) -> BeaconState:
    """
    Process the exit queue.
    """
    def eligible(index: ValidatorIndex) -> bool:
        validator = state.validator_registry[index]
        # Filter out dequeued validators
        if validator.withdrawable_epoch != FAR_FUTURE_EPOCH:
            return False
        # Dequeue if the minimum amount of time has passed
        else:
            return (state.current_epoch(
                config.SLOTS_PER_EPOCH) >= validator.exit_epoch +
                    config.MIN_VALIDATOR_WITHDRAWABILITY_DELAY)

    eligible_indices = filter(
        eligible,
        tuple(
            [ValidatorIndex(i) for i in range(len(state.validator_registry))]))
    # Sort in order of exit epoch, and validators that exit within the same epoch exit
    # in order of validator index
    sorted_indices = sorted(
        eligible_indices,
        key=lambda index: state.validator_registry[index].exit_epoch,
    )
    for dequeues, index in enumerate(sorted_indices):
        if dequeues >= config.MAX_EXIT_DEQUEUES_PER_EPOCH:
            break
        state = prepare_validator_for_withdrawal(
            state,
            ValidatorIndex(index),
            slots_per_epoch=config.SLOTS_PER_EPOCH,
            min_validator_withdrawability_delay=config.
            MIN_VALIDATOR_WITHDRAWABILITY_DELAY,
        )

    return state
예제 #16
0
def process_slashings(state: BeaconState, config: Eth2Config) -> BeaconState:
    current_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)
    total_balance = get_total_active_balance(state, config)

    slashing_period = config.EPOCHS_PER_SLASHINGS_VECTOR // 2
    for index, validator in enumerate(state.validators):
        index = ValidatorIndex(index)
        if validator.slashed and current_epoch + slashing_period == validator.withdrawable_epoch:
            penalty = _determine_slashing_penalty(
                Gwei(sum(state.slashings)),
                total_balance,
                validator.effective_balance,
                config.EFFECTIVE_BALANCE_INCREMENT,
            )
            state = decrease_balance(state, index, penalty)
    return state
예제 #17
0
def _get_mock_message_and_attesting_indices(
        attestation_data: AttestationData, committee: Sequence[ValidatorIndex],
        num_voted_attesters: int) -> Tuple[Hash32, Tuple[ValidatorIndex, ...]]:
    """
    Get ``message_hash`` and voting indices of the given ``committee``.
    """
    message_hash = AttestationDataAndCustodyBit(data=attestation_data,
                                                custody_bit=False).root

    committee_size = len(committee)
    assert num_voted_attesters <= committee_size

    # Index in committee
    attesting_indices = tuple(
        ValidatorIndex(i)
        for i in random.sample(range(committee_size), num_voted_attesters))

    return message_hash, tuple(sorted(attesting_indices))
예제 #18
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
예제 #19
0
def initialize_beacon_state_from_eth1(*, eth1_block_hash: Hash32,
                                      eth1_timestamp: Timestamp,
                                      deposits: Sequence[Deposit],
                                      config: Eth2Config) -> BeaconState:
    state = BeaconState(
        genesis_time=_genesis_time_from_eth1_timestamp(eth1_timestamp),
        eth1_data=Eth1Data(block_hash=eth1_block_hash,
                           deposit_count=len(deposits)),
        latest_block_header=BeaconBlockHeader(
            body_root=BeaconBlockBody().hash_tree_root),
        randao_mixes=(eth1_block_hash, ) * config.EPOCHS_PER_HISTORICAL_VECTOR,
        config=config,
    )

    # Process genesis deposits
    for index, deposit in enumerate(deposits):
        deposit_data_list = tuple(deposit.data
                                  for deposit in deposits[:index + 1])
        state = state.copy(eth1_data=state.eth1_data.copy(
            deposit_root=ssz.get_hash_tree_root(
                deposit_data_list,
                ssz.List(DepositData, 2**DEPOSIT_CONTRACT_TREE_DEPTH),
            )))
        state = process_deposit(state=state, deposit=deposit, config=config)

    # Process genesis activations
    for validator_index in range(len(state.validators)):
        validator_index = ValidatorIndex(validator_index)
        balance = state.balances[validator_index]
        effective_balance = calculate_effective_balance(balance, config)

        state = state.update_validator_with_fn(
            validator_index,
            lambda v, *_: v.copy(effective_balance=effective_balance))

        if effective_balance == config.MAX_EFFECTIVE_BALANCE:
            state = state.update_validator_with_fn(validator_index,
                                                   activate_validator,
                                                   config.GENESIS_EPOCH)

    return state
예제 #20
0
def process_slashings(state: BeaconState, config: BeaconConfig) -> BeaconState:
    """
    Process the slashings.
    """
    latest_slashed_exit_length = config.LATEST_SLASHED_EXIT_LENGTH
    max_deposit_amount = config.MAX_DEPOSIT_AMOUNT

    current_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)
    active_validator_indices = get_active_validator_indices(
        state.validator_registry, current_epoch)
    total_balance = Gwei(
        sum(
            get_effective_balance(state.validator_balances, i,
                                  max_deposit_amount)
            for i in active_validator_indices))
    total_penalties = _compute_total_penalties(
        state,
        config,
        current_epoch,
    )

    for validator_index, validator in enumerate(state.validator_registry):
        validator_index = ValidatorIndex(validator_index)
        is_halfway_to_withdrawable_epoch = (
            current_epoch == validator.withdrawable_epoch -
            latest_slashed_exit_length // 2)
        if validator.slashed and is_halfway_to_withdrawable_epoch:
            penalty = _compute_individual_penalty(
                state=state,
                config=config,
                validator_index=validator_index,
                total_penalties=total_penalties,
                total_balance=total_balance,
            )
            state = state.update_validator_balance(
                validator_index=validator_index,
                balance=state.validator_balances[validator_index] - penalty,
            )
    return state
예제 #21
0
def get_genesis_beacon_state(*,
                             genesis_deposits: Sequence[Deposit],
                             genesis_time: Timestamp,
                             genesis_eth1_data: Eth1Data,
                             config: Eth2Config) -> BeaconState:
    state = BeaconState(
        genesis_time=genesis_time,
        eth1_data=genesis_eth1_data,
        latest_block_header=BeaconBlockHeader(
            body_root=BeaconBlockBody().root,
        ),
        config=config,
    )

    # Process genesis deposits
    for deposit in genesis_deposits:
        state = process_deposit(
            state=state,
            deposit=deposit,
            config=config,
        )

    # Process genesis activations
    for validator_index in range(len(state.validators)):
        validator_index = ValidatorIndex(validator_index)
        effective_balance = state.validators[validator_index].effective_balance
        is_enough_effective_balance = effective_balance >= config.MAX_EFFECTIVE_BALANCE
        if is_enough_effective_balance:
            state = state.update_validator_with_fn(
                validator_index,
                activate_validator,
                config.GENESIS_EPOCH,
            )

    return genesis_state_with_active_index_roots(
        state,
        config,
    )
예제 #22
0
def process_slashings(state: BeaconState, config: Eth2Config) -> BeaconState:
    current_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)
    total_balance = get_total_active_balance(state, config)

    start_index = (current_epoch + 1) % config.EPOCHS_PER_SLASHED_BALANCES_VECTOR
    total_at_start = state.slashed_balances[start_index]

    end_index = current_epoch % config.EPOCHS_PER_SLASHED_BALANCES_VECTOR
    total_at_end = state.slashed_balances[end_index]

    total_penalties = total_at_end - total_at_start

    slashing_period = config.EPOCHS_PER_SLASHED_BALANCES_VECTOR // 2
    for index, validator in enumerate(state.validators):
        index = ValidatorIndex(index)
        if validator.slashed and current_epoch == validator.withdrawable_epoch - slashing_period:
            penalty = _determine_slashing_penalty(
                total_penalties,
                total_balance,
                validator.effective_balance,
                config.MIN_SLASHING_PENALTY_QUOTIENT,
            )
            state = decrease_balance(state, index, penalty)
    return state
예제 #23
0
def get_initial_beacon_state(*, initial_validator_deposits: Sequence[Deposit],
                             genesis_time: Timestamp,
                             latest_eth1_data: Eth1Data,
                             genesis_slot: SlotNumber,
                             genesis_fork_version: int,
                             genesis_start_shard: ShardNumber,
                             shard_count: int, latest_block_roots_length: int,
                             epoch_length: int, target_committee_size: int,
                             max_deposit: Ether,
                             latest_penalized_exit_length: int,
                             latest_randao_mixes_length: int,
                             entry_exit_delay: int) -> BeaconState:
    state = BeaconState(
        # Misc
        slot=genesis_slot,
        genesis_time=genesis_time,
        fork=Fork(
            previous_version=genesis_fork_version,
            current_version=genesis_fork_version,
            slot=genesis_slot,
        ),

        # Validator registry
        validator_registry=(),
        validator_balances=(),
        validator_registry_update_slot=genesis_slot,
        validator_registry_exit_count=0,
        validator_registry_delta_chain_tip=ZERO_HASH32,

        # Randomness and committees
        latest_randao_mixes=tuple(ZERO_HASH32
                                  for _ in range(latest_randao_mixes_length)),
        latest_vdf_outputs=tuple(ZERO_HASH32
                                 for _ in range(latest_randao_mixes_length //
                                                epoch_length)),
        # TODO Remove `persistent_committees`, `persistent_committee_reassignments`
        persistent_committees=(),
        persistent_committee_reassignments=(),
        previous_epoch_start_shard=genesis_start_shard,
        current_epoch_start_shard=genesis_start_shard,
        previous_epoch_calculation_slot=genesis_slot,
        current_epoch_calculation_slot=genesis_slot,
        previous_epoch_randao_mix=ZERO_HASH32,
        current_epoch_randao_mix=ZERO_HASH32,

        # Custody challenges
        custody_challenges=(),

        # Finality
        previous_justified_slot=genesis_slot,
        justified_slot=genesis_slot,
        justification_bitfield=0,
        finalized_slot=genesis_slot,

        # Recent state
        latest_crosslinks=tuple([
            CrosslinkRecord(slot=genesis_slot, shard_block_root=ZERO_HASH32)
            for _ in range(shard_count)
        ]),
        latest_block_roots=tuple(ZERO_HASH32
                                 for _ in range(latest_block_roots_length)),
        latest_penalized_balances=tuple(
            Gwei(0) for _ in range(latest_penalized_exit_length)),
        latest_attestations=(),
        batched_block_roots=(),

        # Ethereum 1.0 chain data
        latest_eth1_data=latest_eth1_data,
        eth1_data_votes=(),
    )

    # Process initial deposits
    for deposit in initial_validator_deposits:
        state = process_deposit(
            state=state,
            pubkey=deposit.deposit_data.deposit_input.pubkey,
            amount=deposit.deposit_data.amount,
            proof_of_possession=deposit.deposit_data.deposit_input.
            proof_of_possession,
            withdrawal_credentials=deposit.deposit_data.deposit_input.
            withdrawal_credentials,
            randao_commitment=deposit.deposit_data.deposit_input.
            randao_commitment,
            custody_commitment=deposit.deposit_data.deposit_input.
            custody_commitment,
        )

    for validator_index, _ in enumerate(state.validator_registry):
        validator_index = ValidatorIndex(validator_index)
        is_enough_effective_balance = get_effective_balance(
            state.validator_balances,
            validator_index,
            max_deposit,
        ) >= max_deposit * GWEI_PER_ETH
        if is_enough_effective_balance:
            state = activate_validator(
                state,
                validator_index,
                genesis=True,
                genesis_slot=genesis_slot,
                entry_exit_delay=entry_exit_delay,
            )

    return state
예제 #24
0
def get_genesis_beacon_state(
        *, genesis_validator_deposits: Sequence[Deposit],
        genesis_time: Timestamp, genesis_eth1_data: Eth1Data,
        genesis_slot: Slot, genesis_epoch: Epoch, genesis_fork_version: int,
        genesis_start_shard: Shard, shard_count: int, min_seed_lookahead: int,
        slots_per_historical_root: int, latest_active_index_roots_length: int,
        slots_per_epoch: int, max_deposit_amount: Gwei,
        latest_slashed_exit_length: int, latest_randao_mixes_length: int,
        activation_exit_delay: int, deposit_contract_tree_depth: int,
        block_class: Type[BaseBeaconBlock]) -> BeaconState:
    state = BeaconState(
        # Misc
        slot=genesis_slot,
        genesis_time=genesis_time,
        fork=Fork(
            previous_version=genesis_fork_version.to_bytes(4, 'little'),
            current_version=genesis_fork_version.to_bytes(4, 'little'),
            epoch=genesis_epoch,
        ),

        # Validator registry
        validator_registry=(),
        validator_balances=(),
        validator_registry_update_epoch=genesis_epoch,

        # Randomness and committees
        latest_randao_mixes=(ZERO_HASH32, ) * latest_randao_mixes_length,
        previous_shuffling_start_shard=genesis_start_shard,
        current_shuffling_start_shard=genesis_start_shard,
        previous_shuffling_epoch=genesis_epoch,
        current_shuffling_epoch=genesis_epoch,
        previous_shuffling_seed=ZERO_HASH32,
        current_shuffling_seed=ZERO_HASH32,

        # Finality
        previous_epoch_attestations=(),
        current_epoch_attestations=(),
        previous_justified_epoch=genesis_epoch,
        current_justified_epoch=genesis_epoch,
        previous_justified_root=ZERO_HASH32,
        current_justified_root=ZERO_HASH32,
        justification_bitfield=0,
        finalized_epoch=genesis_epoch,
        finalized_root=ZERO_HASH32,

        # Recent state
        latest_crosslinks=((CrosslinkRecord(
            epoch=genesis_epoch, crosslink_data_root=ZERO_HASH32), ) *
                           shard_count),
        latest_block_roots=(ZERO_HASH32, ) * slots_per_historical_root,
        latest_state_roots=(ZERO_HASH32, ) * slots_per_historical_root,
        latest_active_index_roots=(ZERO_HASH32, ) *
        latest_active_index_roots_length,
        latest_slashed_balances=(Gwei(0), ) * latest_slashed_exit_length,
        latest_block_header=get_temporary_block_header(
            BeaconBlock.create_empty_block(genesis_slot), ),
        historical_roots=(),

        # Ethereum 1.0 chain data
        latest_eth1_data=genesis_eth1_data,
        eth1_data_votes=(),
        deposit_index=0,
    )

    # Process genesis deposits
    for deposit in genesis_validator_deposits:
        state = process_deposit(
            state=state,
            deposit=deposit,
            slots_per_epoch=slots_per_epoch,
            deposit_contract_tree_depth=deposit_contract_tree_depth,
        )

    # Process genesis activations
    for validator_index, _ in enumerate(state.validator_registry):
        validator_index = ValidatorIndex(validator_index)
        is_enough_effective_balance = get_effective_balance(
            state.validator_balances,
            validator_index,
            max_deposit_amount,
        ) >= max_deposit_amount
        if is_enough_effective_balance:
            state = activate_validator(
                state=state,
                index=validator_index,
                is_genesis=True,
                genesis_epoch=genesis_epoch,
                slots_per_epoch=slots_per_epoch,
                activation_exit_delay=activation_exit_delay,
            )

    # TODO: chanege to hash_tree_root
    active_validator_indices = get_active_validator_indices(
        state.validator_registry,
        genesis_epoch,
    )
    genesis_active_index_root = hash_eth2(b''.join(
        [index.to_bytes(32, 'little') for index in active_validator_indices]))
    latest_active_index_roots = (
        genesis_active_index_root, ) * latest_active_index_roots_length
    state = state.copy(latest_active_index_roots=latest_active_index_roots, )

    current_shuffling_seed = generate_seed(
        state=state,
        epoch=genesis_epoch,
        slots_per_epoch=slots_per_epoch,
        min_seed_lookahead=min_seed_lookahead,
        activation_exit_delay=activation_exit_delay,
        latest_active_index_roots_length=latest_active_index_roots_length,
        latest_randao_mixes_length=latest_randao_mixes_length,
    )
    state = state.copy(current_shuffling_seed=current_shuffling_seed, )

    return state
예제 #25
0
def get_genesis_beacon_state(*,
                             genesis_validator_deposits: Sequence[Deposit],
                             genesis_time: Timestamp,
                             latest_eth1_data: Eth1Data,
                             genesis_slot: SlotNumber,
                             genesis_epoch: EpochNumber,
                             genesis_fork_version: int,
                             genesis_start_shard: ShardNumber,
                             shard_count: int,
                             seed_lookahead: int,
                             latest_block_roots_length: int,
                             latest_index_roots_length: int,
                             epoch_length: int,
                             max_deposit_amount: Gwei,
                             latest_penalized_exit_length: int,
                             latest_randao_mixes_length: int,
                             entry_exit_delay: int) -> BeaconState:
    state = BeaconState(
        # Misc
        slot=genesis_slot,
        genesis_time=genesis_time,
        fork=Fork(
            previous_version=genesis_fork_version,
            current_version=genesis_fork_version,
            epoch=genesis_epoch,
        ),

        # Validator registry
        validator_registry=(),
        validator_balances=(),
        validator_registry_update_epoch=genesis_epoch,

        # Randomness and committees
        latest_randao_mixes=(ZERO_HASH32,) * latest_randao_mixes_length,
        previous_epoch_start_shard=genesis_start_shard,
        current_epoch_start_shard=genesis_start_shard,
        previous_calculation_epoch=genesis_epoch,
        current_calculation_epoch=genesis_epoch,
        previous_epoch_seed=ZERO_HASH32,
        current_epoch_seed=ZERO_HASH32,

        # Finality
        previous_justified_epoch=genesis_epoch,
        justified_epoch=genesis_epoch,
        justification_bitfield=0,
        finalized_epoch=genesis_epoch,

        # Recent state
        latest_crosslinks=(
            (CrosslinkRecord(epoch=genesis_epoch, shard_block_root=ZERO_HASH32),) * shard_count
        ),
        latest_block_roots=(ZERO_HASH32,) * latest_block_roots_length,
        latest_index_roots=(ZERO_HASH32,) * latest_index_roots_length,
        latest_penalized_balances=(Gwei(0),) * latest_penalized_exit_length,
        latest_attestations=(),
        batched_block_roots=(),

        # Ethereum 1.0 chain data
        latest_eth1_data=latest_eth1_data,
        eth1_data_votes=(),
        deposit_index=len(genesis_validator_deposits),
    )

    # Process initial deposits
    for deposit in genesis_validator_deposits:
        state = process_deposit(
            state=state,
            pubkey=deposit.deposit_data.deposit_input.pubkey,
            amount=deposit.deposit_data.amount,
            proof_of_possession=deposit.deposit_data.deposit_input.proof_of_possession,
            withdrawal_credentials=deposit.deposit_data.deposit_input.withdrawal_credentials,
            epoch_length=epoch_length,
        )

    # Process initial activations
    for validator_index, _ in enumerate(state.validator_registry):
        validator_index = ValidatorIndex(validator_index)
        is_enough_effective_balance = get_effective_balance(
            state.validator_balances,
            validator_index,
            max_deposit_amount,
        ) >= max_deposit_amount
        if is_enough_effective_balance:
            state = activate_validator(
                state=state,
                index=validator_index,
                is_genesis=True,
                genesis_epoch=genesis_epoch,
                epoch_length=epoch_length,
                entry_exit_delay=entry_exit_delay,
            )

    # TODO: chanege to hash_tree_root
    active_validator_indices = get_active_validator_indices(
        state.validator_registry,
        genesis_epoch,
    )
    genesis_active_index_root = hash_eth2(
        b''.join(
            [
                index.to_bytes(32, 'big')
                for index in active_validator_indices
            ]
        )
    )
    latest_index_roots = (genesis_active_index_root,) * latest_index_roots_length
    state = state.copy(
        latest_index_roots=latest_index_roots,
    )

    current_epoch_seed = generate_seed(
        state=state,
        epoch=genesis_epoch,
        epoch_length=epoch_length,
        seed_lookahead=seed_lookahead,
        entry_exit_delay=entry_exit_delay,
        latest_index_roots_length=latest_index_roots_length,
        latest_randao_mixes_length=latest_randao_mixes_length,
    )
    state = state.copy(
        current_epoch_seed=current_epoch_seed,
    )

    return state
예제 #26
0
파일: validator.py 프로젝트: mhchia/trinity
def create_mock_slashable_attestation(
        state: BeaconState, config: Eth2Config, keymap: Dict[BLSPubkey, int],
        attestation_slot: Slot) -> SlashableAttestation:
    """
    Create `SlashableAttestation` that is signed by one attester.
    """
    attester_index = ValidatorIndex(0)
    committee = (attester_index, )
    shard = Shard(0)

    # Use genesis block root as `beacon_block_root`, only for tests.
    beacon_block_root = get_block_root(
        state,
        config.GENESIS_SLOT,
        config.SLOTS_PER_HISTORICAL_ROOT,
    )

    # Get `target_root`
    target_root = _get_target_root(state, config, beacon_block_root)
    # Get `source_root`
    source_root = get_block_root(
        state,
        get_epoch_start_slot(state.current_justified_epoch,
                             config.SLOTS_PER_EPOCH),
        config.SLOTS_PER_HISTORICAL_ROOT,
    )
    previous_crosslink = state.latest_crosslinks[shard]

    attestation_data = AttestationData(
        slot=attestation_slot,
        beacon_block_root=beacon_block_root,
        source_epoch=state.current_justified_epoch,
        source_root=source_root,
        target_root=target_root,
        shard=shard,
        previous_crosslink=previous_crosslink,
        crosslink_data_root=ZERO_HASH32,
    )

    message_hash, voting_committee_indices = _get_mock_message_and_voting_committee_indices(
        attestation_data,
        committee,
        num_voted_attesters=1,
    )

    signature = sign_transaction(
        message_hash=message_hash,
        privkey=keymap[state.validator_registry[
            voting_committee_indices[0]].pubkey],
        fork=state.fork,
        slot=attestation_slot,
        signature_domain=SignatureDomain.DOMAIN_ATTESTATION,
        slots_per_epoch=config.SLOTS_PER_EPOCH,
    )
    validator_indices = tuple(committee[i] for i in voting_committee_indices)

    return SlashableAttestation(
        validator_indices=sorted(validator_indices),
        data=attestation_data,
        custody_bitfield=get_empty_bitfield(len(voting_committee_indices)),
        aggregate_signature=signature,
    )
예제 #27
0
def get_attestation_deltas(
        state: BeaconState,
        config: Eth2Config) -> Tuple[Sequence[Gwei], Sequence[Gwei]]:
    rewards = tuple(0 for _ in range(len(state.validators)))
    penalties = tuple(0 for _ in range(len(state.validators)))
    previous_epoch = state.previous_epoch(config.SLOTS_PER_EPOCH)
    total_balance = get_total_active_balance(state, config)
    eligible_validator_indices = tuple(
        ValidatorIndex(index) for index, v in enumerate(state.validators)
        if v.is_active(previous_epoch) or (
            v.slashed and previous_epoch + 1 < v.withdrawable_epoch))

    matching_source_attestations = get_matching_source_attestations(
        state, previous_epoch, config)
    matching_target_attestations = get_matching_target_attestations(
        state, previous_epoch, config)
    matching_head_attestations = get_matching_head_attestations(
        state, previous_epoch, config)

    increment = config.EFFECTIVE_BALANCE_INCREMENT
    total_balance_in_increment = total_balance // increment
    for attestations in (
            matching_source_attestations,
            matching_target_attestations,
            matching_head_attestations,
    ):
        unslashed_attesting_indices = get_unslashed_attesting_indices(
            state, attestations, config)
        attesting_balance = get_total_balance(state,
                                              unslashed_attesting_indices,
                                              config)
        attesting_balance_in_increment = attesting_balance // increment
        for index in eligible_validator_indices:
            if index in unslashed_attesting_indices:
                if is_in_inactivity_leak(state, config):
                    reward = get_base_reward(state, index, config)
                else:
                    reward = Gwei((get_base_reward(state, index, config) *
                                   attesting_balance_in_increment) //
                                  total_balance_in_increment)
                rewards = update_tuple_item_with_fn(
                    rewards, index, lambda balance, delta: balance + delta,
                    reward)
            else:
                penalties = update_tuple_item_with_fn(
                    penalties,
                    index,
                    lambda balance, delta: balance + delta,
                    get_base_reward(state, index, config),
                )

    for index in get_unslashed_attesting_indices(state,
                                                 matching_source_attestations,
                                                 config):
        attestation = min(
            (a for a in matching_source_attestations if index in
             get_attesting_indices(state, a.data, a.aggregation_bits, config)),
            key=lambda a: a.inclusion_delay,
        )
        proposer_reward = get_proposer_reward(state, index, config)
        rewards = update_tuple_item_with_fn(
            rewards,
            attestation.proposer_index,
            lambda balance, delta: balance + delta,
            proposer_reward,
        )
        base_reward = get_base_reward(state, index, config)
        max_attester_reward = base_reward - proposer_reward
        rewards = update_tuple_item_with_fn(
            rewards,
            index,
            lambda balance, delta: balance + delta,
            (max_attester_reward // attestation.inclusion_delay),
        )

    if is_in_inactivity_leak(state, config):
        matching_target_attesting_indices = get_unslashed_attesting_indices(
            state, matching_target_attestations, config)
        for index in eligible_validator_indices:
            base_reward = get_base_reward(state, index, config)
            penalties = update_tuple_item_with_fn(
                penalties,
                index,
                lambda balance, delta: balance + delta,
                BASE_REWARDS_PER_EPOCH * base_reward -
                get_proposer_reward(state, index, config),
            )
            if index not in matching_target_attesting_indices:
                effective_balance = state.validators[index].effective_balance
                penalties = update_tuple_item_with_fn(
                    penalties,
                    index,
                    lambda balance, delta: balance + delta,
                    effective_balance *
                    get_finality_delay(state, config.SLOTS_PER_EPOCH) //
                    config.INACTIVITY_PENALTY_QUOTIENT,
                )
    return (
        tuple(Gwei(reward) for reward in rewards),
        tuple(Gwei(penalty) for penalty in penalties),
    )
예제 #28
0
def get_attestation_deltas(state: BeaconState,
                           config: Eth2Config) -> Tuple[Sequence[Gwei], Sequence[Gwei]]:
    committee_config = CommitteeConfig(config)
    rewards = tuple(
        0 for _ in range(len(state.validators))
    )
    penalties = tuple(
        0 for _ in range(len(state.validators))
    )
    previous_epoch = state.previous_epoch(config.SLOTS_PER_EPOCH, config.GENESIS_EPOCH)
    total_balance = get_total_active_balance(state, config)
    eligible_validator_indices = tuple(
        ValidatorIndex(index) for index, v in enumerate(state.validators)
        if v.is_active(previous_epoch) or (
            v.slashed and previous_epoch + 1 < v.withdrawable_epoch
        )
    )

    matching_source_attestations = get_matching_source_attestations(
        state,
        previous_epoch,
        config,
    )
    matching_target_attestations = get_matching_target_attestations(
        state,
        previous_epoch,
        config,
    )
    matching_head_attestations = get_matching_head_attestations(
        state,
        previous_epoch,
        config,
    )

    for attestations in (
            matching_source_attestations,
            matching_target_attestations,
            matching_head_attestations
    ):
        unslashed_attesting_indices = get_unslashed_attesting_indices(
            state,
            attestations,
            committee_config,
        )
        attesting_balance = get_total_balance(state, unslashed_attesting_indices)
        for index in eligible_validator_indices:
            if index in unslashed_attesting_indices:
                rewards = update_tuple_item_with_fn(
                    rewards,
                    index,
                    lambda balance, delta: balance + delta,
                    get_base_reward(
                        state,
                        index,
                        config,
                    ) * attesting_balance // total_balance,
                )
            else:
                penalties = update_tuple_item_with_fn(
                    penalties,
                    index,
                    lambda balance, delta: balance + delta,
                    get_base_reward(
                        state,
                        index,
                        config,
                    ),
                )

    for index in get_unslashed_attesting_indices(
            state,
            matching_source_attestations,
            committee_config,
    ):
        attestation = min(
            (
                a for a in matching_source_attestations
                if index in get_attesting_indices(
                    state,
                    a.data,
                    a.aggregation_bitfield,
                    committee_config,
                )
            ),
            key=lambda a: a.inclusion_delay,
        )
        base_reward = get_base_reward(state, index, config)
        proposer_reward = base_reward // config.PROPOSER_REWARD_QUOTIENT
        rewards = update_tuple_item_with_fn(
            rewards,
            attestation.proposer_index,
            lambda balance, delta: balance + delta,
            proposer_reward,
        )
        max_attester_reward = base_reward - proposer_reward
        rewards = update_tuple_item_with_fn(
            rewards,
            index,
            lambda balance, delta: balance + delta,
            (
                max_attester_reward *
                config.MIN_ATTESTATION_INCLUSION_DELAY //
                attestation.inclusion_delay
            )
        )

    finality_delay = previous_epoch - state.finalized_epoch
    if finality_delay > config.MIN_EPOCHS_TO_INACTIVITY_PENALTY:
        matching_target_attesting_indices = get_unslashed_attesting_indices(
            state,
            matching_target_attestations,
            committee_config,
        )
        for index in eligible_validator_indices:
            penalties = update_tuple_item_with_fn(
                penalties,
                index,
                lambda balance, delta: balance + delta,
                BASE_REWARDS_PER_EPOCH * get_base_reward(
                    state,
                    index,
                    config,
                ),
            )
            if index not in matching_target_attesting_indices:
                effective_balance = state.validators[index].effective_balance
                penalties = update_tuple_item_with_fn(
                    penalties,
                    index,
                    lambda balance, delta: balance + delta,
                    effective_balance * finality_delay // config.INACTIVITY_PENALTY_QUOTIENT,
                )
    return tuple(
        Gwei(reward) for reward in rewards
    ), tuple(
        Gwei(penalty) for penalty in penalties
    )
예제 #29
0
def create_mock_slashable_attestation(
    state: BeaconState,
    config: Eth2Config,
    keymap: Dict[BLSPubkey, int],
    attestation_slot: Slot,
) -> IndexedAttestation:
    """
    Create an `IndexedAttestation` that is signed by one attester.
    """
    attester_index = ValidatorIndex(0)
    committee = (attester_index, )

    # Use genesis block root as `beacon_block_root`, only for tests.
    beacon_block_root = get_block_root_at_slot(
        state, attestation_slot, config.SLOTS_PER_HISTORICAL_ROOT)

    # Get `target_root`
    target_root = _get_target_root(state, config, beacon_block_root)
    # Get `source_root`
    source_root = get_block_root_at_slot(
        state,
        compute_start_slot_at_epoch(state.current_justified_checkpoint.epoch,
                                    config.SLOTS_PER_EPOCH),
        config.SLOTS_PER_HISTORICAL_ROOT,
    )

    committees_per_slot = get_committee_count_at_slot(
        state,
        Slot(attestation_slot),
        config.MAX_COMMITTEES_PER_SLOT,
        config.SLOTS_PER_EPOCH,
        config.TARGET_COMMITTEE_SIZE,
    )
    # Use the first committee
    assert committees_per_slot > 0
    committee_index = CommitteeIndex(0)

    attestation_data = AttestationData.create(
        slot=attestation_slot,
        index=committee_index,
        beacon_block_root=beacon_block_root,
        source=Checkpoint.create(
            epoch=state.current_justified_checkpoint.epoch, root=source_root),
        target=Checkpoint.create(
            epoch=compute_epoch_at_slot(attestation_slot,
                                        config.SLOTS_PER_EPOCH),
            root=target_root,
        ),
    )

    message_hash = attestation_data.hash_tree_root
    attesting_indices = _get_mock_attesting_indices(committee,
                                                    num_voted_attesters=1)

    signature = sign_transaction(
        message_hash=message_hash,
        privkey=keymap[state.validators[attesting_indices[0]].pubkey],
        state=state,
        slot=attestation_slot,
        signature_domain=SignatureDomain.DOMAIN_BEACON_ATTESTER,
        slots_per_epoch=config.SLOTS_PER_EPOCH,
    )
    validator_indices = tuple(committee[i] for i in attesting_indices)

    return IndexedAttestation.create(attesting_indices=validator_indices,
                                     data=attestation_data,
                                     signature=signature)
예제 #30
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