Пример #1
0
def build_attestation_data(state, slot, shard):
    assert state.slot >= slot

    if slot == state.slot:
        block_root = build_empty_block_for_next_slot(state).previous_block_root
    else:
        block_root = get_block_root_at_slot(state, slot)

    current_epoch_start_slot = get_epoch_start_slot(get_current_epoch(state))
    if slot < current_epoch_start_slot:
        epoch_boundary_root = get_block_root(state, get_previous_epoch(state))
    elif slot == current_epoch_start_slot:
        epoch_boundary_root = block_root
    else:
        epoch_boundary_root = get_block_root(state, get_current_epoch(state))

    if slot < current_epoch_start_slot:
        justified_epoch = state.previous_justified_epoch
        justified_block_root = state.previous_justified_root
    else:
        justified_epoch = state.current_justified_epoch
        justified_block_root = state.current_justified_root

    crosslinks = state.current_crosslinks if slot_to_epoch(slot) == get_current_epoch(state) else state.previous_crosslinks
    return AttestationData(
        slot=slot,
        shard=shard,
        beacon_block_root=block_root,
        source_epoch=justified_epoch,
        source_root=justified_block_root,
        target_root=epoch_boundary_root,
        crosslink_data_root=spec.ZERO_HASH,
        previous_crosslink_root=hash_tree_root(crosslinks[shard]),
    )
Пример #2
0
def test_activation(state):
    index = 0
    assert is_active_validator(state.validator_registry[index], get_current_epoch(state))

    # Mock a new deposit
    state.validator_registry[index].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH
    state.validator_registry[index].activation_epoch = spec.FAR_FUTURE_EPOCH
    state.validator_registry[index].effective_balance = spec.MAX_EFFECTIVE_BALANCE
    assert not is_active_validator(state.validator_registry[index], get_current_epoch(state))

    pre_state = deepcopy(state)

    blocks = []
    for _ in range(spec.ACTIVATION_EXIT_DELAY + 1):
        block = next_epoch(state)
        blocks.append(block)

    assert state.validator_registry[index].activation_eligibility_epoch != spec.FAR_FUTURE_EPOCH
    assert state.validator_registry[index].activation_epoch != spec.FAR_FUTURE_EPOCH
    assert is_active_validator(
        state.validator_registry[index],
        get_current_epoch(state),
    )

    return pre_state, blocks, state
Пример #3
0
def test_transfer(state):
    # overwrite default 0 to test
    spec.MAX_TRANSFERS = 1

    sender_index = get_active_validator_indices(state, get_current_epoch(state))[-1]
    amount = get_balance(state, sender_index)

    transfer = get_valid_transfer(state, state.slot + 1, sender_index, amount, signed=True)
    recipient_index = transfer.recipient
    pre_transfer_recipient_balance = get_balance(state, recipient_index)

    # un-activate so validator can transfer
    state.validator_registry[sender_index].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH

    yield 'pre', state

    # Add to state via block transition
    block = build_empty_block_for_next_slot(state)
    block.body.transfers.append(transfer)
    sign_block(state, block)

    yield 'blocks', [block], [spec.BeaconBlock]

    state_transition(state, block)
    yield 'post', state

    sender_balance = get_balance(state, sender_index)
    recipient_balance = get_balance(state, recipient_index)
    assert sender_balance == 0
    assert recipient_balance == pre_transfer_recipient_balance + amount
Пример #4
0
def run_attestation_processing(state, attestation, valid=True):
    """
    Run ``process_attestation``, yielding:
      - pre-state ('pre')
      - attestation ('attestation')
      - post-state ('post').
    If ``valid == False``, run expecting ``AssertionError``
    """
    # yield pre-state
    yield 'pre', state

    yield 'attestation', attestation

    # If the attestation is invalid, processing is aborted, and there is no post-state.
    if not valid:
        expect_assertion_error(lambda: process_attestation(state, attestation))
        yield 'post', None
        return

    current_epoch_count = len(state.current_epoch_attestations)
    previous_epoch_count = len(state.previous_epoch_attestations)

    # process attestation
    process_attestation(state, attestation)

    # Make sure the attestation has been processed
    if attestation.data.target_epoch == get_current_epoch(state):
        assert len(state.current_epoch_attestations) == current_epoch_count + 1
    else:
        assert len(state.previous_epoch_attestations) == previous_epoch_count + 1

    # yield post-state
    yield 'post', state
