def test_get_matching_target_attestations(genesis_state, config):
    some_epoch = GENESIS_EPOCH + 20
    some_slot = compute_start_slot_at_epoch(some_epoch, config.SLOTS_PER_EPOCH)
    some_target_root = b"\x33" * 32
    target_attestations = tuple(
        PendingAttestation.create(
            data=AttestationData.create(target=Checkpoint.create(root=some_target_root))
        )
        for _ in range(3)
    )
    current_epoch_attestations = target_attestations + tuple(
        PendingAttestation.create(
            data=AttestationData.create(target=Checkpoint.create(root=b"\x44" * 32))
        )
        for _ in range(3)
    )
    state = genesis_state.transform(
        ["slot"],
        some_slot + 1,
        ["block_roots", some_slot % config.SLOTS_PER_HISTORICAL_ROOT],
        some_target_root,
        ["current_epoch_attestations"],
        current_epoch_attestations,
    )

    attestations = get_matching_target_attestations(state, some_epoch, config)

    assert attestations == target_attestations
def test_get_matching_head_attestations(genesis_state, config):
    some_epoch = config.GENESIS_EPOCH + 20
    some_slot = (
        compute_start_slot_at_epoch(some_epoch, config.SLOTS_PER_EPOCH) +
        config.SLOTS_PER_EPOCH // 4)
    some_target_root = b"\x33" * 32
    target_attestations = tuple(
        (PendingAttestation.create(data=AttestationData.create(
            slot=some_slot - 1,
            index=0,
            beacon_block_root=some_target_root,
            target=Checkpoint.create(epoch=some_epoch - 1),
        )) for i in range(3)))
    current_epoch_attestations = target_attestations + tuple(
        (PendingAttestation.create(data=AttestationData.create(
            beacon_block_root=b"\x44" * 32,
            target=Checkpoint.create(epoch=some_epoch - 1),
        )) for _ in range(3)))
    state = genesis_state.mset(
        "slot",
        some_slot,
        "block_roots",
        tuple(some_target_root
              for _ in range(config.SLOTS_PER_HISTORICAL_ROOT)),
        "current_epoch_attestations",
        current_epoch_attestations,
    )

    attestations = get_matching_head_attestations(state, some_epoch, config)

    assert attestations == target_attestations
Exemple #3
0
def sample_attestation_data_params():
    return {
        "slot": 5,
        "index": 1,
        "beacon_block_root": b"\x11" * 32,
        "source": Checkpoint.create(epoch=11, root=b"\x22" * 32),
        "target": Checkpoint.create(epoch=12, root=b"\x33" * 32),
    }
def test_process_justification_and_finalization(
    genesis_state,
    current_epoch,
    current_epoch_justifiable,
    previous_epoch_justifiable,
    previous_justified_epoch,
    current_justified_epoch,
    justification_bits,
    finalized_epoch,
    justified_epoch_after,
    justification_bits_after,
    finalized_epoch_after,
    config,
):
    justification_bits = _convert_to_bitfield(justification_bits)
    justification_bits_after = _convert_to_bitfield(justification_bits_after)
    previous_epoch = max(current_epoch - 1, 0)
    slot = (current_epoch + 1) * config.SLOTS_PER_EPOCH - 1

    state = genesis_state.mset(
        "slot",
        slot,
        "previous_justified_checkpoint",
        Checkpoint.create(epoch=previous_justified_epoch),
        "current_justified_checkpoint",
        Checkpoint.create(epoch=current_justified_epoch),
        "justification_bits",
        justification_bits,
        "finalized_checkpoint",
        Checkpoint.create(epoch=finalized_epoch),
        "block_roots",
        tuple(
            i.to_bytes(32, "little")
            for i in range(config.SLOTS_PER_HISTORICAL_ROOT)),
    )

    if previous_epoch_justifiable:
        attestations = mk_all_pending_attestations_with_full_participation_in_epoch(
            state, previous_epoch, config)
        state = state.set("previous_epoch_attestations", attestations)

    if current_epoch_justifiable:
        attestations = mk_all_pending_attestations_with_full_participation_in_epoch(
            state, current_epoch, config)
        state = state.set("current_epoch_attestations", attestations)

    post_state = process_justification_and_finalization(state, config)

    assert (post_state.previous_justified_checkpoint.epoch ==
            state.current_justified_checkpoint.epoch)
    assert post_state.current_justified_checkpoint.epoch == justified_epoch_after
    assert post_state.justification_bits == justification_bits_after
    assert post_state.finalized_checkpoint.epoch == finalized_epoch_after
Exemple #5
0
def create_mock_signed_attestations_at_slot(
    state: BeaconState,
    config: Eth2Config,
    state_machine: BaseBeaconStateMachine,
    attestation_slot: Slot,
    beacon_block_root: Root,
    keymap: Dict[BLSPubkey, int],
    voted_attesters_ratio: float = 1.0,
) -> Iterable[Attestation]:
    """
    Create the mocking attestations of the given ``attestation_slot`` slot with ``keymap``.
    """
    if voted_attesters_ratio == 0:
        return ()

    committees_per_slot = get_committee_count_at_slot(
        state,
        attestation_slot,
        config.MAX_COMMITTEES_PER_SLOT,
        config.SLOTS_PER_EPOCH,
        config.TARGET_COMMITTEE_SIZE,
    )

    # Get `target_root`
    target_root = _get_target_root(state, config, beacon_block_root)
    target_epoch = compute_epoch_at_slot(state.slot, config.SLOTS_PER_EPOCH)

    for committee, committee_index, _ in iterate_committees_at_slot(
            state, attestation_slot, committees_per_slot, config):
        attestation_data = AttestationData.create(
            slot=attestation_slot,
            index=CommitteeIndex(committee_index),
            beacon_block_root=beacon_block_root,
            source=Checkpoint.create(
                epoch=state.current_justified_checkpoint.epoch,
                root=state.current_justified_checkpoint.root,
            ),
            target=Checkpoint.create(root=target_root, epoch=target_epoch),
        )

        num_voted_attesters = max(int(len(committee) * voted_attesters_ratio),
                                  1)

        yield _create_mock_signed_attestation(
            state,
            attestation_data,
            attestation_slot,
            committee,
            num_voted_attesters,
            keymap,
            config.SLOTS_PER_EPOCH,
        )
Exemple #6
0
def sample_beacon_state_params(
    config,
    genesis_slot,
    genesis_epoch,
    sample_fork_params,
    sample_eth1_data_params,
    sample_block_header_params,
):
    return {
        # Versioning
        "genesis_time":
        0,
        "slot":
        genesis_slot + 100,
        "fork":
        Fork.create(**sample_fork_params),
        # History
        "latest_block_header":
        BeaconBlockHeader.create(**sample_block_header_params),
        "block_roots": (ZERO_HASH32, ) * config.SLOTS_PER_HISTORICAL_ROOT,
        "state_roots": (ZERO_HASH32, ) * config.SLOTS_PER_HISTORICAL_ROOT,
        "historical_roots": (),
        # Eth1
        "eth1_data":
        Eth1Data.create(**sample_eth1_data_params),
        "eth1_data_votes": (),
        "eth1_deposit_index":
        0,
        # Registry
        "validators": (),
        "balances": (),
        # Shuffling
        "randao_mixes": (ZERO_HASH32, ) * config.EPOCHS_PER_HISTORICAL_VECTOR,
        # Slashings
        "slashings": (0, ) * config.EPOCHS_PER_SLASHINGS_VECTOR,
        # Attestations
        "previous_epoch_attestations": (),
        "current_epoch_attestations": (),
        # Justification
        "justification_bits": (False, ) * JUSTIFICATION_BITS_LENGTH,
        "previous_justified_checkpoint":
        Checkpoint.create(epoch=0, root=b"\x99" * 32),
        "current_justified_checkpoint":
        Checkpoint.create(epoch=0, root=b"\x55" * 32),
        # Finality
        "finalized_checkpoint":
        Checkpoint.create(epoch=0, root=b"\x33" * 32),
    }
def test_get_attesting_indices(genesis_state, config):
    state = genesis_state.set(
        "slot", compute_start_slot_at_epoch(3, config.SLOTS_PER_EPOCH))
    target_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)
    target_slot = compute_start_slot_at_epoch(target_epoch,
                                              config.SLOTS_PER_EPOCH)
    committee_index = 0
    some_committee = get_beacon_committee(state, target_slot, committee_index,
                                          config)

    data = AttestationData.create(
        slot=target_slot,
        index=committee_index,
        target=Checkpoint.create(epoch=target_epoch),
    )
    some_subset_count = random.randrange(1, len(some_committee) // 2)
    some_subset = random.sample(some_committee, some_subset_count)

    bitfield = get_empty_bitfield(len(some_committee))
    for i, index in enumerate(some_committee):
        if index in some_subset:
            bitfield = set_voted(bitfield, i)

    indices = get_attesting_indices(state, data, bitfield, config)

    assert set(indices) == set(some_subset)
    assert len(indices) == len(some_subset)
def _determine_new_finalized_checkpoint(state: BeaconState,
                                        justification_bits: Bitfield,
                                        config: Eth2Config) -> Checkpoint:
    current_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)

    new_finalized_epoch = _determine_new_finalized_epoch(
        state.finalized_checkpoint.epoch,
        state.previous_justified_checkpoint.epoch,
        state.current_justified_checkpoint.epoch,
        current_epoch,
        justification_bits,
    )
    if new_finalized_epoch != state.finalized_checkpoint.epoch:
        # NOTE: we only want to call ``get_block_root``
        # upon some change, not unconditionally
        # Given the way it reads the block roots, it can cause
        # validation problems with some configurations, esp. in testing.
        # This is implicitly happening above for the justified roots.
        new_finalized_root = get_block_root(
            state,
            new_finalized_epoch,
            config.SLOTS_PER_EPOCH,
            config.SLOTS_PER_HISTORICAL_ROOT,
        )
    else:
        new_finalized_root = state.finalized_checkpoint.root

    return Checkpoint.create(epoch=new_finalized_epoch,
                             root=new_finalized_root)
