Esempio n. 1
0
def test_update_attestations(sample_attestation_params, sample_beacon_block_params):
    block = BeaconBlock(**sample_beacon_block_params)
    attestations = block.body.attestations
    attestations = list(attestations)
    attestations.append(Attestation(**sample_attestation_params))
    body2 = block.body.copy(attestations=attestations)
    block2 = block.copy(body=body2)
    assert len(block2.body.attestations) == 1
Esempio n. 2
0
def test_validate_proposer_signature(
        slots_per_epoch,
        shard_count,
        proposer_privkey,
        proposer_pubkey,
        is_valid_signature,
        sample_beacon_block_params,
        sample_beacon_state_params,
        target_committee_size,
        max_effective_balance,
        config):

    state = BeaconState(**sample_beacon_state_params).copy(
        validators=tuple(
            create_mock_validator(proposer_pubkey, config)
            for _ in range(10)
        ),
        balances=(max_effective_balance,) * 10,
    )

    block = BeaconBlock(**sample_beacon_block_params)
    header = block.header

    proposed_block = block.copy(
        signature=bls.sign(
            message_hash=header.signing_root,
            privkey=proposer_privkey,
            domain=get_domain(
                state,
                SignatureDomain.DOMAIN_BEACON_PROPOSER,
                slots_per_epoch,
            ),
        ),
    )

    if is_valid_signature:
        validate_proposer_signature(
            state,
            proposed_block,
            CommitteeConfig(config),
        )
    else:
        with pytest.raises(ValidationError):
            validate_proposer_signature(
                state,
                proposed_block,
                CommitteeConfig(config),
            )
Esempio n. 3
0
def test_validate_serenity_proposer_signature(
        proposer_privkey, proposer_pubkey, is_valid_signature,
        sample_beacon_block_params, sample_beacon_state_params,
        sample_shard_committee_params, beacon_chain_shard_number, epoch_length,
        max_deposit):

    state = BeaconState(**sample_beacon_state_params).copy(
        validator_registry=tuple(
            mock_validator_record(proposer_pubkey) for _ in range(10)),
        validator_balances=(max_deposit * GWEI_PER_ETH, ) * 10,
        shard_committees_at_slots=get_sample_shard_committees_at_slots(
            num_slot=128,
            num_shard_committee_per_slot=10,
            sample_shard_committee_params=sample_shard_committee_params,
        ),
    )

    default_block = BeaconBlock(**sample_beacon_block_params)
    empty_signature_block_root = default_block.block_without_signature_root

    proposal_root = ProposalSignedData(
        state.slot,
        beacon_chain_shard_number,
        empty_signature_block_root,
    ).root

    proposed_block = BeaconBlock(**sample_beacon_block_params).copy(
        signature=bls.sign(
            message=proposal_root,
            privkey=proposer_privkey,
            domain=SignatureDomain.DOMAIN_PROPOSAL,
        ), )

    if is_valid_signature:
        validate_serenity_proposer_signature(
            state,
            proposed_block,
            beacon_chain_shard_number,
            epoch_length,
        )
    else:
        with pytest.raises(ValidationError):
            validate_serenity_proposer_signature(
                state,
                proposed_block,
                beacon_chain_shard_number,
                epoch_length,
            )
Esempio n. 4
0
def _mk_block(block_params, slot, parent, block_offset):
    return BeaconBlock(**block_params).copy(
        slot=slot,
        parent_root=parent.signing_root,
        # mix in something unique
        state_root=block_offset.to_bytes(32, byteorder="big"),
    )
