Exemplo n.º 1
0
def create_block_on_state(
        *,
        state: BeaconState,
        config: BeaconConfig,
        state_machine: BaseBeaconStateMachine,
        block_class: BaseBeaconBlock,
        parent_block: BaseBeaconBlock,
        slot: SlotNumber,
        validator_index: ValidatorIndex,
        privkey: int,
        attestations: Sequence[Attestation],
        check_proposer_index: bool = True) -> BaseBeaconBlock:
    """
    Create a beacon block with the given parameters.
    """
    # Check proposer
    if check_proposer_index:
        validate_proposer_index(state, config, slot, validator_index)

    # Prepare block: slot and parent_root
    block = block_class.from_parent(
        parent_block=parent_block,
        block_params=FromBlockParams(slot=slot),
    )

    # TODO: Add more operations
    randao_reveal = ZERO_HASH32
    eth1_data = Eth1Data.create_empty_data()
    body = BeaconBlockBody.create_empty_body().copy(
        attestations=attestations, )

    block = block.copy(
        randao_reveal=randao_reveal,
        eth1_data=eth1_data,
        body=body,
    )

    # Apply state transition to get state root
    state, block = state_machine.import_block(block,
                                              check_proposer_signature=True)

    # Sign
    empty_signature_block_root = block.block_without_signature_root
    proposal_root = ProposalSignedData(
        slot,
        config.BEACON_CHAIN_SHARD_NUMBER,
        empty_signature_block_root,
    ).root
    domain = get_domain(
        state.fork,
        slot_to_epoch(slot, config.EPOCH_LENGTH),
        SignatureDomain.DOMAIN_PROPOSAL,
    )
    block = block.copy(signature=bls.sign(
        message=proposal_root,
        privkey=privkey,
        domain=domain,
    ), )

    return block
Exemplo n.º 2
0
def test_canonical_chain(valid_chain, genesis_slot, fork_choice_scoring):
    genesis_block = valid_chain.get_canonical_block_by_slot(genesis_slot)

    # Our chain fixture is created with only the genesis header, so initially that's the head of
    # the canonical chain.
    assert valid_chain.get_canonical_head() == genesis_block
    # verify a special case (score(genesis) == 0)
    assert valid_chain.get_score(
        genesis_block.message.hash_tree_root) == fork_choice_scoring.score(
            genesis_block.message)

    block = SerenitySignedBeaconBlock.from_parent(genesis_block,
                                                  FromBlockParams(slot=1))
    valid_chain.chaindb.persist_block(block, block.__class__,
                                      fork_choice_scoring)

    assert valid_chain.get_canonical_head() == block
    state_machine = valid_chain.get_state_machine(block.slot)
    scoring = state_machine.get_fork_choice_scoring()

    assert valid_chain.get_score(
        block.message.hash_tree_root) == scoring.score(block.message)
    assert scoring.score(block.message) != 0

    canonical_block_1 = valid_chain.get_canonical_block_by_slot(
        genesis_block.slot + 1)
    assert canonical_block_1 == block

    result_block = valid_chain.get_block_by_root(block.message.hash_tree_root)
    assert result_block == block
Exemplo n.º 3
0
def test_chaindb_get_score(chaindb, fixture_sm_class, genesis_block,
                           fork_choice_scoring):
    chaindb.persist_block(genesis_block, genesis_block.__class__,
                          fork_choice_scoring)

    genesis_score_key = SchemaV1.make_block_root_to_score_lookup_key(
        genesis_block.message.hash_tree_root)
    genesis_score_data = chaindb.db.get(genesis_score_key)
    genesis_score_class = fork_choice_scoring.get_score_class()
    genesis_score = genesis_score_class.deserialize(genesis_score_data)

    expected_genesis_score = fork_choice_scoring.score(genesis_block.message)

    assert genesis_score == expected_genesis_score
    assert (chaindb.get_score(genesis_block.message.hash_tree_root,
                              genesis_score_class) == expected_genesis_score)

    block1 = SignedBeaconBlock.from_parent(genesis_block,
                                           FromBlockParams(slot=1))

    chaindb.persist_block(block1, block1.__class__, fork_choice_scoring)

    block1_score_key = SchemaV1.make_block_root_to_score_lookup_key(
        block1.message.hash_tree_root)
    block1_score_data = chaindb.db.get(block1_score_key)
    block1_score = genesis_score_class.deserialize(block1_score_data)
    expected_block1_score = fork_choice_scoring.score(block1.message)
    assert block1_score == expected_block1_score
    assert (chaindb.get_score(block1.message.hash_tree_root,
                              genesis_score_class) == expected_block1_score)