Exemple #9
0
    def _load_checkpoints(self) -> None:
        justified = self._chain_db.get_justified_head(BeaconBlock)
        finalized = self._chain_db.get_finalized_head(BeaconBlock)

        state_machine = self.get_state_machine(self._current_head.slot)
        config = state_machine.config
        self._justified_checkpoint = Checkpoint.create(
            epoch=compute_epoch_at_slot(justified.slot,
                                        config.SLOTS_PER_EPOCH),
            root=justified.hash_tree_root,
        )
        self._finalized_checkpoint = Checkpoint.create(
            epoch=compute_epoch_at_slot(finalized.slot,
                                        config.SLOTS_PER_EPOCH),
            root=finalized.hash_tree_root,
        )
Exemple #10
0
def _find_collision(state, config, validator_index, epoch, block_producer):
    """
    Given a target epoch, make the attestation expected for the
    validator w/ the given ``validator_index``.
    """
    for committee, committee_index, slot in iterate_committees_at_epoch(
            state, epoch, config):
        if slot >= state.slot:
            # do not make attestations in the future
            return {}

        if validator_index in committee:
            # TODO(ralexstokes) refactor w/ tools/builder
            block = block_producer(slot)
            root = block.message.hash_tree_root
            attestation_data = AttestationData.create(
                slot=slot,
                index=committee_index,
                target=Checkpoint.create(epoch=epoch, root=root),
                beacon_block_root=root,
            )
            committee_count = len(committee)
            aggregation_bits = bitfield.get_empty_bitfield(committee_count)
            for i in range(committee_count):
                aggregation_bits = bitfield.set_voted(aggregation_bits, i)

            return {
                index: (slot, (aggregation_bits, attestation_data))
                for index in committee
            }
    else:
        raise Exception("should have found a duplicate validator")