Esempio n. 5
0
async def test_get_blocks_from_canonical_chain_by_slot(
    monkeypatch, db_block_slots, slot_of_requested_blocks, expected_block_slots
):
    node = NodeFactory()

    # Mock up block database
    mock_slot_to_block_db = {
        slot: BeaconBlock(
            slot=slot,
            parent_root=ZERO_HASH32,
            state_root=ZERO_HASH32,
            signature=EMPTY_SIGNATURE,
            body=BeaconBlockBody(),
        )
        for slot in db_block_slots
    }

    def get_canonical_block_by_slot(slot):
        if slot in mock_slot_to_block_db:
            return mock_slot_to_block_db[slot]
        else:
            raise BlockNotFound

    monkeypatch.setattr(
        node.chain, "get_canonical_block_by_slot", get_canonical_block_by_slot
    )

    result_blocks = node._get_blocks_from_canonical_chain_by_slot(
        slot_of_requested_blocks=slot_of_requested_blocks
    )

    expected_blocks = [mock_slot_to_block_db[slot] for slot in expected_block_slots]
    assert len(result_blocks) == len(expected_blocks)
    assert set(result_blocks) == set(expected_blocks)
Esempio n. 6
0
def create_block_proposal(
    slot: Slot,
    parent_root: Root,
    randao_reveal: BLSSignature,
    eth1_data: Eth1Data,
    attestations: Sequence[Attestation],
    state: BeaconState,
    state_machine: BaseBeaconStateMachine,
) -> BeaconBlock:
    config = state_machine.config
    state_at_slot, _ = state_machine.apply_state_transition(state,
                                                            future_slot=slot)
    proposer_index = get_beacon_proposer_index(state_at_slot, config)

    block_body = BeaconBlockBody.create(randao_reveal=randao_reveal,
                                        eth1_data=eth1_data,
                                        attestations=attestations)
    proposal = BeaconBlock.create(
        slot=slot,
        parent_root=parent_root,
        body=block_body,
        proposer_index=proposer_index,
    )
    block_with_empty_signature = SignedBeaconBlock.create(
        message=proposal, signature=EMPTY_SIGNATURE)
    post_state, block_with_state_root = state_machine.apply_state_transition(
        state, block_with_empty_signature, check_proposer_signature=False)
    return block_with_state_root.message
def test_ensure_update_eth1_vote_if_exists(genesis_state, config,
                                           vote_offsets):
    # one less than a majority is the majority divided by 2
    threshold = config.SLOTS_PER_ETH1_VOTING_PERIOD // 2
    data_votes = tuple(
        concat((Eth1Data.create(block_hash=(i).to_bytes(32, "little")), ) *
               (threshold + offset) for i, offset in enumerate(vote_offsets)))
    state = genesis_state

    for vote in data_votes:
        state = process_eth1_data(
            state,
            BeaconBlock.create(body=BeaconBlockBody.create(eth1_data=vote)),
            config,
        )

    if not vote_offsets:
        assert state.eth1_data == genesis_state.eth1_data

    # we should update the 'latest' entry if we have a majority
    for offset in vote_offsets:
        if offset <= 0:
            assert genesis_state.eth1_data == state.eth1_data
        else:
            assert state.eth1_data == data_votes[0]
def test_process_eth1_data(
    original_votes,
    block_data,
    expected_votes,
    sample_beacon_state_params,
    sample_beacon_block_params,
    sample_beacon_block_body_params,
    config,
):
    eth1_data_votes = tuple(mapcat(_expand_eth1_votes, original_votes))
    state = BeaconState.create(**sample_beacon_state_params).set(
        "eth1_data_votes", eth1_data_votes)

    block_body = BeaconBlockBody.create(
        **sample_beacon_block_body_params).mset(
            "eth1_data", Eth1Data.create(block_hash=block_data))

    block = BeaconBlock.create(**sample_beacon_block_params).set(
        "body", block_body)

    updated_state = process_eth1_data(state, block, config)
    updated_votes = updated_state.eth1_data_votes
    expanded_expected_votes = tuple(mapcat(_expand_eth1_votes, expected_votes))

    assert tuple(updated_votes) == expanded_expected_votes