Exemplo n.º 4
0
def create_unsigned_block_on_state(
    *,
    state: BeaconState,
    config: Eth2Config,
    block_class: Type[BaseBeaconBlock],
    parent_block: BaseBeaconBlock,
    slot: Slot,
    attestations: Sequence[Attestation],
    eth1_data: Eth1Data = None,
    deposits: Sequence[Deposit] = None,
    check_proposer_index: bool = True,
) -> BeaconBlock:
    """
    Create a beacon block with the given parameters.
    """
    block = block_class.from_parent(parent_block=parent_block,
                                    block_params=FromBlockParams(slot=slot))

    # MAX_ATTESTATIONS
    attestations = attestations[:config.MAX_ATTESTATIONS]

    # TODO: Add more operations
    if eth1_data is None:
        eth1_data = state.eth1_data
    body = BeaconBlockBody.create(eth1_data=eth1_data,
                                  attestations=attestations)
    if deposits is not None and len(deposits) > 0:
        body = body.set("deposits", deposits)

    block = block.set("body", body)

    return block
Exemplo n.º 5
0
def test_block_is_not_genesis():
    genesis_block = SignedBeaconBlock.create().transform(
        ("message", "parent_root"), GENESIS_PARENT_ROOT)
    another_block = SignedBeaconBlock.from_parent(genesis_block,
                                                  FromBlockParams())
    assert genesis_block.is_genesis
    assert not another_block.is_genesis
Exemplo n.º 6
0
def create_block_on_state(state: BeaconState, config: BeaconConfig,
                          block_class: BaseBeaconBlock,
                          parent_block: BaseBeaconBlock, slot: SlotNumber,
                          validator_index: int, privkey: int,
                          attestations: Sequence[Attestation]):
    """
    Create a beacon block with the given parameters.
    """
    # Check proposer
    beacon_proposer_index = get_beacon_proposer_index(
        state.copy(slot=slot, ),
        slot,
        config.EPOCH_LENGTH,
        config.TARGET_COMMITTEE_SIZE,
        config.SHARD_COUNT,
    )

    if validator_index != beacon_proposer_index:
        raise ProposerIndexError

    # Prepare block: slot and parent_root
    block = block_class.from_parent(
        parent_block=parent_block,
        block_params=FromBlockParams(slot=slot),
    )

    # TODO: Add more operations
    randao_reveal = ZERO_HASH32
    eth1_data = Eth1Data.create_empty_data()
    body = BeaconBlockBody.create_empty_body().copy(
        attestations=attestations, )

    block = block.copy(
        randao_reveal=randao_reveal,
        eth1_data=eth1_data,
        body=body,
    )

    # Sign
    empty_signature_block_root = block.block_without_signature_root
    proposal_root = ProposalSignedData(
        slot,
        config.BEACON_CHAIN_SHARD_NUMBER,
        empty_signature_block_root,
    ).root
    domain = get_domain(
        state.fork,
        slot,
        SignatureDomain.DOMAIN_PROPOSAL,
    )
    block = block.copy(signature=bls.sign(
        message=proposal_root,
        privkey=privkey,
        domain=domain,
    ), )

    return block
Exemplo n.º 7
0
def get_pseudo_chain(length, genesis_block):
    """
    Get a pseudo chain, only slot and parent_root are valid.
    """
    block = genesis_block
    yield genesis_block
    for slot in range(1, length * 3):
        block = SignedBeaconBlock.from_parent(block, FromBlockParams(slot=slot))
        yield block
Exemplo n.º 8
0
 def __init__(self,
              chaindb: BaseBeaconChainDB,
              block: BaseBeaconBlock,
              parent_block_class: Type[BaseBeaconBlock]) -> None:
     self.chaindb = chaindb
     self.block = self.get_block_class().from_parent(
         parent_block=self.chaindb.get_block_by_root(block.parent_root, parent_block_class),
         block_params=FromBlockParams(slot=block.slot),
     )
Exemplo n.º 9
0
 def ensure_block(self, block: BaseBeaconBlock=None) -> BaseBeaconBlock:
     """
     Return ``block`` if it is not ``None``, otherwise return the block
     of the canonical head.
     """
     if block is None:
         head = self.get_canonical_head()
         return self.create_block_from_parent(head, FromBlockParams())
     else:
         return block
Exemplo n.º 10
0
def block_with_attestation(chaindb, genesis_block, sample_attestation_params,
                           fork_choice_scoring):
    sample_attestation = Attestation.create(**sample_attestation_params)

    chaindb.persist_block(genesis_block, genesis_block.__class__,
                          fork_choice_scoring)
    block1 = SignedBeaconBlock.from_parent(
        genesis_block, FromBlockParams(slot=1)).transform(
            ("message", "body", "attestations"), (sample_attestation, ))
    return block1, sample_attestation