Пример #5
0
def get_valid_proposer_slashing(state, signed_1=False, signed_2=False):
    current_epoch = get_current_epoch(state)
    validator_index = get_active_validator_indices(state, current_epoch)[-1]
    privkey = pubkey_to_privkey[
        state.validator_registry[validator_index].pubkey]
    slot = state.slot

    header_1 = BeaconBlockHeader(
        slot=slot,
        previous_block_root=b'\x33' * 32,
        state_root=b'\x44' * 32,
        block_body_root=b'\x55' * 32,
    )
    header_2 = deepcopy(header_1)
    header_2.previous_block_root = b'\x99' * 32
    header_2.slot = slot + 1

    if signed_1:
        sign_block_header(state, header_1, privkey)
    if signed_2:
        sign_block_header(state, header_2, privkey)

    return ProposerSlashing(
        proposer_index=validator_index,
        header_1=header_1,
        header_2=header_2,
    )
Пример #6
0
def sign_transfer(state, transfer, privkey):
    transfer.signature = bls_sign(message_hash=signing_root(transfer),
                                  privkey=privkey,
                                  domain=get_domain(
                                      state=state,
                                      domain_type=spec.DOMAIN_TRANSFER,
                                      message_epoch=get_current_epoch(state),
                                  ))
    return transfer
def test_ejection(state):
    index = 0
    assert is_active_validator(state.validator_registry[index], get_current_epoch(state))
    assert state.validator_registry[index].exit_epoch == spec.FAR_FUTURE_EPOCH

    # Mock an ejection
    state.validator_registry[index].effective_balance = spec.EJECTION_BALANCE

    for _ in range(spec.ACTIVATION_EXIT_DELAY + 1):
        next_epoch(state)

    yield from run_process_registry_updates(state)

    assert state.validator_registry[index].exit_epoch != spec.FAR_FUTURE_EPOCH
    assert not is_active_validator(
        state.validator_registry[index],
        get_current_epoch(state),
    )