Esempio n. 9
0
def test_process_eth1_data(original_votes,
                           block_data,
                           expected_votes,
                           sample_beacon_state_params,
                           sample_beacon_block_params,
                           sample_beacon_block_body_params,
                           config):
    eth1_data_votes = tuple(mapcat(
        _expand_eth1_votes,
        original_votes,
    ))
    state = BeaconState(**sample_beacon_state_params).copy(
        eth1_data_votes=eth1_data_votes,
    )

    block_body = BeaconBlockBody(**sample_beacon_block_body_params).copy(
        eth1_data=Eth1Data(
            block_hash=block_data,
        ),
    )

    block = BeaconBlock(**sample_beacon_block_params).copy(
        body=block_body,
    )

    updated_state = process_eth1_data(state, block, config)
    updated_votes = updated_state.eth1_data_votes
    expanded_expected_votes = tuple(mapcat(
        _expand_eth1_votes,
        expected_votes,
    ))

    assert updated_votes == expanded_expected_votes
Esempio n. 10
0
def test_process_eth1_data(original_votes,
                           block_data,
                           expected_votes,
                           sample_beacon_state_params,
                           sample_beacon_block_params,
                           sample_beacon_block_body_params):
    eth1_data_votes = tuple(
        Eth1DataVote(data, vote_count)
        for data, vote_count in original_votes
    )
    state = BeaconState(**sample_beacon_state_params).copy(
        eth1_data_votes=eth1_data_votes,
    )

    block_body = BeaconBlockBody(**sample_beacon_block_body_params).copy(
        eth1_data=block_data,
    )

    block = BeaconBlock(**sample_beacon_block_params).copy(
        body=block_body,
    )

    updated_state = process_eth1_data(state, block)
    updated_votes = tuple(
        (vote.eth1_data, vote.vote_count)
        for vote in updated_state.eth1_data_votes
    )
    assert updated_votes == expected_votes
Esempio n. 11
0
 def run_with(
     cls,
     inputs: Tuple[BeaconState, OperationOrBlockHeader],
     config: Optional[Eth2Config],
 ) -> BeaconState:
     state, operation = inputs
     # NOTE: we do not have an easy way to evaluate a single operation on the state
     # So, we wrap it in a beacon block. The following statement lets us rely on
     # the config given in a particular handler class while working w/in the
     # update API provided by `py-ssz`.
     # NOTE: we ignore the type here, otherwise need to spell out each of the keyword
     # arguments individually... save some work and just build them dynamically
     block = BeaconBlock(
         body=BeaconBlockBody(**{f"{cls.name}s": (
             operation, )})  # type: ignore
     )
     try:
         return cls.processor(state, block, config)
     except ValidationError as e:
         # if already a ValidationError, re-raise
         raise e
     except Exception as e:
         # check if the exception is expected...
         for exception in cls.expected_exceptions:
             if isinstance(e, exception):
                 raise ValidationError(e)
         # else raise (and fail the pytest test case ...)
         raise e
Esempio n. 12
0
def test_higher_slot_fork_choice_scoring(sample_beacon_block_params, slot):
    block = BeaconBlock(**sample_beacon_block_params).copy(slot=slot, )

    expected_score = slot

    score = higher_slot_scoring(block)

    assert score == expected_score
Esempio n. 13
0
 async def _get_block_proposal(self, request: web.Request) -> web.Response:
     slot = Slot(int(request.query["slot"]))
     randao_reveal = BLSSignature(
         decode_hex(request.query["randao_reveal"]).ljust(96, b"\x00"))
     block = BeaconBlock.create(
         slot=slot,
         body=BeaconBlockBody.create(randao_reveal=randao_reveal))
     return web.json_response(to_formatted_dict(block))
Esempio n. 14
0
def _mk_minimum_viable_signed_beacon_blocks(slots, state_machine_provider,
                                            state, block):
    for slot in slots:
        message = BeaconBlock.create(slot=slot,
                                     parent_root=block.message.hash_tree_root)
        block = SignedBeaconBlock.create(message=message)
        state, block = state_machine_provider(slot).import_block(block, state)
        yield block