Exemplo n.º 11
0
def create_block_on_state(
        *,
        state: BeaconState,
        config: Eth2Config,
        state_machine: BaseBeaconStateMachine,
        block_class: Type[BaseBeaconBlock],
        parent_block: BaseBeaconBlock,
        slot: Slot,
        validator_index: ValidatorIndex,
        privkey: int,
        attestations: Sequence[Attestation],
        check_proposer_index: bool = True) -> BaseBeaconBlock:
    """
    Create a beacon block with the given parameters.
    """
    # Check proposer
    if check_proposer_index:
        validate_proposer_index(state, config, slot, validator_index)

    # Prepare block: slot and previous_block_root
    block = block_class.from_parent(
        parent_block=parent_block,
        block_params=FromBlockParams(slot=slot),
    )

    # TODO: Add more operations
    randao_reveal = _generate_randao_reveal(privkey, slot, state.fork, config)
    eth1_data = Eth1Data.create_empty_data()
    body = BeaconBlockBody.create_empty_body().copy(
        randao_reveal=randao_reveal,
        eth1_data=eth1_data,
        attestations=attestations,
    )

    block = block.copy(body=body, )

    # Apply state transition to get state root
    state, block = state_machine.import_block(block,
                                              check_proposer_signature=False)

    # Sign
    # TODO make sure we use the correct signed_root
    signature = sign_transaction(
        message_hash=block.signed_root,
        privkey=privkey,
        fork=state.fork,
        slot=slot,
        signature_domain=SignatureDomain.DOMAIN_BEACON_BLOCK,
        slots_per_epoch=config.SLOTS_PER_EPOCH,
    )

    block = block.copy(signature=signature, )

    return block
Exemplo n.º 12
0
def test_chaindb_get_canonical_head(chaindb, block, fork_choice_scoring):
    chaindb.persist_block(block, block.__class__, fork_choice_scoring)

    canonical_head_root = chaindb.get_canonical_head_root()
    assert canonical_head_root == block.message.hash_tree_root

    result_block = chaindb.get_canonical_head(block.__class__)
    assert result_block == block

    block_2 = SignedBeaconBlock.from_parent(
        block, FromBlockParams(slot=block.message.slot + 1))
    chaindb.persist_block(block_2, block_2.__class__, fork_choice_scoring)
    result_block = chaindb.get_canonical_head(block.__class__)
    assert result_block == block_2

    block_3 = SignedBeaconBlock.from_parent(
        block_2, FromBlockParams(slot=block_2.message.slot + 1))
    chaindb.persist_block(block_3, block_3.__class__, fork_choice_scoring)
    result_block = chaindb.get_canonical_head(block.__class__)
    assert result_block == block_3
Exemplo n.º 13
0
    def import_block(
            self,
            block: BaseBeaconBlock,
            perform_validation: bool=True
    ) -> Tuple[BaseBeaconBlock, Tuple[BaseBeaconBlock, ...], Tuple[BaseBeaconBlock, ...]]:
        """
        Import a complete block and returns a 3-tuple

        - the imported block
        - a tuple of blocks which are now part of the canonical chain.
        - a tuple of blocks which are were canonical and now are no longer canonical.
        """

        try:
            parent_block = self.get_block_by_root(block.parent_root)
        except BlockNotFound:
            raise ValidationError(
                "Attempt to import block #{}.  Cannot import block {} before importing "
                "its parent block at {}".format(
                    block.slot,
                    block.hash,
                    block.parent_root,
                )
            )
        base_block_for_import = self.create_block_from_parent(
            parent_block,
            FromBlockParams(),
        )
        state, imported_block = self.get_state_machine(
            base_block_for_import,
        ).import_block(block)

        # TODO: Now it just persit all state. Should design how to clean up the old state.
        self.chaindb.persist_state(state)

        # Validate the imported block.
        if perform_validation:
            validate_imported_block_unchanged(imported_block, block)

        (
            new_canonical_blocks,
            old_canonical_blocks,
        ) = self.chaindb.persist_block(imported_block, imported_block.__class__)

        self.logger.debug(
            'IMPORTED_BLOCK: slot %s | hash %s',
            imported_block.slot,
            encode_hex(imported_block.hash),
        )

        return imported_block, new_canonical_blocks, old_canonical_blocks