Пример #8
0
def test_voluntary_exit(state):
    pre_state = deepcopy(state)
    validator_index = get_active_validator_indices(
        pre_state, get_current_epoch(pre_state))[-1]

    # move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow for exit
    pre_state.slot += spec.PERSISTENT_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH

    post_state = deepcopy(pre_state)

    voluntary_exit = VoluntaryExit(
        epoch=get_current_epoch(pre_state),
        validator_index=validator_index,
    )
    voluntary_exit.signature = bls.sign(
        message_hash=signing_root(voluntary_exit),
        privkey=privkeys[validator_index],
        domain=get_domain(
            state=pre_state,
            domain_type=spec.DOMAIN_VOLUNTARY_EXIT,
        ))

    #
    # Add to state via block transition
    #
    initiate_exit_block = build_empty_block_for_next_slot(post_state)
    initiate_exit_block.body.voluntary_exits.append(voluntary_exit)
    state_transition(post_state, initiate_exit_block)

    assert post_state.validator_registry[
        validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH

    #
    # Process within epoch transition
    #
    exit_block = build_empty_block_for_next_slot(post_state)
    exit_block.slot += spec.SLOTS_PER_EPOCH
    state_transition(post_state, exit_block)

    assert post_state.validator_registry[
        validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH

    return pre_state, [initiate_exit_block, exit_block], post_state
Пример #9
0
def test_voluntary_exit(state):
    validator_index = get_active_validator_indices(
        state,
        get_current_epoch(state)
    )[-1]

    # move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow for exit
    state.slot += spec.PERSISTENT_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH

    yield 'pre', state

    voluntary_exit = VoluntaryExit(
        epoch=get_current_epoch(state),
        validator_index=validator_index,
    )
    voluntary_exit.signature = bls_sign(
        message_hash=signing_root(voluntary_exit),
        privkey=privkeys[validator_index],
        domain=get_domain(
            state=state,
            domain_type=spec.DOMAIN_VOLUNTARY_EXIT,
        )
    )

    # Add to state via block transition
    initiate_exit_block = build_empty_block_for_next_slot(state)
    initiate_exit_block.body.voluntary_exits.append(voluntary_exit)
    sign_block(state, initiate_exit_block)
    state_transition(state, initiate_exit_block)

    assert state.validator_registry[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH

    # Process within epoch transition
    exit_block = build_empty_block_for_next_slot(state)
    exit_block.slot += spec.SLOTS_PER_EPOCH
    sign_block(state, exit_block)
    state_transition(state, exit_block)

    yield 'blocks', [initiate_exit_block, exit_block], [spec.BeaconBlock]
    yield 'post', state

    assert state.validator_registry[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH
def test_invalid_signature(state):
    # move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow for exit
    state.slot += spec.PERSISTENT_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH

    current_epoch = get_current_epoch(state)
    validator_index = get_active_validator_indices(state, current_epoch)[0]
    privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey]

    voluntary_exit = build_voluntary_exit(state, current_epoch, validator_index, privkey)

    yield from run_voluntary_exit_processing(state, voluntary_exit, False)
Пример #11
0
def test_success_withdrawable(state):
    next_epoch(state)
    apply_empty_block(state)

    transfer = get_valid_transfer(state, signed=True)

    # withdrawable_epoch in past so can transfer
    state.validator_registry[
        transfer.sender].withdrawable_epoch = get_current_epoch(state) - 1

    yield from run_transfer_processing(state, transfer)
Пример #12
0
def test_success_active_above_max_effective_fee(state):
    sender_index = get_active_validator_indices(state,
                                                get_current_epoch(state))[-1]
    state.balances[sender_index] = spec.MAX_EFFECTIVE_BALANCE + 1
    transfer = get_valid_transfer(state,
                                  sender_index=sender_index,
                                  amount=0,
                                  fee=1,
                                  signed=True)

    yield from run_transfer_processing(state, transfer)
Пример #13
0
def get_valid_transfer(state,
                       slot=None,
                       sender_index=None,
                       amount=None,
                       fee=None):
    if slot is None:
        slot = state.slot
    current_epoch = get_current_epoch(state)
    if sender_index is None:
        sender_index = get_active_validator_indices(state, current_epoch)[-1]
    recipient_index = get_active_validator_indices(state, current_epoch)[0]
    transfer_pubkey = pubkeys[-1]
    transfer_privkey = privkeys[-1]

    if fee is None:
        fee = get_balance(state, sender_index) // 32
    if amount is None:
        amount = get_balance(state, sender_index) - fee

    transfer = Transfer(
        sender=sender_index,
        recipient=recipient_index,
        amount=amount,
        fee=fee,
        slot=slot,
        pubkey=transfer_pubkey,
        signature=ZERO_HASH,
    )
    transfer.signature = bls.sign(message_hash=signing_root(transfer),
                                  privkey=transfer_privkey,
                                  domain=get_domain(
                                      state=state,
                                      domain_type=spec.DOMAIN_TRANSFER,
                                      message_epoch=get_current_epoch(state),
                                  ))

    # ensure withdrawal_credentials reproducable
    state.validator_registry[transfer.sender].withdrawal_credentials = (
        spec.BLS_WITHDRAWAL_PREFIX_BYTE + spec.hash(transfer.pubkey)[1:])

    return transfer
def test_proposer_is_not_activated(state):
    proposer_slashing = get_valid_proposer_slashing(state,
                                                    signed_1=True,
                                                    signed_2=True)

    # set proposer to be not active yet
    state.validator_registry[
        proposer_slashing.
        proposer_index].activation_epoch = get_current_epoch(state) + 1

    yield from run_proposer_slashing_processing(state, proposer_slashing,
                                                False)
def test_activation(state):
    index = 0
    assert is_active_validator(state.validator_registry[index], get_current_epoch(state))

    # Mock a new deposit
    state.validator_registry[index].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH
    state.validator_registry[index].activation_epoch = spec.FAR_FUTURE_EPOCH
    state.validator_registry[index].effective_balance = spec.MAX_EFFECTIVE_BALANCE
    assert not is_active_validator(state.validator_registry[index], get_current_epoch(state))

    for _ in range(spec.ACTIVATION_EXIT_DELAY + 1):
        next_epoch(state)

    yield from run_process_registry_updates(state)

    assert state.validator_registry[index].activation_eligibility_epoch != spec.FAR_FUTURE_EPOCH
    assert state.validator_registry[index].activation_epoch != spec.FAR_FUTURE_EPOCH
    assert is_active_validator(
        state.validator_registry[index],
        get_current_epoch(state),
    )
def test_success_withdrawable(state):
    next_epoch(state)

    transfer = get_valid_transfer(state)

    # withdrawable_epoch in past so can transfer
    state.validator_registry[
        transfer.sender].withdrawable_epoch = get_current_epoch(state) - 1

    pre_state, post_state = run_transfer_processing(state, transfer)

    return pre_state, transfer, post_state
Пример #17
0
def test_active_but_transfer_past_effective_balance(state):
    sender_index = get_active_validator_indices(state,
                                                get_current_epoch(state))[-1]
    amount = spec.MAX_EFFECTIVE_BALANCE // 32
    state.balances[sender_index] = spec.MAX_EFFECTIVE_BALANCE
    transfer = get_valid_transfer(state,
                                  sender_index=sender_index,
                                  amount=amount,
                                  fee=0,
                                  signed=True)

    yield from run_transfer_processing(state, transfer, False)
Пример #18
0
def test_empty_epoch_transition_not_finalizing(state):
    test_state = deepcopy(state)
    block = build_empty_block_for_next_slot(test_state)
    block.slot += spec.SLOTS_PER_EPOCH * 5

    state_transition(test_state, block)

    assert test_state.slot == block.slot
    assert test_state.finalized_epoch < get_current_epoch(test_state) - 4
    for index in range(len(test_state.validator_registry)):
        assert get_balance(test_state, index) < get_balance(state, index)

    return state, [block], test_state
Пример #19
0
def test_ejection(state):
    index = 0
    assert is_active_validator(state.validator_registry[index], get_current_epoch(state))
    assert state.validator_registry[index].exit_epoch == spec.FAR_FUTURE_EPOCH

    # Mock an ejection
    state.validator_registry[index].effective_balance = spec.EJECTION_BALANCE

    pre_state = deepcopy(state)

    blocks = []
    for _ in range(spec.ACTIVATION_EXIT_DELAY + 1):
        block = next_epoch(state)
        blocks.append(block)

    assert state.validator_registry[index].exit_epoch != spec.FAR_FUTURE_EPOCH
    assert not is_active_validator(
        state.validator_registry[index],
        get_current_epoch(state),
    )

    return pre_state, blocks, state
def test_success_active_above_max_effective(state):
    sender_index = get_active_validator_indices(state,
                                                get_current_epoch(state))[-1]
    amount = spec.MAX_EFFECTIVE_BALANCE // 32
    state.balances[sender_index] = spec.MAX_EFFECTIVE_BALANCE + amount
    transfer = get_valid_transfer(state,
                                  sender_index=sender_index,
                                  amount=amount,
                                  fee=0)

    pre_state, post_state = run_transfer_processing(state, transfer)

    return pre_state, transfer, post_state
def test_proposer_is_withdrawn(state):
    proposer_slashing = get_valid_proposer_slashing(state)

    # set proposer withdrawable_epoch in past
    current_epoch = get_current_epoch(state)
    proposer_index = proposer_slashing.proposer_index
    state.validator_registry[
        proposer_index].withdrawable_epoch = current_epoch - 1

    pre_state, post_state = run_proposer_slashing_processing(
        state, proposer_slashing, False)

    return pre_state, proposer_slashing, post_state
Пример #22
0
def test_double_late_crosslink(state):
    if spec.get_epoch_committee_count(
            state, spec.get_current_epoch(state)) < spec.SHARD_COUNT:
        print(
            "warning: ignoring test, test-assumptions are incompatible with configuration"
        )
        return

    next_epoch(state)
    state.slot += 4

    attestation_1 = get_valid_attestation(state, signed=True)
    fill_aggregate_attestation(state, attestation_1)

    # add attestation_1 to next epoch
    next_epoch(state)
    add_attestation_to_state(state, attestation_1, state.slot + 1)

    for slot in range(spec.SLOTS_PER_EPOCH):
        attestation_2 = get_valid_attestation(state)
        if attestation_2.data.shard == attestation_1.data.shard:
            sign_attestation(state, attestation_2)
            break
        next_slot(state)
    apply_empty_block(state)

    fill_aggregate_attestation(state, attestation_2)

    # add attestation_2 in the next epoch after attestation_1 has
    # already updated the relevant crosslink
    next_epoch(state)
    add_attestation_to_state(state, attestation_2, state.slot + 1)

    assert len(state.previous_epoch_attestations) == 1
    assert len(state.current_epoch_attestations) == 0

    crosslink_deltas = get_crosslink_deltas(state)

    yield from run_process_crosslinks(state)

    shard = attestation_2.data.shard

    # ensure that the current crosslinks were not updated by the second attestation
    assert state.previous_crosslinks[shard] == state.current_crosslinks[shard]
    # ensure no reward, only penalties for the failed crosslink
    for index in get_crosslink_committee(state,
                                         attestation_2.data.target_epoch,
                                         attestation_2.data.shard):
        assert crosslink_deltas[0][index] == 0
        assert crosslink_deltas[1][index] > 0
def test_proposer_is_withdrawn(state):
    proposer_slashing = get_valid_proposer_slashing(state,
                                                    signed_1=True,
                                                    signed_2=True)

    # move 1 epoch into future, to allow for past withdrawable epoch
    state.slot += spec.SLOTS_PER_EPOCH
    # set proposer withdrawable_epoch in past
    current_epoch = get_current_epoch(state)
    proposer_index = proposer_slashing.proposer_index
    state.validator_registry[
        proposer_index].withdrawable_epoch = current_epoch - 1

    yield from run_proposer_slashing_processing(state, proposer_slashing,
                                                False)
Пример #24
0
def test_historical_batch(state):
    state.slot += spec.SLOTS_PER_HISTORICAL_ROOT - (state.slot % spec.SLOTS_PER_HISTORICAL_ROOT) - 1
    pre_historical_roots_len = len(state.historical_roots)

    yield 'pre', state

    block = build_empty_block_for_next_slot(state, signed=True)
    state_transition(state, block)

    yield 'blocks', [block], [spec.BeaconBlock]
    yield 'post', state

    assert state.slot == block.slot
    assert get_current_epoch(state) % (spec.SLOTS_PER_HISTORICAL_ROOT // spec.SLOTS_PER_EPOCH) == 0
    assert len(state.historical_roots) == pre_historical_roots_len + 1
Пример #25
0
def test_insufficient_balance(state):
    sender_index = get_active_validator_indices(state,
                                                get_current_epoch(state))[-1]
    state.balances[sender_index] = spec.MAX_EFFECTIVE_BALANCE
    transfer = get_valid_transfer(state,
                                  sender_index=sender_index,
                                  amount=1,
                                  fee=0,
                                  signed=True)

    # un-activate so validator can transfer
    state.validator_registry[
        transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH

    yield from run_transfer_processing(state, transfer, False)
Пример #26
0
def test_no_dust_sender(state):
    sender_index = get_active_validator_indices(state,
                                                get_current_epoch(state))[-1]
    balance = state.balances[sender_index]
    transfer = get_valid_transfer(state,
                                  sender_index=sender_index,
                                  amount=balance - spec.MIN_DEPOSIT_AMOUNT + 1,
                                  fee=0,
                                  signed=True)

    # un-activate so validator can transfer
    state.validator_registry[
        transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH

    yield from run_transfer_processing(state, transfer, False)
Пример #27
0
def test_transfer(state):
    # overwrite default 0 to test
    spec.MAX_TRANSFERS = 1

    pre_state = deepcopy(state)
    current_epoch = get_current_epoch(pre_state)
    sender_index = get_active_validator_indices(pre_state, current_epoch)[-1]
    recipient_index = get_active_validator_indices(pre_state, current_epoch)[0]
    transfer_pubkey = pubkeys[-1]
    transfer_privkey = privkeys[-1]
    amount = get_balance(pre_state, sender_index)
    pre_transfer_recipient_balance = get_balance(pre_state, recipient_index)
    transfer = Transfer(
        sender=sender_index,
        recipient=recipient_index,
        amount=amount,
        fee=0,
        slot=pre_state.slot + 1,
        pubkey=transfer_pubkey,
    )
    transfer.signature = bls.sign(message_hash=signing_root(transfer),
                                  privkey=transfer_privkey,
                                  domain=get_domain(
                                      state=pre_state,
                                      domain_type=spec.DOMAIN_TRANSFER,
                                  ))

    # ensure withdrawal_credentials reproducable
    pre_state.validator_registry[sender_index].withdrawal_credentials = (
        spec.BLS_WITHDRAWAL_PREFIX_BYTE + hash(transfer_pubkey)[1:])
    # un-activate so validator can transfer
    pre_state.validator_registry[
        sender_index].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH

    post_state = deepcopy(pre_state)
    #
    # Add to state via block transition
    #
    block = build_empty_block_for_next_slot(post_state)
    block.body.transfers.append(transfer)
    state_transition(post_state, block)

    sender_balance = get_balance(post_state, sender_index)
    recipient_balance = get_balance(post_state, recipient_index)
    assert sender_balance == 0
    assert recipient_balance == pre_transfer_recipient_balance + amount

    return pre_state, [block], post_state
Пример #28
0
def test_historical_batch(state):
    state.slot += spec.SLOTS_PER_HISTORICAL_ROOT - (
        state.slot % spec.SLOTS_PER_HISTORICAL_ROOT) - 1

    post_state = deepcopy(state)

    block = build_empty_block_for_next_slot(post_state)

    state_transition(post_state, block)

    assert post_state.slot == block.slot
    assert get_current_epoch(post_state) % (spec.SLOTS_PER_HISTORICAL_ROOT //
                                            spec.SLOTS_PER_EPOCH) == 0
    assert len(post_state.historical_roots) == len(state.historical_roots) + 1

    return state, [block], post_state
def test_success_exit_queue(state):
    # move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow for exit
    state.slot += spec.PERSISTENT_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH

    current_epoch = get_current_epoch(state)

    # exit `MAX_EXITS_PER_EPOCH`
    initial_indices = get_active_validator_indices(state, current_epoch)[:get_churn_limit(state)]

    # Prepare a bunch of exits, based on the current state
    exit_queue = []
    for index in initial_indices:
        privkey = pubkey_to_privkey[state.validator_registry[index].pubkey]
        exit_queue.append(build_voluntary_exit(
            state,
            current_epoch,
            index,
            privkey,
            signed=True,
        ))

    # Now run all the exits
    for voluntary_exit in exit_queue:
        # the function yields data, but we are just interested in running it here, ignore yields.
        for _ in run_voluntary_exit_processing(state, voluntary_exit):
            continue

    # exit an additional validator
    validator_index = get_active_validator_indices(state, current_epoch)[-1]
    privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey]
    voluntary_exit = build_voluntary_exit(
        state,
        current_epoch,
        validator_index,
        privkey,
        signed=True,
    )

    # This is the interesting part of the test: on a pre-state with a full exit queue,
    #  when processing an additional exit, it results in an exit in a later epoch
    yield from run_voluntary_exit_processing(state, voluntary_exit)

    assert (
        state.validator_registry[validator_index].exit_epoch ==
        state.validator_registry[initial_indices[0]].exit_epoch + 1
    )
def test_insufficient_balance(state):
    sender_index = get_active_validator_indices(state,
                                                get_current_epoch(state))[-1]
    amount = spec.MAX_EFFECTIVE_BALANCE
    state.balances[sender_index] = spec.MAX_EFFECTIVE_BALANCE
    transfer = get_valid_transfer(state,
                                  sender_index=sender_index,
                                  amount=amount + 1,
                                  fee=0)

    # un-activate so validator can transfer
    state.validator_registry[
        transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH

    pre_state, post_state = run_transfer_processing(state, transfer, False)

    return pre_state, transfer, post_state