Exemple #11
0
def _mk_attestation_inputs_in_epoch(epoch, block_producer, state, config):
    for committee, committee_index, slot in iterate_committees_at_epoch(
            state, epoch, config):
        if not committee:
            # empty committee this slot
            continue

        if slot >= state.slot:
            # do not make attestations in the future
            break

        block = block_producer(slot)
        root = block.message.hash_tree_root
        attestation_data = AttestationData.create(
            slot=slot,
            index=committee_index,
            target=Checkpoint.create(epoch=epoch, root=root),
            beacon_block_root=root,
        )
        committee_size = len(committee)
        aggregation_bits = bitfield.get_empty_bitfield(committee_size)
        for index in range(committee_size):
            aggregation_bits = bitfield.set_voted(aggregation_bits, index)
            for index in committee:
                yield (
                    index,
                    (attestation_data.slot, (aggregation_bits,
                                             attestation_data)),
                )
Exemple #12
0
    def __init__(
        self,
        finalized_block_node: BlockNode[BaseBeaconBlock],
        justified_checkpoint: Checkpoint,
        justified_state: BeaconState,
        config: Eth2Config,
        block_sink: BlockSink,
    ) -> None:
        self._config = config
        finalized_checkpoint = Checkpoint.create(
            epoch=compute_epoch_at_slot(finalized_block_node.slot,
                                        config.SLOTS_PER_EPOCH),
            root=finalized_block_node.root,
        )
        self._impl = ProtoArrayForkChoice(
            finalized_block_node,
            finalized_checkpoint,
            justified_checkpoint,
            block_sink,
            config,
        )
        self._justified = justified_checkpoint
        self._finalized = finalized_checkpoint

        self.update_justified(justified_state)
