Exemple #1
0
def create_mock_attester_slashing_is_surround_vote(
    state: BeaconState,
    config: Eth2Config,
    keymap: Dict[BLSPubkey, int],
    attestation_epoch: Epoch,
) -> AttesterSlashing:
    # target_epoch_2 < target_epoch_1
    attestation_slot_2 = compute_start_slot_at_epoch(attestation_epoch,
                                                     config.SLOTS_PER_EPOCH)
    attestation_slot_1 = Slot(attestation_slot_2 + config.SLOTS_PER_EPOCH)

    slashable_attestation_1 = create_mock_slashable_attestation(
        state.mset("slot", attestation_slot_1, "current_justified_epoch",
                   config.GENESIS_EPOCH),
        config,
        keymap,
        attestation_slot_1,
    )
    slashable_attestation_2 = create_mock_slashable_attestation(
        state.mset(
            "slot",
            attestation_slot_1,
            "current_justified_epoch",
            config.GENESIS_EPOCH + 1,  # source_epoch_1 < source_epoch_2
        ),
        config,
        keymap,
        attestation_slot_2,
    )

    return AttesterSlashing.create(attestation_1=slashable_attestation_1,
                                   attestation_2=slashable_attestation_2)
Exemple #2
0
def create_mock_deposit(
    state: BeaconState,
    pubkey: BLSPubkey,
    keymap: Dict[BLSPubkey, int],
    withdrawal_credentials: Hash32,
    config: Eth2Config,
    leaves: Sequence[Hash32] = None,
) -> Tuple[BeaconState, Deposit]:
    deposits, root = create_mock_deposits_and_root(
        (pubkey, ),
        keymap,
        config,
        withdrawal_credentials=(withdrawal_credentials, ),
        leaves=leaves,
    )
    # sanity check
    assert len(deposits) == 1
    deposit = deposits[0]

    eth1_data = state.eth1_data.mset(
        "deposit_root",
        root,
        "deposit_count",
        state.eth1_data.deposit_count + len(deposits),
    )
    state = state.mset("eth1_data", eth1_data, "eth1_deposit_index",
                       0 if not leaves else len(leaves))

    return state, deposit
def process_justification_and_finalization(state: BeaconState,
                                           config: Eth2Config) -> BeaconState:
    current_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)

    if current_epoch <= GENESIS_EPOCH + 1:
        return state

    (
        new_current_justified_checkpoint,
        justification_bits,
    ) = _determine_new_justified_checkpoint_and_bitfield(state, config)

    new_finalized_checkpoint = _determine_new_finalized_checkpoint(
        state, justification_bits, config)

    return state.mset(
        "justification_bits",
        justification_bits,
        "previous_justified_checkpoint",
        state.current_justified_checkpoint,
        "current_justified_checkpoint",
        new_current_justified_checkpoint,
        "finalized_checkpoint",
        new_finalized_checkpoint,
    )
Exemple #4
0
def process_attestations(state: BeaconState, block: BaseBeaconBlock,
                         config: Eth2Config) -> BeaconState:
    if len(block.body.attestations) > config.MAX_ATTESTATIONS:
        raise ValidationError(
            f"The block has too many attestations:\n"
            f"\tFound {len(block.body.attestations)} attestations, "
            f"maximum: {config.MAX_ATTESTATIONS}")

    current_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)
    current_epoch_attestations = state.current_epoch_attestations
    previous_epoch_attestations = state.previous_epoch_attestations

    for attestation in block.body.attestations:
        validate_attestation(state, attestation, config)
        proposer_index = get_beacon_proposer_index(state, config)
        pending_attestation = PendingAttestation.create(
            aggregation_bits=attestation.aggregation_bits,
            data=attestation.data,
            inclusion_delay=state.slot - attestation.data.slot,
            proposer_index=proposer_index,
        )

        if attestation.data.target.epoch == current_epoch:
            current_epoch_attestations = current_epoch_attestations.append(
                pending_attestation)
        else:
            previous_epoch_attestations = previous_epoch_attestations.append(
                pending_attestation)

    return state.mset(
        "current_epoch_attestations",
        current_epoch_attestations,
        "previous_epoch_attestations",
        previous_epoch_attestations,
    )
Exemple #5
0
def process_eth1_data(state: BeaconState, block: BaseBeaconBlock,
                      config: Eth2Config) -> BeaconState:
    body = block.body

    new_eth1_data_votes = state.eth1_data_votes.append(body.eth1_data)

    new_eth1_data = state.eth1_data
    if (new_eth1_data_votes.count(body.eth1_data) * 2 >
            config.SLOTS_PER_ETH1_VOTING_PERIOD):
        new_eth1_data = body.eth1_data

    return state.mset("eth1_data", new_eth1_data, "eth1_data_votes",
                      new_eth1_data_votes)
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.set("eth1_deposit_index", state.eth1_deposit_index + 1)

    pubkey = deposit.data.pubkey
    amount = deposit.data.amount
    withdrawal_credentials = deposit.data.withdrawal_credentials
    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`.
        deposit_message = DepositMessage.create(
            pubkey=pubkey,
            withdrawal_credentials=withdrawal_credentials,
            amount=amount)
        domain = compute_domain(SignatureDomain.DOMAIN_DEPOSIT,
                                fork_version=config.GENESIS_FORK_VERSION)
        signing_root = compute_signing_root(deposit_message, domain)

        is_valid_proof_of_possession = bls.verify(signing_root,
                                                  deposit.data.signature,
                                                  pubkey)

        if not is_valid_proof_of_possession:
            return state

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

        return state.mset(
            "validators",
            state.validators.append(validator),
            "balances",
            state.balances.append(amount),
        )
    else:
        index = ValidatorIndex(validator_pubkeys.index(pubkey))
        return increase_balance(state, index, amount)
Exemple #7
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)
def process_final_updates(state: BeaconState,
                          config: Eth2Config) -> BeaconState:
    new_eth1_data_votes = _determine_next_eth1_votes(state, config)
    new_validators = _update_effective_balances(state, config)
    new_slashings = _compute_next_slashings(state, config)
    new_randao_mixes = _compute_next_randao_mixes(state, config)
    new_historical_roots = _compute_next_historical_roots(state, config)
    return state.mset(
        "eth1_data_votes",
        new_eth1_data_votes,
        "validators",
        new_validators,
        "slashings",
        new_slashings,
        "randao_mixes",
        new_randao_mixes,
        "historical_roots",
        new_historical_roots,
        "previous_epoch_attestations",
        state.current_epoch_attestations,
        "current_epoch_attestations",
        HashableList.from_iterable(
            (), sedes=state.current_epoch_attestations.sedes),
    )
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