Esempio n. 1
0
def test_get_block_committees_info(monkeypatch, sample_block, sample_state,
                                   num_validators, committee,
                                   parent_block_number, result_proposer_index,
                                   epoch_length):
    from eth.beacon import helpers

    def mock_get_shard_committees_at_slot(state, slot, epoch_length):
        return (ShardCommittee(
            shard=1,
            committee=committee,
            total_validator_count=num_validators,
        ), )

    monkeypatch.setattr(helpers, 'get_shard_committees_at_slot',
                        mock_get_shard_committees_at_slot)

    parent_block = sample_block
    parent_block = sample_block.copy(slot=parent_block_number, )

    if isinstance(result_proposer_index, Exception):
        with pytest.raises(ValidationError):
            get_block_committees_info(
                parent_block,
                sample_state,
                epoch_length,
            )
    else:
        block_committees_info = get_block_committees_info(
            parent_block,
            sample_state,
            epoch_length,
        )
        assert (block_committees_info.proposer_index == result_proposer_index)
Esempio n. 2
0
def test_get_block_committees_info(monkeypatch, genesis_block,
                                   genesis_crystallized_state, committee,
                                   parent_block_number,
                                   result_proposer_index_in_committee,
                                   cycle_length):
    from eth.beacon import helpers

    def mock_get_shards_and_committees_for_slot(parent_block,
                                                crystallized_state,
                                                cycle_length):
        return [
            ShardAndCommittee(shard_id=1, committee=committee),
        ]

    monkeypatch.setattr(helpers, 'get_shards_and_committees_for_slot',
                        mock_get_shards_and_committees_for_slot)

    parent_block = genesis_block
    parent_block = genesis_block.copy(slot_number=parent_block_number, )

    if isinstance(result_proposer_index_in_committee, Exception):
        with pytest.raises(ValueError):
            get_block_committees_info(
                parent_block,
                genesis_crystallized_state,
                cycle_length,
            )
    else:
        block_committees_info = get_block_committees_info(
            parent_block,
            genesis_crystallized_state,
            cycle_length,
        )
        assert (block_committees_info.proposer_index_in_committee ==
                result_proposer_index_in_committee)
Esempio n. 3
0
    def attest_proposed_block(cls, post_crystallized_state: CrystallizedState,
                              post_active_state: ActiveState,
                              block_proposal: 'BlockProposal',
                              chaindb: BaseBeaconChainDB,
                              private_key: int) -> 'AttestationRecord':
        """
        Return the initial attestation by the block proposer.

        The proposer broadcasts their attestation with the proposed block.
        """
        block_committees_info = get_block_committees_info(
            block_proposal.block,
            post_crystallized_state,
            cls.config.CYCLE_LENGTH,
        )
        # Vote
        attester_bitfield = set_voted(
            get_empty_bitfield(block_committees_info.proposer_committee_size),
            block_committees_info.proposer_index_in_committee,
        )

        # Get justified_slot and justified_block_hash
        justified_slot = post_crystallized_state.last_justified_slot
        justified_block_hash = chaindb.get_canonical_block_hash_by_slot(
            justified_slot)

        # Get signing message and sign it
        parent_hashes = get_hashes_to_sign(
            post_active_state.recent_block_hashes,
            block_proposal.block,
            cls.config.CYCLE_LENGTH,
        )

        message = create_signing_message(
            block_proposal.block.slot_number,
            parent_hashes,
            block_proposal.shard_id,
            block_proposal.shard_block_hash,
            justified_slot,
        )
        sig = bls.sign(
            message,
            private_key,
        )

        return cls.get_attestation_record_class()(
            slot=block_proposal.block.slot_number,
            shard_id=block_proposal.shard_id,
            oblique_parent_hashes=(),
            shard_block_hash=block_proposal.shard_block_hash,
            attester_bitfield=attester_bitfield,
            justified_slot=justified_slot,
            justified_block_hash=justified_block_hash,
            aggregate_sig=sig,
        )
Esempio n. 4
0
def attestation_validation_fixture(fixture_sm_class, initial_chaindb,
                                   genesis_block, privkeys):
    # NOTE: Copied from `test_proposer.py`, might need to refactor it.

    chaindb = initial_chaindb

    # Propose a block
    block_1_shell = genesis_block.copy(
        parent_hash=genesis_block.hash,
        slot_number=genesis_block.slot_number + 1,
    )
    sm = fixture_sm_class(chaindb, block_1_shell)

    # The proposer of block_1
    block_committees_info = (get_block_committees_info(
        block_1_shell,
        sm.crystallized_state,
        sm.config.CYCLE_LENGTH,
    ))
    # public_key = sm.crystallized_state.validators[block_committees_info.proposer_index].pubkey
    private_key = privkeys[block_committees_info.proposer_index]
    block_proposal = BlockProposal(
        block=block_1_shell,
        shard_id=block_committees_info.proposer_shard_id,
        shard_block_hash=ZERO_HASH32,
    )

    (block_1, post_crystallized_state, post_active_state,
     proposer_attestation) = (sm.propose_block(
         crystallized_state=sm.crystallized_state,
         active_state=sm.active_state,
         block_proposal=block_proposal,
         chaindb=sm.chaindb,
         config=sm.config,
         private_key=private_key,
     ))

    # Block 2
    # Manually update state for testing
    sm._update_the_states(post_crystallized_state, post_active_state)

    # Validate the attestation
    block_2_shell = block_1.copy(
        parent_hash=block_1.hash,
        slot_number=block_1.slot_number + 1,
        attestations=[proposer_attestation],
    )
    recent_block_hashes = get_new_recent_block_hashes(
        sm.active_state.recent_block_hashes, block_1.slot_number,
        block_2_shell.slot_number, block_1.hash)
    filled_active_state = sm.active_state.copy(
        recent_block_hashes=recent_block_hashes, )

    return (post_crystallized_state, filled_active_state, proposer_attestation,
            block_2_shell, block_1, sm.chaindb)