Exemple #13
0
def create_signed_attestation_at_slot(
    state: BeaconState,
    config: Eth2Config,
    state_machine: BaseBeaconStateMachine,
    attestation_slot: Slot,
    beacon_block_root: SigningRoot,
    validator_privkeys: Dict[ValidatorIndex, int],
    committee: Tuple[ValidatorIndex, ...],
    committee_index: CommitteeIndex,
    attesting_indices: Sequence[CommitteeValidatorIndex],
) -> Attestation:
    """
    Create the attestations of the given ``attestation_slot`` slot with ``validator_privkeys``.
    """
    state_transition = state_machine.state_transition
    state = state_transition.apply_state_transition(
        state, future_slot=attestation_slot)

    target_epoch = compute_epoch_at_slot(attestation_slot,
                                         config.SLOTS_PER_EPOCH)

    target_root = _get_target_root(state, config, beacon_block_root)

    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=state.current_justified_checkpoint.root,
        ),
        target=Checkpoint.create(root=target_root, epoch=target_epoch),
    )

    return _create_mock_signed_attestation(
        state,
        attestation_data,
        attestation_slot,
        committee,
        len(committee),
        keymapper(lambda index: state.validators[index].pubkey,
                  validator_privkeys),
        config.SLOTS_PER_EPOCH,
        is_for_simulation=False,
        attesting_indices=attesting_indices,
    )
Exemple #14
0
def _get_target_checkpoint(state: BeaconState, head_root: Root,
                           config: Eth2Config) -> Checkpoint:
    epoch = state.current_epoch(config.SLOTS_PER_EPOCH)
    start_slot = compute_start_slot_at_epoch(epoch, config.SLOTS_PER_EPOCH)
    if start_slot == state.slot:
        root = head_root
    else:
        root = get_block_root_at_slot(state, start_slot,
                                      config.SLOTS_PER_HISTORICAL_ROOT)
    return Checkpoint.create(epoch=epoch, root=root)
Exemple #15
0
 def from_genesis(cls, genesis_state: BeaconState, config: Eth2Config,
                  block_sink: BlockSink) -> "LMDGHOSTForkChoice":
     # NOTE: patch up genesis state to reflect the genesis block as an initial checkpoint
     # this only has to be patched once at genesis
     genesis_block = get_genesis_block(genesis_state.hash_tree_root,
                                       BeaconBlock)
     genesis_block_node = _block_to_block_node(genesis_block)
     justified_checkpoint = Checkpoint.create()
     return cls(genesis_block_node, justified_checkpoint, genesis_state,
                config, block_sink)
