async def validate_unfinished_block(
        self,
        block: UnfinishedBlock,
        skip_overflow_ss_validation=True
    ) -> Tuple[Optional[uint64], Optional[Err]]:
        if (block.prev_header_hash not in self.sub_blocks
                and not block.prev_header_hash
                == self.constants.GENESIS_PREV_HASH):
            return None, Err.INVALID_PREV_BLOCK_HASH

        unfinished_header_block = UnfinishedHeaderBlock(
            block.finished_sub_slots,
            block.reward_chain_sub_block,
            block.challenge_chain_sp_proof,
            block.reward_chain_sp_proof,
            block.foliage_sub_block,
            block.foliage_block,
            b"",
        )
        prev_sb = self.sub_blocks.get(unfinished_header_block.prev_header_hash,
                                      None)
        sub_slot_iters, difficulty = get_sub_slot_iters_and_difficulty(
            self.constants, unfinished_header_block, self.sub_height_to_hash,
            prev_sb, self.sub_blocks)
        required_iters, error = validate_unfinished_header_block(
            self.constants,
            self.sub_blocks,
            unfinished_header_block,
            False,
            difficulty,
            sub_slot_iters,
            skip_overflow_ss_validation,
        )

        if error is not None:
            return None, error.code

        prev_sub_height = (
            -1 if block.prev_header_hash == self.constants.GENESIS_PREV_HASH
            else self.sub_blocks[block.prev_header_hash].sub_block_height)

        if block.is_block():
            assert block.foliage_block is not None
            height: Optional[uint32] = block.foliage_block.height
        else:
            height = None
        error_code = await validate_block_body(
            self.constants,
            self.sub_blocks,
            self.sub_height_to_hash,
            self.block_store,
            self.coin_store,
            self.get_peak(),
            block,
            uint32(prev_sub_height + 1),
            height,
        )

        if error_code is not None:
            return None, error_code

        return required_iters, None