Esempio n. 5
0
def validate_parent_block_proposer(crystallized_state: 'CrystallizedState',
                                   block: 'BaseBeaconBlock',
                                   parent_block: 'BaseBeaconBlock',
                                   cycle_length: int) -> None:
    if block.slot_number == 0:
        return

    block_committees_info = get_block_committees_info(
        parent_block,
        crystallized_state,
        cycle_length,
    )

    try:
        attestation = block.attestations[0]
    except IndexError:
        raise ValidationError("block.attestations should not be an empty list")

    is_proposer_attestation = (
        attestation.shard_id == block_committees_info.proposer_shard_id
        and attestation.slot == parent_block.slot_number
        and has_voted(attestation.attester_bitfield,
                      block_committees_info.proposer_index_in_committee))
    if not is_proposer_attestation:
        raise ValidationError(
            "Proposer of parent block should be one of the attesters in block.attestions[0]:\n"
            "\tExpected: proposer index in committee: %d, shard_id: %d, slot: %d\n"
            "\tFound: shard_id: %d, slot: %d, voted: %s" % (
                block_committees_info.proposer_index_in_committee,
                block_committees_info.proposer_shard_id,
                parent_block.slot_number,
                attestation.shard_id,
                attestation.slot,
                has_voted(
                    attestation.attester_bitfield,
                    block_committees_info.proposer_index_in_committee,
                ),
            ))
Esempio n. 6
0
def test_propose_block(fixture_sm_class,
                       initial_chaindb,
                       genesis_block,
                       privkeys):
    chaindb = initial_chaindb

    # Propose a block
    block_1_shell = genesis_block.copy(
        parent_hash=genesis_block.hash,
        slot_number=genesis_block.slot_number + 1,
    )
    sm = fixture_sm_class(chaindb, block_1_shell)

    #
    # The proposer of block_1
    #
    block_committees_info = (
        get_block_committees_info(
            block_1_shell,
            sm.crystallized_state,
            sm.config.CYCLE_LENGTH,
        )
    )
    private_key = privkeys[block_committees_info.proposer_index]
    block_proposal = BlockProposal(
        block=block_1_shell,
        shard_id=block_committees_info.proposer_shard_id,
        shard_block_hash=ZERO_HASH32,
    )

    (block_1, post_crystallized_state, post_active_state, proposer_attestation) = (
        sm.propose_block(
            crystallized_state=sm.crystallized_state,
            active_state=sm.active_state,
            block_proposal=block_proposal,
            chaindb=sm.chaindb,
            config=sm.config,
            private_key=private_key,
        )
    )
    expect_block_1 = block_1_shell.copy(
        active_state_root=post_active_state.hash,
        crystallized_state_root=post_crystallized_state.hash,
    )
    assert block_1.hash == expect_block_1.hash

    # Persist block_1
    sm.import_block(block_1)
    sm.chaindb.persist_block(block_1)

    # Validate the attestation
    block_2_shell = block_1.copy(
        parent_hash=block_1.hash,
        slot_number=block_1.slot_number + 1,
        attestations=(proposer_attestation, ),
    )

    # Validate the parent block proposer
    validate_parent_block_proposer(
        sm.crystallized_state,
        block_2_shell,
        block_1,
        sm.config.CYCLE_LENGTH,
    )

    assert has_voted(
        proposer_attestation.attester_bitfield,
        block_committees_info.proposer_index_in_committee
    )

    #
    # The proposer of block_2
    #
    block_committees_info = (
        get_block_committees_info(
            block_2_shell,
            sm.crystallized_state,
            sm.config.CYCLE_LENGTH,
        )
    )
    private_key = privkeys[block_committees_info.proposer_index]
    block_proposal = BlockProposal(
        block=block_2_shell,
        shard_id=block_committees_info.proposer_shard_id,
        shard_block_hash=ZERO_HASH32,
    )

    (block_2, post_crystallized_state, post_active_state, proposer_attestation) = (
        sm.propose_block(
            crystallized_state=sm.crystallized_state,
            active_state=sm.active_state,
            block_proposal=block_proposal,
            chaindb=sm.chaindb,
            config=sm.config,
            private_key=private_key,
        )
    )
    expect_block_2 = block_2_shell.copy(
        active_state_root=post_active_state.hash,
        crystallized_state_root=post_crystallized_state.hash,
    )
    assert block_2.hash == expect_block_2.hash