Exemple #16
0
def create_atteatsion_data(
    state: BeaconState,
    config: Eth2Config,
    state_machine: BaseBeaconStateMachine,
    attestation_slot: Slot,
    beacon_block_root: Root,
    committee_index: CommitteeIndex,
) -> AttestationData:
    target_epoch = compute_epoch_at_slot(attestation_slot, config.SLOTS_PER_EPOCH)

    target_root = _get_target_root(state, config, beacon_block_root)

    return AttestationData.create(
        slot=attestation_slot,
        index=committee_index,
        beacon_block_root=beacon_block_root,
        source=Checkpoint.create(
            epoch=state.current_justified_checkpoint.epoch,
            root=state.current_justified_checkpoint.root,
        ),
        target=Checkpoint.create(root=target_root, epoch=target_epoch),
    )
def test_validate_attestation_data(
    genesis_state,
    sample_attestation_data_params,
    attestation_source_epoch,
    attestation_target_epoch,
    current_epoch,
    previous_justified_epoch,
    current_justified_epoch,
    slots_per_epoch,
    config,
    is_valid,
):
    state = genesis_state.mset(
        "slot",
        compute_start_slot_at_epoch(current_epoch, slots_per_epoch) + 5,
        "previous_justified_checkpoint",
        Checkpoint.create(epoch=previous_justified_epoch),
        "current_justified_checkpoint",
        Checkpoint.create(epoch=current_justified_epoch),
    )
    target_slot = compute_start_slot_at_epoch(current_epoch, config.SLOTS_PER_EPOCH)
    committee_index = 0

    attestation_data = AttestationData.create(**sample_attestation_data_params).mset(
        "slot",
        target_slot,
        "index",
        committee_index,
        "source",
        Checkpoint.create(epoch=attestation_source_epoch),
        "target",
        Checkpoint.create(epoch=attestation_target_epoch),
    )

    if is_valid:
        _validate_attestation_data(state, attestation_data, config)
    else:
        with pytest.raises(ValidationError):
            _validate_attestation_data(state, attestation_data, config)
Exemple #18
0
def test_chaindb_get_justified_head(
    chaindb_at_genesis,
    genesis_block,
    genesis_state,
    sample_beacon_block_params,
    fork_choice_scoring,
    config,
):
    chaindb = chaindb_at_genesis
    block = SignedBeaconBlock.from_parent(genesis_block,
                                          FromBlockParams(slot=1))

    assert chaindb.get_finalized_head(genesis_block.__class__) == genesis_block
    assert chaindb.get_justified_head(genesis_block.__class__) == genesis_block

    # test that there is only one justified head per epoch
    state_with_bad_epoch = genesis_state.set(
        "current_justified_checkpoint",
        Checkpoint.create(root=block.message.hash_tree_root,
                          epoch=config.GENESIS_EPOCH),
    )
    chaindb.persist_state(state_with_bad_epoch)
    chaindb.persist_block(block, SignedBeaconBlock, fork_choice_scoring)

    assert chaindb.get_finalized_head(genesis_block.__class__) == genesis_block
    assert chaindb.get_justified_head(genesis_block.__class__) == genesis_block

    # test that the we can update justified head if we satisfy the invariants
    state_with_justified_block = genesis_state.set(
        "current_justified_checkpoint",
        Checkpoint.create(root=block.message.hash_tree_root,
                          epoch=config.GENESIS_EPOCH + 1),
    )
    chaindb.persist_state(state_with_justified_block)

    assert chaindb.get_finalized_head(genesis_block.__class__) == genesis_block
    assert (chaindb.get_justified_head(SignedBeaconBlock).message.
            hash_tree_root == block.message.hash_tree_root)