Esempio n. 2
0
def create_unfinished_block(
    constants: ConsensusConstants,
    sub_slot_start_total_iters: uint128,
    sub_slot_iters: uint64,
    signage_point_index: uint8,
    sp_iters: uint64,
    ip_iters: uint64,
    proof_of_space: ProofOfSpace,
    slot_cc_challenge: bytes32,
    farmer_reward_puzzle_hash: bytes32,
    pool_target: PoolTarget,
    get_plot_signature: Callable[[bytes32, G1Element], G2Element],
    get_pool_signature: Callable[[PoolTarget, Optional[G1Element]],
                                 Optional[G2Element]],
    signage_point: SignagePoint,
    timestamp: uint64,
    blocks: BlockchainInterface,
    seed: bytes32 = b"",
    spend_bundle: Optional[SpendBundle] = None,
    additions: Optional[List[Coin]] = None,
    removals: Optional[List[Coin]] = None,
    prev_block: Optional[BlockRecord] = None,
    finished_sub_slots_input: List[EndOfSubSlotBundle] = None,
) -> UnfinishedBlock:
    """
    Creates a new unfinished block using all the information available at the signage point. This will have to be
    modified using information from the infusion point.

    Args:
        constants: consensus constants being used for this chain
        sub_slot_start_total_iters: the starting sub-slot iters at the signage point sub-slot
        sub_slot_iters: sub-slot-iters at the infusion point epoch
        signage_point_index: signage point index of the block to create
        sp_iters: sp_iters of the block to create
        ip_iters: ip_iters of the block to create
        proof_of_space: proof of space of the block to create
        slot_cc_challenge: challenge hash at the sp sub-slot
        farmer_reward_puzzle_hash: where to pay out farmer rewards
        pool_target: where to pay out pool rewards
        get_plot_signature: function that returns signature corresponding to plot public key
        get_pool_signature: function that returns signature corresponding to pool public key
        signage_point: signage point information (VDFs)
        timestamp: timestamp to add to the foliage block, if created
        seed: seed to randomize chain
        spend_bundle: transactions to add to the foliage block, if created
        additions: Coins added in spend_bundle
        removals: Coins removed in spend_bundle
        prev_block: previous block (already in chain) from the signage point
        blocks: dictionary from header hash to SBR of all included SBR
        finished_sub_slots_input: finished_sub_slots at the signage point

    Returns:

    """
    if finished_sub_slots_input is None:
        finished_sub_slots: List[EndOfSubSlotBundle] = []
    else:
        finished_sub_slots = finished_sub_slots_input.copy()
    overflow: bool = sp_iters > ip_iters
    total_iters_sp: uint128 = uint128(sub_slot_start_total_iters + sp_iters)
    is_genesis: bool = prev_block is None

    new_sub_slot: bool = len(finished_sub_slots) > 0

    cc_sp_hash: Optional[bytes32] = slot_cc_challenge

    # Only enters this if statement if we are in testing mode (making VDF proofs here)
    if signage_point.cc_vdf is not None:
        assert signage_point.rc_vdf is not None
        cc_sp_hash = signage_point.cc_vdf.output.get_hash()
        rc_sp_hash = signage_point.rc_vdf.output.get_hash()
    else:
        if new_sub_slot:
            rc_sp_hash = finished_sub_slots[-1].reward_chain.get_hash()
        else:
            if is_genesis:
                rc_sp_hash = constants.GENESIS_CHALLENGE
            else:
                assert prev_block is not None
                assert blocks is not None
                curr = prev_block
                while not curr.first_in_sub_slot:
                    curr = blocks.block_record(curr.prev_hash)
                assert curr.finished_reward_slot_hashes is not None
                rc_sp_hash = curr.finished_reward_slot_hashes[-1]
        signage_point = SignagePoint(None, None, None, None)

    cc_sp_signature: Optional[G2Element] = get_plot_signature(
        cc_sp_hash, proof_of_space.plot_public_key)
    rc_sp_signature: Optional[G2Element] = get_plot_signature(
        rc_sp_hash, proof_of_space.plot_public_key)
    assert cc_sp_signature is not None
    assert rc_sp_signature is not None
    assert blspy.AugSchemeMPL.verify(proof_of_space.plot_public_key,
                                     cc_sp_hash, cc_sp_signature)

    total_iters = uint128(sub_slot_start_total_iters + ip_iters +
                          (sub_slot_iters if overflow else 0))

    rc_block = RewardChainBlockUnfinished(
        total_iters,
        signage_point_index,
        slot_cc_challenge,
        proof_of_space,
        signage_point.cc_vdf,
        cc_sp_signature,
        signage_point.rc_vdf,
        rc_sp_signature,
    )
    if additions is None:
        additions = []
    if removals is None:
        removals = []
    (
        foliage,
        foliage_transaction_block,
        transactions_info,
        solution_program,
    ) = create_foliage(
        constants,
        rc_block,
        spend_bundle,
        additions,
        removals,
        prev_block,
        blocks,
        total_iters_sp,
        timestamp,
        farmer_reward_puzzle_hash,
        pool_target,
        get_plot_signature,
        get_pool_signature,
        seed,
    )

    return UnfinishedBlock(
        finished_sub_slots,
        rc_block,
        signage_point.cc_proof,
        signage_point.rc_proof,
        foliage,
        foliage_transaction_block,
        transactions_info,
        solution_program,
    )
    async def test1(self, two_nodes):
        num_blocks = 5
        test_rpc_port = uint16(21522)
        full_node_api_1, full_node_api_2, server_1, server_2 = two_nodes

        def stop_node_cb():
            full_node_api_1._close()
            server_1.close_all()

        full_node_rpc_api = FullNodeRpcApi(full_node_api_1.full_node)

        config = bt.config
        hostname = config["self_hostname"]
        daemon_port = config["daemon_port"]

        rpc_cleanup = await start_rpc_server(
            full_node_rpc_api,
            hostname,
            daemon_port,
            test_rpc_port,
            stop_node_cb,
            bt.root_path,
            config,
            connect_to_daemon=False,
        )

        try:
            client = await FullNodeRpcClient.create(self_hostname,
                                                    test_rpc_port,
                                                    bt.root_path, config)
            state = await client.get_blockchain_state()
            assert state["peak"] is None
            assert not state["sync"]["sync_mode"]
            assert state["difficulty"] > 0
            assert state["sub_slot_iters"] > 0

            blocks = bt.get_consecutive_blocks(num_blocks)
            blocks = bt.get_consecutive_blocks(1,
                                               block_list_input=blocks,
                                               guarantee_block=True)

            assert len(await client.get_unfinished_sub_block_headers()) == 0
            assert len((await client.get_sub_block_records(0, 100))) == 0
            for block in blocks:
                if is_overflow_sub_block(
                        test_constants,
                        block.reward_chain_sub_block.signage_point_index):
                    finished_ss = block.finished_sub_slots[:-1]
                else:
                    finished_ss = block.finished_sub_slots

                unf = UnfinishedBlock(
                    finished_ss,
                    block.reward_chain_sub_block.get_unfinished(),
                    block.challenge_chain_sp_proof,
                    block.reward_chain_sp_proof,
                    block.foliage_sub_block,
                    block.foliage_block,
                    block.transactions_info,
                    block.transactions_generator,
                )
                await full_node_api_1.full_node.respond_unfinished_sub_block(
                    full_node_protocol.RespondUnfinishedSubBlock(unf), None)
                await full_node_api_1.full_node.respond_sub_block(
                    full_node_protocol.RespondSubBlock(block), None)

            assert len(await client.get_unfinished_sub_block_headers()) > 0
            assert len(await client.get_all_block(0, 2)) == 2
            state = await client.get_blockchain_state()

            block = await client.get_sub_block(state["peak"].header_hash)
            assert block == blocks[-1]
            assert (await client.get_sub_block(bytes([1] * 32))) is None

            assert (await client.get_sub_block_record_by_sub_height(2)
                    ).header_hash == blocks[2].header_hash

            assert len(
                (await client.get_sub_block_records(0, 100))) == num_blocks + 1

            assert (await
                    client.get_sub_block_record_by_sub_height(100)) is None

            ph = list(blocks[-1].get_included_reward_coins())[0].puzzle_hash
            coins = await client.get_unspent_coins(ph)
            assert len(coins) >= 1

            additions, removals = await client.get_additions_and_removals(
                blocks[-1].header_hash)
            assert len(additions) >= 2 and len(removals) == 0

            assert len(await client.get_connections()) == 0

            await client.open_connection(self_hostname, server_2._port)

            async def num_connections():
                return len(await client.get_connections())

            await time_out_assert(10, num_connections, 1)
            connections = await client.get_connections()

            await client.close_connection(connections[0]["node_id"])
            await time_out_assert(10, num_connections, 0)
        finally:
            # Checks that the RPC manages to stop the node
            client.close()
            await client.await_closed()
            await rpc_cleanup()
