def _mk_resolved_attestation_duty(slot, public_key):
    return (
        AttestationDuty(public_key,
                        Tick(0, slot, 0, 1),
                        Tick(0, 0, 0, 1),
                        committee_index=22),
        Attestation.create(data=AttestationData.create(slot=slot)),
    )
Exemple #2
0
    def duty_fetcher(current_tick, _public_keys, target_epoch,
                     _slots_per_epoch, _seconds_per_slot):
        duties = ()
        if target_epoch < 0:
            return duties

        some_slot = current_tick.slot
        if current_tick.epoch >= 0:
            block_proposal_duty = BlockProposalDuty(
                public_key, Tick(0, some_slot, target_epoch, 0), current_tick)
            duties += (block_proposal_duty, )
        attestation_duty = AttestationDuty(
            public_key,
            Tick(0, some_slot + slots_per_epoch, target_epoch, 1),
            current_tick,
            CommitteeIndex(22),
        )
        duties += (attestation_duty, )
        return duties
Exemple #3
0
def _fetch_some_random_duties(
    current_tick: Tick,
    public_keys: Collection[BLSPubkey],
    target_epoch: Epoch,
    slots_per_epoch: Slot,
    seconds_per_slot: int,
) -> Tuple[Duty, ...]:
    if not public_keys:
        return ()
    if target_epoch < 0:
        return ()
    some_slot = Slot(
        random.randint(0, slots_per_epoch) + target_epoch * slots_per_epoch)
    execution_time = seconds_per_slot * (some_slot -
                                         current_tick.slot) + current_tick.t
    is_attestation = bool(random.getrandbits(1))
    # NOTE: use of ``tuple`` here is satisfy ``mypy``.
    some_validator = random.choice(tuple(public_keys))
    if is_attestation:
        committee_index = random.randint(0, 64)
        some_tick_count = 1
        attestation_duty = AttestationDuty(
            some_validator,
            Tick(execution_time, some_slot, target_epoch, some_tick_count),
            current_tick,
            CommitteeIndex(committee_index),
        )
        return (attestation_duty, )
    else:
        some_tick_count = 0
        block_proposal_duty = BlockProposalDuty(
            some_validator,
            Tick(execution_time, some_slot, target_epoch, some_tick_count),
            current_tick,
        )
        return (block_proposal_duty, )
Exemple #4
0
def _parse_block_proposal_duty(
    duty_data: Dict[str, Any],
    validator_public_key: BLSPubkey,
    current_tick: Tick,
    target_epoch: Epoch,
    genesis_time: int,
    seconds_per_slot: int,
    ticks_per_slot: int,
) -> BlockProposalDuty:
    target_tick = Tick.computing_t_from(
        Slot(duty_data["block_proposal_slot"]),
        target_epoch,
        BlockProposalDuty.tick_count,
        genesis_time,
        seconds_per_slot,
        ticks_per_slot,
    )
    return BlockProposalDuty(
        validator_public_key=validator_public_key,
        tick_for_execution=target_tick,
        discovered_at_tick=current_tick,
    )
Exemple #5
0
def _parse_attestation_duty(
    duty_data: Dict[str, Any],
    validator_public_key: BLSPubkey,
    current_tick: Tick,
    target_epoch: Epoch,
    genesis_time: int,
    seconds_per_slot: int,
    ticks_per_slot: int,
) -> AttestationDuty:
    target_tick = Tick.computing_t_from(
        Slot(duty_data["attestation_slot"]),
        target_epoch,
        AttestationDuty.tick_count,
        genesis_time,
        seconds_per_slot,
        ticks_per_slot,
    )
    return AttestationDuty(
        validator_public_key=validator_public_key,
        tick_for_execution=target_tick,
        discovered_at_tick=current_tick,
        committee_index=CommitteeIndex(duty_data["committee_index"]),
    )
Exemple #6
0
 def on_tick(self, tick: Tick) -> None:
     if tick.is_first_in_slot():
         fork_choice = self._get_fork_choice(tick.slot)
         head = fork_choice.find_head()
         self._update_head_if_new(head)
def test_chain_can_reorg_with_attestations(base_db, genesis_state,
                                           genesis_block, config, keymap):
    chain = BeaconChain.from_genesis(base_db, genesis_state)

    genesis_head = chain.get_canonical_head()
    assert genesis_head == genesis_block.message

    some_epochs = 5
    some_slots = some_epochs * config.SLOTS_PER_EPOCH
    blocks, states = _build_chain_of_blocks_with_states(
        chain,
        genesis_state,
        genesis_block.message,
        some_slots,
        config,
        keymap,
        attestation_participation=0.01,
    )
    for block in blocks:
        chain.on_block(block)

    head = chain.get_canonical_head()
    assert head == blocks[-1].message

    # NOTE: ideally we can randomly pick a reorg slot and successfully execute a reorg...
    # however, it becomes tricky to do reliably at low validator count as the numbers
    # may be too low to easily get enough stake one way or the other...
    # The following numbers are somewhat handcrafted and it would greatly improve this test
    # if it were made more resilient to these parameters. However, the big thing blocking
    # that is performance work so that the test runs in a short time at high validator count.
    some_reorg_slot = 12
    # NOTE: this block hash is selected so that
    # we do not re-org in the chain import due to the tie breaker...
    some_block_hash = b"\x12" * 32

    blocks, states = _build_chain_of_blocks_with_states(
        chain,
        states[some_reorg_slot - 1],
        blocks[some_reorg_slot - 1].message,
        25,
        config,
        keymap,
        attestation_participation=0,
        eth1_block_hash=some_block_hash,
    )
    for block in blocks:
        with pytest.raises(SlashableBlockError):
            chain.on_block(block)
    existing_head = head
    head = chain.get_canonical_head()
    assert head == existing_head

    attestations = _mk_attestations_from(blocks, states, chain, config, keymap)
    for attestation in attestations:
        chain.on_attestation(attestation)
    # NOTE: we have not updated the fork choice yet...
    # This is essentially to prevent what would otherwise be a DoS
    # vector according to this test...
    head = chain.get_canonical_head()
    assert head == existing_head

    # NOTE: simulate a tick to run the fork choice
    # in this case, we do not care which tick it is,
    # as long as it is the first tick in the slot
    chain.on_tick(Tick(0, Slot(0), Epoch(0), 0))

    head = chain.get_canonical_head()
    assert head != existing_head
    assert head == blocks[-1].message
def _mk_resolved_block_proposal_duty(slot, public_key):
    return (
        BlockProposalDuty(public_key, Tick(0, slot, 0, 0), Tick(0, 0, 0, 0)),
        BeaconBlock.create(slot=slot),
    )