Exemple #19
0
def _mk_pending_attestation(
    bitfield: Bitfield = default_bitfield,
    target_root: Root = ZERO_ROOT,
    target_epoch: Epoch = default_epoch,
    slot: Slot = default_slot,
    committee_index: CommitteeIndex = default_committee_index,
) -> PendingAttestation:
    return PendingAttestation.create(
        aggregation_bits=bitfield,
        data=AttestationData.create(
            slot=slot,
            index=committee_index,
            target=Checkpoint.create(epoch=target_epoch, root=target_root),
        ),
    )
Exemple #20
0
def _mk_attestation_for_block_with_committee(block, committee, committee_index,
                                             config):
    committee_count = len(committee)
    aggregation_bits = bitfield.get_empty_bitfield(committee_count)
    for index in range(committee_count):
        aggregation_bits = bitfield.set_voted(aggregation_bits, index)

    attestation = Attestation.create(
        aggregation_bits=aggregation_bits,
        data=AttestationData.create(
            slot=block.slot,
            index=committee_index,
            beacon_block_root=block.message.hash_tree_root,
            target=Checkpoint.create(epoch=compute_epoch_at_slot(
                block.slot, config.SLOTS_PER_EPOCH)),
        ),
    )
    return attestation
Exemple #21
0
    def from_db(cls, chain_db: BaseBeaconChainDB, config: Eth2Config,
                block_sink: BlockSink) -> "LMDGHOSTForkChoice":
        canonical_head = chain_db.get_canonical_head(BeaconBlock)
        justified_head = chain_db.get_justified_head(BeaconBlock)
        finalized_head = chain_db.get_finalized_head(BeaconBlock)

        assert canonical_head.slot >= justified_head.slot >= finalized_head.slot

        finalized_head_node = _block_to_block_node(finalized_head)
        justified_checkpoint = Checkpoint.create(
            epoch=compute_epoch_at_slot(justified_head.slot,
                                        config.SLOTS_PER_EPOCH),
            root=justified_head.hash_tree_root,
        )
        justified_state = chain_db.get_state_by_root(justified_head.state_root,
                                                     BeaconState, config)
        fork_choice = cls(
            finalized_head_node,
            justified_checkpoint,
            justified_state,
            config,
            block_sink,
        )

        is_consistent_with_justified = False
        parent_root = canonical_head.parent_root
        chain: Tuple[BaseBeaconBlock, ...] = (canonical_head, )
        while parent_root != finalized_head.hash_tree_root:
            if parent_root == justified_head.hash_tree_root:
                is_consistent_with_justified = True
            parent = chain_db.get_block_by_root(parent_root, BeaconBlock)
            chain += (parent, )
            parent_root = parent.parent_root

        assert is_consistent_with_justified

        for block in reversed(chain):
            fork_choice.on_block(block)

        return fork_choice
Exemple #22
0
def test_chaindb_get_finalized_head(
    chaindb_at_genesis,
    genesis_block,
    genesis_state,
    sample_beacon_block_params,
    fork_choice_scoring,
):
    chaindb = chaindb_at_genesis
    block = BeaconBlock.create(**sample_beacon_block_params).set(
        "parent_root", genesis_block.signing_root)

    assert chaindb.get_finalized_head(genesis_block.__class__) == genesis_block
    assert chaindb.get_justified_head(genesis_block.__class__) == genesis_block

    state_with_finalized_block = genesis_state.set(
        "finalized_checkpoint", Checkpoint.create(root=block.signing_root))
    chaindb.persist_state(state_with_finalized_block)
    chaindb.persist_block(block, BeaconBlock, fork_choice_scoring)

    assert chaindb.get_finalized_head(
        BeaconBlock).signing_root == block.signing_root
    assert chaindb.get_justified_head(genesis_block.__class__) == genesis_block