Esempio n. 4
0
    async def test_basic_store(self, empty_blockchain):
        blockchain = empty_blockchain
        blocks = bt.get_consecutive_blocks(10, seed=b"1234")

        store = await FullNodeStore.create(test_constants)

        unfinished_blocks = []
        for block in blocks:
            unfinished_blocks.append(
                UnfinishedBlock(
                    block.finished_sub_slots,
                    block.reward_chain_sub_block.get_unfinished(),
                    block.challenge_chain_sp_proof,
                    block.reward_chain_sp_proof,
                    block.foliage_sub_block,
                    block.foliage_block,
                    block.transactions_info,
                    block.transactions_generator,
                ))

        # Add/get candidate block
        assert store.get_candidate_block(
            unfinished_blocks[0].get_hash()) is None
        for height, unf_block in enumerate(unfinished_blocks):
            store.add_candidate_block(unf_block.get_hash(), height, unf_block)

        assert store.get_candidate_block(
            unfinished_blocks[4].get_hash()) == unfinished_blocks[4]
        store.clear_candidate_blocks_below(uint32(8))
        assert store.get_candidate_block(
            unfinished_blocks[5].get_hash()) is None
        assert store.get_candidate_block(
            unfinished_blocks[8].get_hash()) is not None

        # Test seen unfinished blocks
        h_hash_1 = bytes32(token_bytes(32))
        assert not store.seen_unfinished_block(h_hash_1)
        assert store.seen_unfinished_block(h_hash_1)
        store.clear_seen_unfinished_blocks()
        assert not store.seen_unfinished_block(h_hash_1)

        # Disconnected blocks
        assert store.get_disconnected_block(blocks[0].prev_header_hash) is None
        for block in blocks:
            store.add_disconnected_block(block)
            assert store.get_disconnected_block_by_prev(
                block.prev_header_hash) == block
            assert store.get_disconnected_block(block.header_hash) == block

        # Add/get unfinished block
        for height, unf_block in enumerate(unfinished_blocks):
            assert store.get_unfinished_block(unf_block.partial_hash) is None
            store.add_unfinished_block(height, unf_block)
            assert store.get_unfinished_block(
                unf_block.partial_hash) == unf_block
            store.remove_unfinished_block(unf_block.partial_hash)
            assert store.get_unfinished_block(unf_block.partial_hash) is None

        blocks = bt.get_consecutive_blocks(1, skip_slots=5)
        sub_slots = blocks[0].finished_sub_slots
        assert len(sub_slots) == 5

        assert (store.get_finished_sub_slots(
            None,
            {},
            sub_slots[0].challenge_chain.challenge_chain_end_of_slot_vdf.
            challenge,
            False,
        ) == [])
        # Test adding non-connecting sub-slots genesis
        assert store.get_sub_slot(test_constants.FIRST_CC_CHALLENGE) is None
        assert store.get_sub_slot(
            sub_slots[0].challenge_chain.get_hash()) is None
        assert store.get_sub_slot(
            sub_slots[1].challenge_chain.get_hash()) is None
        assert store.new_finished_sub_slot(sub_slots[1], {}, None) is None
        assert store.new_finished_sub_slot(sub_slots[2], {}, None) is None

        # Test adding sub-slots after genesis
        assert store.new_finished_sub_slot(sub_slots[0], {}, None) is not None
        assert store.get_sub_slot(
            sub_slots[0].challenge_chain.get_hash())[0] == sub_slots[0]
        assert store.get_sub_slot(
            sub_slots[1].challenge_chain.get_hash()) is None
        assert store.new_finished_sub_slot(sub_slots[1], {}, None) is not None
        for i in range(len(sub_slots)):
            assert store.new_finished_sub_slot(sub_slots[i], {},
                                               None) is not None
            assert store.get_sub_slot(
                sub_slots[i].challenge_chain.get_hash())[0] == sub_slots[i]

        assert store.get_finished_sub_slots(
            None, {}, sub_slots[-1].challenge_chain.get_hash(),
            False) == sub_slots
        with raises(ValueError):
            store.get_finished_sub_slots(
                None, {}, sub_slots[-1].challenge_chain.get_hash(), True)

        assert store.get_finished_sub_slots(
            None, {}, sub_slots[-2].challenge_chain.get_hash(),
            False) == sub_slots[:-1]

        # Test adding genesis peak
        await blockchain.receive_block(blocks[0])
        peak = blockchain.get_peak()
        if peak.overflow:
            store.new_peak(peak, sub_slots[-2], sub_slots[-1], False, {})
        else:
            store.new_peak(peak, None, sub_slots[-1], False, {})

        assert store.get_sub_slot(
            sub_slots[0].challenge_chain.get_hash()) is None
        assert store.get_sub_slot(
            sub_slots[1].challenge_chain.get_hash()) is None
        assert store.get_sub_slot(
            sub_slots[2].challenge_chain.get_hash()) is None
        assert store.get_sub_slot(
            sub_slots[3].challenge_chain.get_hash())[0] == sub_slots[3]
        assert store.get_sub_slot(
            sub_slots[4].challenge_chain.get_hash())[0] == sub_slots[4]

        assert (store.get_finished_sub_slots(
            peak,
            blockchain.sub_blocks,
            sub_slots[-1].challenge_chain.get_hash(),
            False,
        ) == [])

        # Test adding non genesis peak directly
        blocks = bt.get_consecutive_blocks(2, skip_slots=2)
        blocks = bt.get_consecutive_blocks(3, block_list_input=blocks)
        for block in blocks:
            await blockchain.receive_block(block)
            sb = blockchain.sub_blocks[block.header_hash]
            sp_sub_slot, ip_sub_slot = await blockchain.get_sp_and_ip_sub_slots(
                block.header_hash)
            res = store.new_peak(sb, sp_sub_slot, ip_sub_slot, False,
                                 blockchain.sub_blocks)
            assert res[0] is None

        # Add reorg blocks
        blocks_reorg = bt.get_consecutive_blocks(20)
        for block in blocks_reorg:
            res, _, _ = await blockchain.receive_block(block)
            if res == ReceiveBlockResult.NEW_PEAK:
                sb = blockchain.sub_blocks[block.header_hash]
                sp_sub_slot, ip_sub_slot = await blockchain.get_sp_and_ip_sub_slots(
                    block.header_hash)
                res = store.new_peak(sb, sp_sub_slot, ip_sub_slot, True,
                                     blockchain.sub_blocks)
                assert res[0] is None

        # Add slots to the end
        blocks_2 = bt.get_consecutive_blocks(1,
                                             block_list_input=blocks_reorg,
                                             skip_slots=2)
        for slot in blocks_2[-1].finished_sub_slots:
            store.new_finished_sub_slot(slot, blockchain.sub_blocks,
                                        blockchain.get_peak())

        assert store.get_sub_slot(
            sub_slots[3].challenge_chain.get_hash()) is None
        assert store.get_sub_slot(
            sub_slots[4].challenge_chain.get_hash()) is None

        # Test adding signage point
        peak = blockchain.get_peak()
        ss_start_iters = peak.sp_sub_slot_total_iters(test_constants)
        for i in range(
                1, test_constants.NUM_SPS_SUB_SLOT -
                test_constants.NUM_SP_INTERVALS_EXTRA):
            sp = get_signage_point(
                test_constants,
                blockchain.sub_blocks,
                peak,
                ss_start_iters,
                uint8(i),
                [],
                peak.sub_slot_iters,
            )
            assert store.new_signage_point(i, blockchain.sub_blocks, peak,
                                           peak.sub_slot_iters, sp)

        blocks = blocks_reorg
        while True:
            blocks = bt.get_consecutive_blocks(1, block_list_input=blocks)
            res, _, _ = await blockchain.receive_block(blocks[-1])
            if res == ReceiveBlockResult.NEW_PEAK:
                sb = blockchain.sub_blocks[blocks[-1].header_hash]
                sp_sub_slot, ip_sub_slot = await blockchain.get_sp_and_ip_sub_slots(
                    blocks[-1].header_hash)

                res = store.new_peak(sb, sp_sub_slot, ip_sub_slot, True,
                                     blockchain.sub_blocks)
                assert res[0] is None
                if sb.overflow and sp_sub_slot is not None:
                    assert sp_sub_slot != ip_sub_slot
                    break

        peak = blockchain.get_peak()
        assert peak.overflow
        # Overflow peak should result in 2 finished sub slots
        assert len(store.finished_sub_slots) == 2

        # Add slots to the end, except for the last one, which we will use to test invalid SP
        blocks_2 = bt.get_consecutive_blocks(1,
                                             block_list_input=blocks,
                                             skip_slots=3)
        for slot in blocks_2[-1].finished_sub_slots[:-1]:
            store.new_finished_sub_slot(slot, blockchain.sub_blocks,
                                        blockchain.get_peak())
        finished_sub_slots = blocks_2[-1].finished_sub_slots
        assert len(store.finished_sub_slots) == 4

        # Test adding signage points for overflow blocks (sp_sub_slot)
        ss_start_iters = peak.sp_sub_slot_total_iters(test_constants)
        # for i in range(peak.signage_point_index, test_constants.NUM_SPS_SUB_SLOT):
        #     if i < peak.signage_point_index:
        #         continue
        #     latest = peak
        #     while latest.total_iters > peak.sp_total_iters(test_constants):
        #         latest = blockchain.sub_blocks[latest.prev_hash]
        #     sp = get_signage_point(
        #         test_constants,
        #         blockchain.sub_blocks,
        #         latest,
        #         ss_start_iters,
        #         uint8(i),
        #         [],
        #         peak.sub_slot_iters,
        #     )
        #     assert store.new_signage_point(i, blockchain.sub_blocks, peak, peak.sub_slot_iters, sp)

        # Test adding signage points for overflow blocks (ip_sub_slot)
        for i in range(
                1, test_constants.NUM_SPS_SUB_SLOT -
                test_constants.NUM_SP_INTERVALS_EXTRA):
            sp = get_signage_point(
                test_constants,
                blockchain.sub_blocks,
                peak,
                peak.ip_sub_slot_total_iters(test_constants),
                uint8(i),
                [],
                peak.sub_slot_iters,
            )
            assert store.new_signage_point(i, blockchain.sub_blocks, peak,
                                           peak.sub_slot_iters, sp)

        # Test adding future signage point, a few slots forward (good)
        saved_sp_hash = None
        for slot_offset in range(1, len(finished_sub_slots)):
            for i in range(
                    1,
                    test_constants.NUM_SPS_SUB_SLOT -
                    test_constants.NUM_SP_INTERVALS_EXTRA,
            ):
                sp = get_signage_point(
                    test_constants,
                    blockchain.sub_blocks,
                    peak,
                    peak.ip_sub_slot_total_iters(test_constants) +
                    slot_offset * peak.sub_slot_iters,
                    uint8(i),
                    finished_sub_slots[:slot_offset],
                    peak.sub_slot_iters,
                )
                saved_sp_hash = sp.cc_vdf.output.get_hash()
                assert store.new_signage_point(i, blockchain.sub_blocks, peak,
                                               peak.sub_slot_iters, sp)

        # Test adding future signage point (bad)
        for i in range(
                1, test_constants.NUM_SPS_SUB_SLOT -
                test_constants.NUM_SP_INTERVALS_EXTRA):
            sp = get_signage_point(
                test_constants,
                blockchain.sub_blocks,
                peak,
                peak.ip_sub_slot_total_iters(test_constants) +
                len(finished_sub_slots) * peak.sub_slot_iters,
                uint8(i),
                finished_sub_slots[:len(finished_sub_slots)],
                peak.sub_slot_iters,
            )
            assert not store.new_signage_point(i, blockchain.sub_blocks, peak,
                                               peak.sub_slot_iters, sp)

        # Test adding past signage point
        sp = SignagePoint(
            blocks[1].reward_chain_sub_block.challenge_chain_sp_vdf,
            blocks[1].challenge_chain_sp_proof,
            blocks[1].reward_chain_sub_block.reward_chain_sp_vdf,
            blocks[1].reward_chain_sp_proof,
        )
        assert not store.new_signage_point(
            blocks[1].reward_chain_sub_block.signage_point_index,
            {},
            peak,
            blockchain.sub_blocks[
                blocks[1].header_hash].sp_sub_slot_total_iters(test_constants),
            sp,
        )

        # Get signage point by index
        assert (store.get_signage_point_by_index(
            finished_sub_slots[0].challenge_chain.get_hash(),
            4,
            finished_sub_slots[0].reward_chain.get_hash(),
        ) is not None)

        assert (store.get_signage_point_by_index(
            finished_sub_slots[0].challenge_chain.get_hash(), 4,
            std_hash(b"1")) is None)

        # Get signage point by hash
        assert store.get_signage_point(saved_sp_hash) is not None
        assert store.get_signage_point(std_hash(b"2")) is None

        # Test adding signage points before genesis
        store.initialize_genesis_sub_slot()
        assert len(store.finished_sub_slots) == 1
        for i in range(
                1, test_constants.NUM_SPS_SUB_SLOT -
                test_constants.NUM_SP_INTERVALS_EXTRA):
            sp = get_signage_point(
                test_constants,
                {},
                None,
                uint128(0),
                uint8(i),
                [],
                peak.sub_slot_iters,
            )
            assert store.new_signage_point(i, {}, None, peak.sub_slot_iters,
                                           sp)

        blocks_3 = bt.get_consecutive_blocks(1, skip_slots=2)
        for slot in blocks_3[-1].finished_sub_slots:
            store.new_finished_sub_slot(slot, {}, None)
        assert len(store.finished_sub_slots) == 3
        finished_sub_slots = blocks_3[-1].finished_sub_slots

        for slot_offset in range(1, len(finished_sub_slots) + 1):
            for i in range(
                    1,
                    test_constants.NUM_SPS_SUB_SLOT -
                    test_constants.NUM_SP_INTERVALS_EXTRA,
            ):
                sp = get_signage_point(
                    test_constants,
                    {},
                    None,
                    slot_offset * peak.sub_slot_iters,
                    uint8(i),
                    finished_sub_slots[:slot_offset],
                    peak.sub_slot_iters,
                )
                assert store.new_signage_point(i, {}, None,
                                               peak.sub_slot_iters, sp)

        # Test adding signage points after genesis
        blocks_4 = bt.get_consecutive_blocks(1)
        blocks_5 = bt.get_consecutive_blocks(1,
                                             block_list_input=blocks_4,
                                             skip_slots=1)

        # If this is not the case, fix test to find a block that is
        assert (blocks_4[-1].reward_chain_sub_block.signage_point_index <
                test_constants.NUM_SPS_SUB_SLOT -
                test_constants.NUM_SP_INTERVALS_EXTRA)
        await blockchain.receive_block(blocks_4[-1])
        sb = blockchain.sub_blocks[blocks_4[-1].header_hash]
        store.new_peak(sb, None, None, False, blockchain.sub_blocks)
        for i in range(
                sb.signage_point_index + test_constants.NUM_SP_INTERVALS_EXTRA,
                test_constants.NUM_SPS_SUB_SLOT,
        ):
            if is_overflow_sub_block(test_constants, i):
                finished_sub_slots = blocks_5[-1].finished_sub_slots
            else:
                finished_sub_slots = []

            sp = get_signage_point(
                test_constants,
                blockchain.sub_blocks,
                sb,
                uint128(0),
                uint8(i),
                finished_sub_slots,
                peak.sub_slot_iters,
            )
            assert store.new_signage_point(i, empty_blockchain.sub_blocks, sb,
                                           peak.sub_slot_iters, sp)

        # Test future EOS cache
        store.initialize_genesis_sub_slot()
        blocks = bt.get_consecutive_blocks(1)
        await blockchain.receive_block(blocks[-1])
        while True:
            blocks = bt.get_consecutive_blocks(1, block_list_input=blocks)
            await blockchain.receive_block(blocks[-1])
            sb = blockchain.sub_blocks[blocks[-1].header_hash]
            if sb.first_in_sub_slot:
                break
        assert len(blocks) >= 3
        dependant_sub_slots = blocks[-1].finished_sub_slots
        for block in blocks[:-2]:
            sb = blockchain.sub_blocks[block.header_hash]
            sp_sub_slot, ip_sub_slot = await blockchain.get_sp_and_ip_sub_slots(
                block.header_hash)
            peak = sb
            res = store.new_peak(sb, sp_sub_slot, ip_sub_slot, False,
                                 blockchain.sub_blocks)
            assert res[0] is None

        assert store.new_finished_sub_slot(dependant_sub_slots[0],
                                           blockchain.sub_blocks, peak) is None
        block = blocks[-2]
        sb = blockchain.sub_blocks[block.header_hash]
        sp_sub_slot, ip_sub_slot = await blockchain.get_sp_and_ip_sub_slots(
            block.header_hash)
        res = store.new_peak(sb, sp_sub_slot, ip_sub_slot, False,
                             blockchain.sub_blocks)
        assert res[0] == dependant_sub_slots[0]
        assert res[1] == res[2] == []

        # Test future IP cache
        store.initialize_genesis_sub_slot()
        blocks = bt.get_consecutive_blocks(60)

        for block in blocks[:5]:
            await blockchain.receive_block(block)
            sp_sub_slot, ip_sub_slot = await blockchain.get_sp_and_ip_sub_slots(
                block.header_hash)
            res = store.new_peak(sb, sp_sub_slot, ip_sub_slot, False,
                                 blockchain.sub_blocks)
            assert res[0] is None

        case_0, case_1 = False, False
        for i in range(5, len(blocks) - 1):
            prev_block = blocks[i]
            block = blocks[i + 1]
            new_ip = NewInfusionPointVDF(
                block.reward_chain_sub_block.get_unfinished().get_hash(),
                block.reward_chain_sub_block.challenge_chain_ip_vdf,
                block.challenge_chain_ip_proof,
                block.reward_chain_sub_block.reward_chain_ip_vdf,
                block.reward_chain_ip_proof,
                block.reward_chain_sub_block.infused_challenge_chain_ip_vdf,
                block.infused_challenge_chain_ip_proof,
            )
            store.add_to_future_ip(new_ip)

            await blockchain.receive_block(prev_block)
            sp_sub_slot, ip_sub_slot = await blockchain.get_sp_and_ip_sub_slots(
                prev_block.header_hash)
            sb = blockchain.sub_blocks[prev_block.header_hash]
            res = store.new_peak(sb, sp_sub_slot, ip_sub_slot, False,
                                 blockchain.sub_blocks)
            if len(block.finished_sub_slots) == 0:
                case_0 = True
                assert res[2] == [new_ip]
            else:
                case_1 = True
                assert res[2] == []
                found_ips = []
                for ss in block.finished_sub_slots:
                    found_ips += store.new_finished_sub_slot(
                        ss, blockchain.sub_blocks, sb)
                assert found_ips == [new_ip]

        # If flaky, increase the number of blocks created
        assert case_0 and case_1