Exemplo n.º 14
0
def create_block_on_state(
        *,
        state: BeaconState,
        config: Eth2Config,
        state_machine: BaseBeaconStateMachine,
        block_class: Type[BaseBeaconBlock],
        parent_block: BaseBeaconBlock,
        slot: Slot,
        validator_index: ValidatorIndex,
        privkey: int,
        attestations: Sequence[Attestation],
        check_proposer_index: bool = True) -> BaseBeaconBlock:
    """
    Create a beacon block with the given parameters.
    """
    if check_proposer_index:
        validate_proposer_index(state, config, slot, validator_index)

    block = block_class.from_parent(parent_block=parent_block,
                                    block_params=FromBlockParams(slot=slot))

    # MAX_ATTESTATIONS
    attestations = attestations[:config.MAX_ATTESTATIONS]

    # TODO: Add more operations
    randao_reveal = _generate_randao_reveal(privkey, slot, state, config)
    eth1_data = state.eth1_data
    body = BeaconBlockBody.create(randao_reveal=randao_reveal,
                                  eth1_data=eth1_data,
                                  attestations=attestations)

    block = block.set("body", body)

    # Apply state transition to get state root
    state, block = state_machine.import_block(block,
                                              state,
                                              check_proposer_signature=False)

    # Sign
    signature = sign_transaction(
        message_hash=block.signing_root,
        privkey=privkey,
        state=state,
        slot=slot,
        signature_domain=SignatureDomain.DOMAIN_BEACON_PROPOSER,
        slots_per_epoch=config.SLOTS_PER_EPOCH,
    )

    block = block.set("signature", signature)

    return block
Exemplo n.º 15
0
def get_blocks(
    chain: BaseBeaconChain,
    parent_block: SerenityBeaconBlock = None,
    num_blocks: int = 3,
) -> Tuple[SerenityBeaconBlock, ...]:
    if parent_block is None:
        parent_block = chain.get_canonical_head()
    blocks = []
    for _ in range(num_blocks):
        block = chain.create_block_from_parent(parent_block=parent_block,
                                               block_params=FromBlockParams())
        blocks.append(block)
        parent_block = block
    return tuple(blocks)
Exemplo n.º 16
0
def get_blocks(receive_server: BCCReceiveServer,
               parent_block: SerenityBeaconBlock = None,
               num_blocks: int = 3) -> Tuple[SerenityBeaconBlock, ...]:
    chain = receive_server.chain
    if parent_block is None:
        parent_block = chain.get_canonical_head()
    blocks = []
    for _ in range(num_blocks):
        block = chain.create_block_from_parent(
            parent_block=parent_block,
            block_params=FromBlockParams(),
        )
        blocks.append(block)
        parent_block = block
    return tuple(blocks)
Exemplo n.º 17
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.signing_root))
    chaindb.persist_state(state_with_finalized_block)
    chaindb.persist_block(block, SignedBeaconBlock, fork_choice_scoring)

    assert (chaindb.get_finalized_head(SignedBeaconBlock).signing_root ==
            block.signing_root)
    assert chaindb.get_justified_head(genesis_block.__class__) == genesis_block
Exemplo n.º 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)
Exemplo n.º 19
0
def create_block_on_state(
        *,
        state: BeaconState,
        config: BeaconConfig,
        state_machine: BaseBeaconStateMachine,
        block_class: Type[BaseBeaconBlock],
        parent_block: BaseBeaconBlock,
        slot: Slot,
        validator_index: ValidatorIndex,
        privkey: int,
        attestations: Sequence[Attestation],
        check_proposer_index: bool = True) -> BaseBeaconBlock:
    """
    Create a beacon block with the given parameters.
    """
    # Check proposer
    if check_proposer_index:
        validate_proposer_index(state, config, slot, validator_index)

    # Prepare block: slot and parent_root
    block = block_class.from_parent(
        parent_block=parent_block,
        block_params=FromBlockParams(slot=slot),
    )

    # TODO: Add more operations
    randao_reveal = EMPTY_SIGNATURE
    eth1_data = Eth1Data.create_empty_data()
    body = BeaconBlockBody.create_empty_body().copy(
        attestations=attestations, )

    block = block.copy(
        randao_reveal=randao_reveal,
        eth1_data=eth1_data,
        body=body,
    )

    # Apply state transition to get state root
    state, block = state_machine.import_block(block,
                                              check_proposer_signature=False)

    # Sign
    empty_signature_block_root = block.block_without_signature_root
    proposal_root = Proposal(
        slot,
        config.BEACON_CHAIN_SHARD_NUMBER,
        empty_signature_block_root,
    ).root

    signature = sign_transaction(
        message_hash=proposal_root,
        privkey=privkey,
        fork=state.fork,
        slot=slot,
        signature_domain=SignatureDomain.DOMAIN_PROPOSAL,
        slots_per_epoch=config.SLOTS_PER_EPOCH,
    )

    block = block.copy(signature=signature, )

    return block
Exemplo n.º 20
0
def test_block_is_not_genesis(sample_beacon_block_params):
    genesis_block = BeaconBlock(**sample_beacon_block_params)
    another_block = BeaconBlock.from_parent(genesis_block, FromBlockParams())
    assert genesis_block.is_genesis
    assert not another_block.is_genesis