def _determine_new_justified_checkpoint_and_bitfield(
        state: BeaconState, config: Eth2Config) -> Tuple[Checkpoint, Bitfield]:
    (
        new_current_justified_epoch,
        justification_bits,
    ) = _determine_new_justified_epoch_and_bitfield(state, config)

    if new_current_justified_epoch != state.current_justified_checkpoint.epoch:
        new_current_justified_root = get_block_root(
            state,
            new_current_justified_epoch,
            config.SLOTS_PER_EPOCH,
            config.SLOTS_PER_HISTORICAL_ROOT,
        )
    else:
        new_current_justified_root = state.current_justified_checkpoint.root

    return (
        Checkpoint.create(epoch=new_current_justified_epoch,
                          root=new_current_justified_root),
        justification_bits,
    )
def test_get_unslashed_attesting_indices(genesis_state, config):
    state = genesis_state.set(
        "slot", compute_start_slot_at_epoch(3, config.SLOTS_PER_EPOCH)
    )
    target_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)
    target_slot = compute_start_slot_at_epoch(target_epoch, config.SLOTS_PER_EPOCH)
    committee_index = 0
    some_committee = get_beacon_committee(
        state, target_slot, committee_index, CommitteeConfig(config)
    )

    data = AttestationData.create(
        slot=state.slot,
        index=committee_index,
        target=Checkpoint.create(epoch=target_epoch),
    )
    some_subset_count = random.randrange(1, len(some_committee) // 2)
    some_subset = random.sample(some_committee, some_subset_count)

    bitfield = get_empty_bitfield(len(some_committee))
    for i, index in enumerate(some_committee):
        if index in some_subset:
            if random.choice([True, False]):
                state = state.transform(["validators", index, "slashed"], True)
            bitfield = set_voted(bitfield, i)

    some_subset = tuple(
        filter(lambda index: not state.validators[index].slashed, some_subset)
    )

    indices = get_unslashed_attesting_indices(
        state,
        (PendingAttestation.create(data=data, aggregation_bits=bitfield),),
        CommitteeConfig(config),
    )

    assert set(indices) == set(some_subset)
    assert len(indices) == len(some_subset)
Exemple #25
0
def test_chaindb_get_finalized_head(
    chaindb_at_genesis,
    genesis_block,
    genesis_state,
    sample_beacon_block_params,
    fork_choice_scoring,
):
    chaindb = chaindb_at_genesis
    block = SignedBeaconBlock.from_parent(genesis_block,
                                          FromBlockParams(slot=1))

    assert chaindb.get_finalized_head(genesis_block.__class__) == genesis_block
    assert chaindb.get_justified_head(genesis_block.__class__) == genesis_block

    state_with_finalized_block = genesis_state.set(
        "finalized_checkpoint",
        Checkpoint.create(root=block.message.hash_tree_root))
    chaindb.persist_state(state_with_finalized_block)
    chaindb.persist_block(block, SignedBeaconBlock, fork_choice_scoring)

    assert (chaindb.get_finalized_head(SignedBeaconBlock).message.
            hash_tree_root == block.message.hash_tree_root)
    assert chaindb.get_justified_head(genesis_block.__class__) == genesis_block
Exemple #26
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)
Exemple #27
0
 def finalized_checkpoint(self) -> Checkpoint:
     return Checkpoint.create(root=self.finalized_root,
                              epoch=self.finalized_epoch)