Esempio n. 5
0
    async def test1(self, two_nodes):
        num_blocks = 5
        test_rpc_port = uint16(21522)
        nodes, _ = two_nodes
        full_node_api_1, full_node_api_2 = nodes
        server_1 = full_node_api_1.full_node.server
        server_2 = full_node_api_2.full_node.server

        def stop_node_cb():
            full_node_api_1._close()
            server_1.close_all()

        full_node_rpc_api = FullNodeRpcApi(full_node_api_1.full_node)

        config = bt.config
        hostname = config["self_hostname"]
        daemon_port = config["daemon_port"]

        rpc_cleanup = await start_rpc_server(
            full_node_rpc_api,
            hostname,
            daemon_port,
            test_rpc_port,
            stop_node_cb,
            bt.root_path,
            config,
            connect_to_daemon=False,
        )

        try:
            client = await FullNodeRpcClient.create(self_hostname,
                                                    test_rpc_port,
                                                    bt.root_path, config)
            state = await client.get_blockchain_state()
            assert state["peak"] is None
            assert not state["sync"]["sync_mode"]
            assert state["difficulty"] > 0
            assert state["sub_slot_iters"] > 0

            blocks = bt.get_consecutive_blocks(num_blocks)
            blocks = bt.get_consecutive_blocks(
                num_blocks,
                block_list_input=blocks,
                guarantee_transaction_block=True)

            assert len(await client.get_unfinished_block_headers()) == 0
            assert len((await client.get_block_records(0, 100))) == 0
            for block in blocks:
                if is_overflow_block(
                        test_constants,
                        block.reward_chain_block.signage_point_index):
                    finished_ss = block.finished_sub_slots[:-1]
                else:
                    finished_ss = block.finished_sub_slots

                unf = UnfinishedBlock(
                    finished_ss,
                    block.reward_chain_block.get_unfinished(),
                    block.challenge_chain_sp_proof,
                    block.reward_chain_sp_proof,
                    block.foliage,
                    block.foliage_transaction_block,
                    block.transactions_info,
                    block.transactions_generator,
                    [],
                )
                await full_node_api_1.full_node.respond_unfinished_block(
                    full_node_protocol.RespondUnfinishedBlock(unf), None)
                await full_node_api_1.full_node.respond_block(
                    full_node_protocol.RespondBlock(block), None)

            assert len(await client.get_unfinished_block_headers()) > 0
            assert len(await client.get_all_block(0, 2)) == 2
            state = await client.get_blockchain_state()

            block = await client.get_block(state["peak"].header_hash)
            assert block == blocks[-1]
            assert (await client.get_block(bytes([1] * 32))) is None

            assert (await client.get_block_record_by_height(2)
                    ).header_hash == blocks[2].header_hash

            assert len((await client.get_block_records(0,
                                                       100))) == num_blocks * 2

            assert (await client.get_block_record_by_height(100)) is None

            ph = list(blocks[-1].get_included_reward_coins())[0].puzzle_hash
            coins = await client.get_coin_records_by_puzzle_hash(ph)
            print(coins)
            assert len(coins) >= 1

            additions, removals = await client.get_additions_and_removals(
                blocks[-1].header_hash)
            assert len(additions) >= 2 and len(removals) == 0

            wallet = WalletTool()
            wallet_receiver = WalletTool(
                AugSchemeMPL.key_gen(std_hash(b"123123")))
            ph = wallet.get_new_puzzlehash()
            ph_2 = wallet.get_new_puzzlehash()
            ph_receiver = wallet_receiver.get_new_puzzlehash()

            assert len(await client.get_coin_records_by_puzzle_hash(ph)) == 0
            assert len(
                await client.get_coin_records_by_puzzle_hash(ph_receiver)) == 0
            blocks = bt.get_consecutive_blocks(
                2,
                block_list_input=blocks,
                guarantee_transaction_block=True,
                farmer_reward_puzzle_hash=ph,
                pool_reward_puzzle_hash=ph,
            )
            for block in blocks[-2:]:
                await full_node_api_1.full_node.respond_block(
                    full_node_protocol.RespondBlock(block))
            assert len(await client.get_coin_records_by_puzzle_hash(ph)) == 2
            assert len(
                await client.get_coin_records_by_puzzle_hash(ph_receiver)) == 0

            coin_to_spend = list(blocks[-1].get_included_reward_coins())[0]

            spend_bundle = wallet.generate_signed_transaction(
                coin_to_spend.amount, ph_receiver, coin_to_spend)

            assert len(await client.get_all_mempool_items()) == 0
            assert len(await client.get_all_mempool_tx_ids()) == 0
            assert (await client.get_mempool_item_by_tx_id(spend_bundle.name()
                                                           )) is None

            await client.push_tx(spend_bundle)

            assert len(await client.get_all_mempool_items()) == 1
            assert len(await client.get_all_mempool_tx_ids()) == 1
            assert (SpendBundle.from_json_dict(
                list((await client.get_all_mempool_items()
                      ).values())[0]["spend_bundle"]) == spend_bundle)
            assert (await
                    client.get_all_mempool_tx_ids())[0] == spend_bundle.name()
            assert (SpendBundle.from_json_dict(
                (await client.get_mempool_item_by_tx_id(
                    spend_bundle.name()))["spend_bundle"]) == spend_bundle)

            await full_node_api_1.farm_new_transaction_block(
                FarmNewBlockProtocol(ph_2))

            assert len(
                await client.get_coin_records_by_puzzle_hash(ph_receiver)) == 1
            assert len(
                list(
                    filter(lambda cr: not cr.spent,
                           (await
                            client.get_coin_records_by_puzzle_hash(ph))))) == 3
            assert len(await
                       client.get_coin_records_by_puzzle_hash(ph, False)) == 3
            assert len(await client.get_coin_records_by_puzzle_hash(ph,
                                                                    True)) == 4

            assert len(await client.get_coin_records_by_puzzle_hash(
                ph, True, 0, 100)) == 4
            assert len(await client.get_coin_records_by_puzzle_hash(
                ph, True, 50, 100)) == 0
            assert len(await client.get_coin_records_by_puzzle_hash(
                ph, True, 0, blocks[-1].height + 1)) == 2
            assert len(await
                       client.get_coin_records_by_puzzle_hash(ph, True, 0,
                                                              1)) == 0

            assert len(await client.get_connections()) == 0

            await client.open_connection(self_hostname, server_2._port)

            async def num_connections():
                return len(await client.get_connections())

            await time_out_assert(10, num_connections, 1)
            connections = await client.get_connections()

            await client.close_connection(connections[0]["node_id"])
            await time_out_assert(10, num_connections, 0)
        finally:
            # Checks that the RPC manages to stop the node
            client.close()
            await client.await_closed()
            await rpc_cleanup()