Esempio n. 15
0
async def test_get_blocks_from_fork_chain_by_root(
    monkeypatch, fork_chain_block_slots, slot_of_requested_blocks, expected_block_slots
):
    node = NodeFactory()

    mock_block = BeaconBlock(
        slot=0,
        parent_root=ZERO_HASH32,
        state_root=ZERO_HASH32,
        signature=EMPTY_SIGNATURE,
        body=BeaconBlockBody(),
    )

    # Mock up fork chain block database
    fork_chain_blocks = []
    for slot in fork_chain_block_slots:
        if len(fork_chain_blocks) == 0:
            fork_chain_blocks.append(mock_block.copy(slot=slot))
        else:
            fork_chain_blocks.append(
                mock_block.copy(
                    slot=slot, parent_root=fork_chain_blocks[-1].signing_root
                )
            )
    mock_root_to_block_db = {block.signing_root: block for block in fork_chain_blocks}

    def get_block_by_root(root):
        if root in mock_root_to_block_db:
            return mock_root_to_block_db[root]
        else:
            raise BlockNotFound

    monkeypatch.setattr(node.chain, "get_block_by_root", get_block_by_root)

    requested_blocks = node._get_blocks_from_fork_chain_by_root(
        start_slot=slot_of_requested_blocks[0],
        peer_head_block=fork_chain_blocks[-1],
        slot_of_requested_blocks=slot_of_requested_blocks,
    )

    expected_blocks = [
        block for block in fork_chain_blocks if block.slot in expected_block_slots
    ]
    assert len(requested_blocks) == len(expected_blocks)
    assert set(requested_blocks) == set(expected_blocks)
Esempio n. 16
0
def test_update_attestations(sample_attestation_params,
                             sample_beacon_block_params):
    block = BeaconBlock.create(**sample_beacon_block_params)
    attestations = block.body.attestations
    attestations = list(attestations)
    attestations.append(Attestation.create(**sample_attestation_params))
    body2 = block.body.set("attestations", attestations)
    block2 = block.set("body", body2)
    assert len(block2.body.attestations) == 1
Esempio n. 17
0
def test_higher_slot_fork_choice_scoring(sample_beacon_block_params, slot):
    block = BeaconBlock.create(**sample_beacon_block_params).set("slot", slot)

    expected_score = HigherSlotScore(slot)

    scoring = HigherSlotScoring()
    score = scoring.score(block)

    assert score == expected_score
Esempio n. 18
0
def test_higher_slot_fork_choice_scoring(slot):
    block = BeaconBlock.create(slot=slot)

    expected_score = HigherSlotScore(slot)

    scoring = HigherSlotScoring()
    score = scoring.score(block)

    assert score == expected_score
Esempio n. 19
0
def _mk_block(block_params, slot, parent, block_offset):
    return BeaconBlock.create(**block_params).mset(
        "slot",
        slot,
        "parent_root",
        parent.signing_root,
        # mix in something unique
        "state_root",
        block_offset.to_bytes(32, byteorder="big"),
    )
Esempio n. 20
0
def test_validate_block_slot(sample_beacon_state_params,
                             sample_beacon_block_params, state_slot,
                             block_slot, expected):
    state = BeaconState(**sample_beacon_state_params).copy(slot=state_slot, )
    block = BeaconBlock(**sample_beacon_block_params).copy(slot=block_slot, )
    if isinstance(expected, Exception):
        with pytest.raises(ValidationError):
            validate_block_slot(state, block)
    else:
        validate_block_slot(state, block)