Exemple #28
0
def test_lmd_ghost_fork_choice_scoring(
    sample_beacon_block_params,
    chaindb_at_genesis,
    # see note below on how this is used
    fork_choice_scoring,
    forking_descriptor,
    forking_asymmetry,
    genesis_state,
    genesis_block,
    config,
):
    """
    Given some blocks and some attestations, can we score them correctly?
    """
    chain_db = chaindb_at_genesis
    root_block = chain_db.get_canonical_head(SignedBeaconBlock)

    some_epoch = 3
    some_slot_offset = 10

    state = genesis_state.mset(
        "slot",
        compute_start_slot_at_epoch(some_epoch, config.SLOTS_PER_EPOCH) +
        some_slot_offset,
        "current_justified_checkpoint",
        Checkpoint.create(epoch=some_epoch,
                          root=root_block.message.hash_tree_root),
    )
    assert some_epoch >= state.current_justified_checkpoint.epoch

    # NOTE: the attestations have to be aligned to the blocks which start from ``base_slot``.
    base_slot = compute_start_slot_at_epoch(some_epoch,
                                            config.SLOTS_PER_EPOCH) + 1
    block_tree = _build_block_tree(
        sample_beacon_block_params,
        root_block,
        base_slot,
        forking_descriptor,
        forking_asymmetry,
        config,
    )

    slot_count = len(forking_descriptor)
    committee_sampling_fraction = 1
    committees_by_slot = tuple(
        _get_committees(state, base_slot +
                        slot_offset, config, committee_sampling_fraction)
        for slot_offset in range(slot_count))

    _attach_committees_to_block_tree(state, block_tree, committees_by_slot,
                                     config, forking_asymmetry)

    _attach_attestations_to_block_tree_with_committees(block_tree, config)

    context = Context.from_genesis(genesis_state, genesis_block)
    store = Store(chain_db, SignedBeaconBlock, config, context)

    score_index = _build_score_index_from_decorated_block_tree(
        block_tree, store, state, config)

    for block in _iter_block_tree_by_block(block_tree):
        # NOTE: we use the ``fork_choice_scoring`` fixture, it doesn't matter for this test
        chain_db.persist_block(block, SignedBeaconBlock, fork_choice_scoring)

    for block in _iter_block_tree_by_block(block_tree):
        score = store.scoring(block)
        expected_score = score_index[block.message.hash_tree_root]
        assert score == expected_score
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
def test_get_attestation_deltas(
    genesis_state,
    config,
    slots_per_epoch,
    target_committee_size,
    max_committees_per_slot,
    min_attestation_inclusion_delay,
    inactivity_penalty_quotient,
    finalized_epoch,
    current_slot,
    sample_pending_attestation_record_params,
    sample_attestation_data_params,
):

    state = genesis_state.mset(
        "slot",
        current_slot,
        "finalized_checkpoint",
        Checkpoint.create(epoch=finalized_epoch),
    )
    previous_epoch = state.previous_epoch(config.SLOTS_PER_EPOCH,
                                          config.GENESIS_EPOCH)
    has_inactivity_penalty = (previous_epoch - finalized_epoch >
                              config.MIN_EPOCHS_TO_INACTIVITY_PENALTY)

    indices_to_check = set()

    prev_epoch_attestations = tuple()

    for committee, committee_index, slot in iterate_committees_at_epoch(
            state, previous_epoch, config):
        participants_bitfield = get_empty_bitfield(len(committee))
        for i, index in enumerate(committee):
            indices_to_check.add(index)
            participants_bitfield = set_voted(participants_bitfield, i)
        prev_epoch_attestations += (PendingAttestation.create(
            **sample_pending_attestation_record_params).mset(
                "aggregation_bits",
                participants_bitfield,
                "inclusion_delay",
                min_attestation_inclusion_delay,
                "proposer_index",
                get_beacon_proposer_index(state.set("slot", slot),
                                          CommitteeConfig(config)),
                "data",
                AttestationData.create(**sample_attestation_data_params).mset(
                    "slot",
                    slot,
                    "index",
                    committee_index,
                    "beacon_block_root",
                    get_block_root_at_slot(state, slot,
                                           config.SLOTS_PER_HISTORICAL_ROOT),
                    "target",
                    Checkpoint.create(
                        epoch=previous_epoch,
                        root=get_block_root(
                            state,
                            previous_epoch,
                            config.SLOTS_PER_EPOCH,
                            config.SLOTS_PER_HISTORICAL_ROOT,
                        ),
                    ),
                ),
            ), )
    state = state.set("previous_epoch_attestations", prev_epoch_attestations)

    rewards_received, penalties_received = get_attestation_deltas(
        state, config)
    if has_inactivity_penalty:
        assert sum(penalties_received) > 0
    else:
        assert sum(penalties_received) == 0
    assert all(reward > 0 for reward in rewards_received)