Exemple #1
0
def slash_validator(
    state: BeaconState,
    index: ValidatorIndex,
    config: Eth2Config,
    whistleblower_index: ValidatorIndex = None,
) -> BeaconState:
    """
    Slash the validator with index ``index``.

    Exit the validator, penalize the validator, and reward the whistleblower.
    """
    # NOTE: remove in phase 1
    assert whistleblower_index is None

    slots_per_epoch = config.SLOTS_PER_EPOCH

    current_epoch = state.current_epoch(slots_per_epoch)

    state = initiate_validator_exit(state, index, config)

    state = state.transform(
        ("validators", index),
        partial(
            _set_validator_slashed,
            current_epoch=current_epoch,
            epochs_per_slashings_vector=config.EPOCHS_PER_SLASHINGS_VECTOR,
        ),
    )

    slashed_balance = state.validators[index].effective_balance
    slashed_epoch = current_epoch % config.EPOCHS_PER_SLASHINGS_VECTOR
    state = state.transform(("slashings", slashed_epoch),
                            lambda balance: Gwei(balance + slashed_balance))
    state = decrease_balance(
        state, index, slashed_balance // config.MIN_SLASHING_PENALTY_QUOTIENT)

    proposer_index = get_beacon_proposer_index(state, config)
    if whistleblower_index is None:
        whistleblower_index = proposer_index
    whistleblower_reward = Gwei(slashed_balance //
                                config.WHISTLEBLOWER_REWARD_QUOTIENT)
    proposer_reward = Gwei(whistleblower_reward //
                           config.PROPOSER_REWARD_QUOTIENT)
    state = increase_balance(state, proposer_index, proposer_reward)
    state = increase_balance(state, whistleblower_index,
                             Gwei(whistleblower_reward - proposer_reward))

    return state
Exemple #2
0
def process_randao(state: BeaconState, block: BaseBeaconBlock,
                   config: Eth2Config) -> BeaconState:
    proposer_index = get_beacon_proposer_index(
        state=state, committee_config=CommitteeConfig(config))

    epoch = state.current_epoch(config.SLOTS_PER_EPOCH)

    validate_randao_reveal(
        state=state,
        proposer_index=proposer_index,
        epoch=epoch,
        randao_reveal=block.body.randao_reveal,
        slots_per_epoch=config.SLOTS_PER_EPOCH,
    )

    randao_mix_index = epoch % config.EPOCHS_PER_HISTORICAL_VECTOR
    new_randao_mix = bitwise_xor(
        get_randao_mix(
            state=state,
            epoch=epoch,
            epochs_per_historical_vector=config.EPOCHS_PER_HISTORICAL_VECTOR,
        ),
        hash_eth2(block.body.randao_reveal),
    )

    return state.transform(("randao_mixes", randao_mix_index), new_randao_mix)
Exemple #3
0
def initiate_validator_exit(state: BeaconState, index: ValidatorIndex,
                            config: Eth2Config) -> BeaconState:
    """
    Initiate exit for the validator with the given ``index``.
    Return the updated state (immutable).
    """
    return state.transform(
        ("validators", index),
        partial(initiate_exit_for_validator, state=state, config=config),
    )
def _process_activation_eligibility_or_ejections(
        state: BeaconState, index: ValidatorIndex,
        config: Eth2Config) -> BeaconState:
    current_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)
    validator = state.validators[index]

    if validator.is_eligible_for_activation_queue(config):
        validator = validator.set("activation_eligibility_epoch",
                                  current_epoch + 1)

    if (validator.is_active(current_epoch)
            and validator.effective_balance <= config.EJECTION_BALANCE):
        validator = initiate_exit_for_validator(validator, state, config)

    return state.transform(("validators", index), validator)
Exemple #5
0
def _process_slot(state: BeaconState, config: Eth2Config) -> BeaconState:
    slots_per_historical_root = config.SLOTS_PER_HISTORICAL_ROOT

    previous_state_root = state.hash_tree_root
    updated_state_roots = _update_historical_root(state.state_roots,
                                                  state.slot,
                                                  slots_per_historical_root,
                                                  previous_state_root)

    if state.latest_block_header.state_root == ZERO_HASH32:
        state = state.transform(("latest_block_header", "state_root"),
                                previous_state_root)

    updated_block_roots = _update_historical_root(
        state.block_roots,
        state.slot,
        slots_per_historical_root,
        state.latest_block_header.signing_root,
    )

    return state.mset("block_roots", updated_block_roots, "state_roots",
                      updated_state_roots)
Exemple #6
0
def decrease_balance(state: BeaconState, index: ValidatorIndex,
                     delta: Gwei) -> BeaconState:
    return state.transform(
        ("balances", index),
        lambda balance: Gwei(0) if delta > balance else Gwei(balance - delta),
    )
Exemple #7
0
def increase_balance(state: BeaconState, index: ValidatorIndex,
                     delta: Gwei) -> BeaconState:
    return state.transform(("balances", index),
                           lambda balance: Gwei(balance + delta))
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