Esempio n. 21
0
def test_validate_proposer_signature(
        slots_per_epoch, shard_count, proposer_privkey, proposer_pubkey,
        is_valid_signature, sample_beacon_block_params,
        sample_beacon_state_params, beacon_chain_shard_number, genesis_epoch,
        target_committee_size, max_deposit_amount, config):

    state = BeaconState(**sample_beacon_state_params).copy(
        validator_registry=tuple(
            mock_validator_record(proposer_pubkey, config) for _ in range(10)),
        validator_balances=(max_deposit_amount, ) * 10,
    )

    default_block = BeaconBlock(**sample_beacon_block_params)
    empty_signature_block_root = default_block.block_without_signature_root

    proposal_signed_root = Proposal(
        state.slot,
        beacon_chain_shard_number,
        empty_signature_block_root,
    ).signed_root

    proposed_block = BeaconBlock(**sample_beacon_block_params).copy(
        signature=bls.sign(
            message_hash=proposal_signed_root,
            privkey=proposer_privkey,
            domain=SignatureDomain.DOMAIN_PROPOSAL,
        ), )

    if is_valid_signature:
        validate_proposer_signature(
            state,
            proposed_block,
            beacon_chain_shard_number,
            CommitteeConfig(config),
        )
    else:
        with pytest.raises(ValidationError):
            validate_proposer_signature(
                state,
                proposed_block,
                beacon_chain_shard_number,
                CommitteeConfig(config),
            )
def test_validate_proposer_signature(
        slots_per_epoch, shard_count, proposer_privkey, proposer_pubkey,
        is_valid_signature, sample_beacon_block_params,
        sample_beacon_state_params, target_committee_size, max_deposit_amount,
        config):

    state = BeaconState(**sample_beacon_state_params).copy(
        validator_registry=tuple(
            mock_validator(proposer_pubkey, config) for _ in range(10)),
        validator_balances=(max_deposit_amount, ) * 10,
    )

    block = BeaconBlock(**sample_beacon_block_params)
    header = block.header

    proposed_block = block.copy(signature=bls.sign(
        message_hash=header.signing_root,
        privkey=proposer_privkey,
        domain=get_domain(
            Fork(
                config.GENESIS_FORK_VERSION.to_bytes(4, 'little'),
                config.GENESIS_FORK_VERSION.to_bytes(4, 'little'),
                config.GENESIS_EPOCH,
            ),
            slot_to_epoch(state.slot, slots_per_epoch),
            SignatureDomain.DOMAIN_BEACON_BLOCK,
        ),
    ), )

    if is_valid_signature:
        validate_proposer_signature(
            state,
            proposed_block,
            CommitteeConfig(config),
        )
    else:
        with pytest.raises(ValidationError):
            validate_proposer_signature(
                state,
                proposed_block,
                CommitteeConfig(config),
            )
Esempio n. 23
0
def _mk_block(block_params, slot, parent, block_offset):
    block = BeaconBlock.create(**block_params).mset(
        "slot",
        slot,
        "parent_root",
        parent.message.hash_tree_root,
        # mix in something unique
        "state_root",
        block_offset.to_bytes(32, byteorder="big"),
    )
    return SignedBeaconBlock.create(message=block)
Esempio n. 24
0
def test_from_genesis(base_db, genesis_block, genesis_state, fixture_sm_class, config):
    klass = BeaconChain.configure(
        __name__="TestChain", sm_configuration=((0, fixture_sm_class),), chain_id=5566
    )

    assert type(genesis_block) == SerenityBeaconBlock
    block = BeaconBlock.convert_block(genesis_block)
    assert type(block) == BeaconBlock

    with pytest.raises(BlockClassError):
        klass.from_genesis(base_db, genesis_state, block, config)
Esempio n. 25
0
async def test_request_recent_beacon_blocks(monkeypatch):
    async with ConnectionPairFactory() as (alice, bob):

        # Mock up block database
        head_block = BeaconBlock(
            slot=0,
            parent_root=ZERO_HASH32,
            state_root=ZERO_HASH32,
            signature=EMPTY_SIGNATURE,
            body=BeaconBlockBody(),
        )
        blocks = [head_block.copy(slot=slot) for slot in range(5)]
        mock_root_to_block_db = {block.hash_tree_root: block for block in blocks}

        def get_block_by_hash_tree_root(root):
            validate_word(root)
            if root in mock_root_to_block_db:
                return mock_root_to_block_db[root]
            else:
                raise BlockNotFound

        monkeypatch.setattr(
            bob.chain, "get_block_by_hash_tree_root", get_block_by_hash_tree_root
        )

        requesting_block_roots = [
            blocks[0].hash_tree_root,
            b"\x12" * 32,  # Unknown block root
            blocks[1].hash_tree_root,
            b"\x23" * 32,  # Unknown block root
            blocks[3].hash_tree_root,
        ]
        requested_blocks = await alice.request_recent_beacon_blocks(
            peer_id=bob.peer_id, block_roots=requesting_block_roots
        )

        expected_blocks = [blocks[0], blocks[1], blocks[3]]
        assert len(requested_blocks) == len(expected_blocks)
        assert set(requested_blocks) == set(expected_blocks)
Esempio n. 26
0
def create_test_block(parent=None, **kwargs):
    defaults = {
        "slot": SERENITY_CONFIG.GENESIS_SLOT,
        "previous_block_root": ZERO_HASH32,
        "state_root": ZERO_HASH32,  # note: not the actual genesis state root
        "signature": EMPTY_SIGNATURE,
        "body": BeaconBlockBody.create_empty_body()
    }

    if parent is not None:
        kwargs["previous_block_root"] = parent.signing_root
        kwargs["slot"] = parent.slot + 1

    return BeaconBlock(**merge(defaults, kwargs))
Esempio n. 27
0
def _mk_minimum_viable_signed_beacon_blocks(slots, state_machine_provider,
                                            state, block, config):
    for slot in slots:
        future_state, _ = state_machine_provider(slot).apply_state_transition(
            state, future_slot=block.slot + 1)
        proposer_index = get_beacon_proposer_index(future_state, config)
        message = BeaconBlock.create(
            slot=slot,
            parent_root=block.message.hash_tree_root,
            proposer_index=proposer_index,
        )
        block = SignedBeaconBlock.create(message=message)
        state, block = state_machine_provider(slot).apply_state_transition(
            state, block)
        yield block
Esempio n. 28
0
def test_operation_fixture(config, test_case):
    config = config._replace(MAX_TRANSFERS=1, )
    post_state = test_case.pre
    block = BeaconBlock().copy(body=BeaconBlockBody(
        **{test_case.handler + 's': (
            test_case.operation, )}  # TODO: it looks awful
    ))
    _, operation_processing = handler_to_processing_call_map[test_case.handler]

    if test_case.is_valid:
        post_state = operation_processing(post_state, block, config)
        validate_state(test_case.post, post_state)
    else:
        with pytest.raises((ValidationError, IndexError, SignatureError)):
            operation_processing(post_state, block, config)
def test_validate_block_slot(
    sample_beacon_state_params,
    sample_beacon_block_params,
    state_slot,
    block_slot,
    expected,
):
    state = BeaconState.create(**sample_beacon_state_params).set(
        "slot", state_slot)
    block = BeaconBlock.create(**sample_beacon_block_params).set(
        "slot", block_slot)
    if isinstance(expected, Exception):
        with pytest.raises(ValidationError):
            validate_block_slot(state, block)
    else:
        validate_block_slot(state, block)
Esempio n. 30
0
def create_test_block(parent=None, **kwargs):
    defaults = {
        "slot": 0,
        "parent_root": ZERO_HASH32,
        "state_root": ZERO_HASH32,  # note: not the actual genesis state root
        "randao_reveal": ZERO_HASH32,
        "candidate_pow_receipt_root": ZERO_HASH32,
        "signature": (0, 0),
        "body": empty_body()
    }

    if parent is not None:
        kwargs["parent_root"] = parent.root
        kwargs["slot"] = parent.slot + 1

    return BeaconBlock(**merge(defaults, kwargs))