async def test_blocks_load(self, two_nodes):
        num_blocks = 50
        full_node_1, full_node_2, server_1, server_2 = two_nodes
        blocks = bt.get_consecutive_blocks(num_blocks)
        peer = await connect_and_get_peer(server_1, server_2)
        await full_node_1.respond_sub_block(
            full_node_protocol.RespondSubBlock(blocks[0]), peer)

        await server_2.start_client(
            PeerInfo(self_hostname, uint16(server_1._port)), None)

        async def num_connections():
            return len(server_2.get_connections())

        await time_out_assert(10, num_connections, 1)

        start_unf = time.time()
        for i in range(1, num_blocks):
            await time_out_assert(5, node_height_at_least, True, full_node_2,
                                  i - 2)
            msg = Message("respond_sub_block",
                          full_node_protocol.RespondSubBlock(blocks[i]))
            await server_1.send_to_all([msg], NodeType.FULL_NODE)
        print(
            f"Time taken to process {num_blocks} is {time.time() - start_unf}")
        assert time.time() - start_unf < 100
Exemple #2
0
    async def test_long_sync_wallet(self, wallet_node, default_1000_blocks):

        full_node_api, wallet_node, full_node_server, wallet_server = wallet_node

        for block in default_1000_blocks:
            await full_node_api.full_node.respond_sub_block(
                full_node_protocol.RespondSubBlock(block))

        await wallet_server.start_client(
            PeerInfo(self_hostname, uint16(full_node_server._port)), None)

        # The second node should eventually catch up to the first one, and have the
        # same tip at height num_blocks - 1.
        await time_out_assert(600, wallet_height_at_least, True, wallet_node,
                              len(default_1000_blocks) - 1)

        # Tests a reorg with the wallet
        num_blocks = 30
        blocks_reorg = bt.get_consecutive_blocks(
            num_blocks, block_list_input=default_1000_blocks[:-5])

        for i in range(1, len(blocks_reorg)):
            await full_node_api.full_node.respond_sub_block(
                full_node_protocol.RespondSubBlock(blocks_reorg[i]))

        await time_out_assert(600, wallet_height_at_least, True, wallet_node,
                              len(default_1000_blocks) + num_blocks - 5 - 1)
    async def test_validate_blockchain_spend_reorg_since_genesis(
            self, two_nodes):
        num_blocks = 10
        wallet_a = WALLET_A
        coinbase_puzzlehash = WALLET_A_PUZZLE_HASHES[0]
        receiver_1_puzzlehash = WALLET_A_PUZZLE_HASHES[1]

        blocks = bt.get_consecutive_blocks(
            num_blocks,
            farmer_reward_puzzle_hash=coinbase_puzzlehash,
            guarantee_block=True)
        full_node_api_1, full_node_api_2, server_1, server_2 = two_nodes

        for block in blocks:
            await full_node_api_1.full_node.respond_sub_block(
                full_node_protocol.RespondSubBlock(block))

        spend_block = blocks[-1]
        spend_coin = None
        for coin in list(spend_block.get_included_reward_coins()):
            if coin.puzzle_hash == coinbase_puzzlehash:
                spend_coin = coin
        spend_bundle = wallet_a.generate_signed_transaction(
            1000, receiver_1_puzzlehash, spend_coin)

        new_blocks = bt.get_consecutive_blocks(
            1,
            blocks,
            seed=b"",
            farmer_reward_puzzle_hash=coinbase_puzzlehash,
            transaction_data=spend_bundle)
        await full_node_api_1.full_node.respond_sub_block(
            full_node_protocol.RespondSubBlock(new_blocks[-1]))

        # Spends a coin in a genesis reorg, that was already spent
        new_blocks = bt.get_consecutive_blocks(
            12,
            [],
            seed=b"reorg since genesis",
            farmer_reward_puzzle_hash=coinbase_puzzlehash,
        )
        for block in new_blocks:
            await full_node_api_1.full_node.respond_sub_block(
                full_node_protocol.RespondSubBlock(block))

        new_blocks = bt.get_consecutive_blocks(
            1,
            new_blocks,
            seed=b"reorg since genesis",
            farmer_reward_puzzle_hash=coinbase_puzzlehash,
            transaction_data=spend_bundle,
        )

        await full_node_api_1.full_node.respond_sub_block(
            full_node_protocol.RespondSubBlock(new_blocks[-1]))
Exemple #4
0
    async def test_wallet_reorg_get_coinbase(self, wallet_node_simulator,
                                             default_400_blocks):
        full_nodes, wallets = wallet_node_simulator
        full_node_api = full_nodes[0]
        wallet_node, server_2 = wallets[0]
        fn_server = full_node_api.full_node.server
        wsm = wallet_node.wallet_state_manager
        wallet = wallet_node.wallet_state_manager.main_wallet
        ph = await wallet.get_new_puzzlehash()

        await server_2.start_client(
            PeerInfo(self_hostname, uint16(fn_server._port)), None)

        # Insert 400 blocks
        for block in default_400_blocks:
            await full_node_api.full_node.respond_sub_block(
                full_node_protocol.RespondSubBlock(block))

        # Reorg blocks that carry reward
        num_blocks_reorg = 30
        blocks_reorg = bt.get_consecutive_blocks(
            num_blocks_reorg, block_list_input=default_400_blocks[:-5])

        for block in blocks_reorg[:-5]:
            await full_node_api.full_node.respond_sub_block(
                full_node_protocol.RespondSubBlock(block))

        async def get_tx_count(wallet_id):
            txs = await wsm.get_all_transactions(wallet_id)
            return len(txs)

        await time_out_assert(10, get_tx_count, 0, 1)

        num_blocks_reorg_1 = 40
        blocks_reorg_1 = bt.get_consecutive_blocks(
            1,
            pool_reward_puzzle_hash=ph,
            farmer_reward_puzzle_hash=ph,
            block_list_input=blocks_reorg[:-30])
        blocks_reorg_2 = bt.get_consecutive_blocks(
            num_blocks_reorg_1, block_list_input=blocks_reorg_1)

        for block in blocks_reorg_2[-41:]:
            await full_node_api.full_node.respond_sub_block(
                full_node_protocol.RespondSubBlock(block))

        # Confirm we have the funds
        funds = calculate_pool_reward(uint32(
            len(blocks_reorg_1))) + calculate_base_farmer_reward(
                uint32(len(blocks_reorg_1)))

        await time_out_assert(10, get_tx_count, 2, 1)
        await time_out_assert(10, wallet.get_confirmed_balance, funds)
    async def test_validate_blockchain_spend_reorg_cb_coin(self, two_nodes):
        num_blocks = 15
        wallet_a = WALLET_A
        coinbase_puzzlehash = WALLET_A_PUZZLE_HASHES[0]
        receiver_1_puzzlehash = WALLET_A_PUZZLE_HASHES[1]

        blocks = bt.get_consecutive_blocks(
            num_blocks, farmer_reward_puzzle_hash=coinbase_puzzlehash)
        full_node_api_1, full_node_api_2, server_1, server_2 = two_nodes

        for block in blocks:
            await full_node_api_1.full_node.respond_sub_block(
                full_node_protocol.RespondSubBlock(block))

        # Spends a coinbase created in reorg
        new_blocks = bt.get_consecutive_blocks(
            5,
            blocks[:6],
            seed=b"reorg cb coin",
            farmer_reward_puzzle_hash=coinbase_puzzlehash,
            guarantee_block=True,
        )

        for block in new_blocks:
            await full_node_api_1.full_node.respond_sub_block(
                full_node_protocol.RespondSubBlock(block))

        spend_block = new_blocks[-1]
        spend_coin = None
        for coin in list(spend_block.get_included_reward_coins()):
            if coin.puzzle_hash == coinbase_puzzlehash:
                spend_coin = coin
        spend_bundle = wallet_a.generate_signed_transaction(
            1000, receiver_1_puzzlehash, spend_coin)

        new_blocks = bt.get_consecutive_blocks(
            1,
            new_blocks,
            seed=b"reorg cb coin",
            farmer_reward_puzzle_hash=coinbase_puzzlehash,
            transaction_data=spend_bundle,
            guarantee_block=True,
        )

        await full_node_api_1.full_node.respond_sub_block(
            full_node_protocol.RespondSubBlock(new_blocks[-1]))

        coins_created = []
        for coin in new_blocks[-1].additions():
            if coin.puzzle_hash == receiver_1_puzzlehash:
                coins_created.append(coin)
        assert len(coins_created) == 1
Exemple #6
0
    async def test_wallet_reorg_sync(self, wallet_node_simulator,
                                     default_400_blocks):
        num_blocks = 5
        full_nodes, wallets = wallet_node_simulator
        full_node_api = full_nodes[0]
        wallet_node, server_2 = wallets[0]
        fn_server = full_node_api.full_node.server
        wsm: WalletStateManager = wallet_node.wallet_state_manager
        wallet = wsm.main_wallet
        ph = await wallet.get_new_puzzlehash()

        await server_2.start_client(
            PeerInfo(self_hostname, uint16(fn_server._port)), None)

        # Insert 400 blocks
        for block in default_400_blocks:
            await full_node_api.full_node.respond_sub_block(
                full_node_protocol.RespondSubBlock(block))

        # Farm few more with reward
        for i in range(0, num_blocks):
            await full_node_api.farm_new_block(FarmNewBlockProtocol(ph))

        # Confirm we have the funds
        funds = sum([
            calculate_pool_reward(uint32(i)) +
            calculate_base_farmer_reward(uint32(i))
            for i in range(1, num_blocks)
        ])

        await time_out_assert(5, wallet.get_confirmed_balance, funds)

        async def get_tx_count(wallet_id):
            txs = await wsm.get_all_transactions(wallet_id)
            return len(txs)

        await time_out_assert(5, get_tx_count, 2 * (num_blocks - 1), 1)

        # Reorg blocks that carry reward
        num_blocks = 30
        blocks_reorg = bt.get_consecutive_blocks(
            num_blocks, block_list_input=default_400_blocks[:-5])

        for block in blocks_reorg[-30:]:
            await full_node_api.full_node.respond_sub_block(
                full_node_protocol.RespondSubBlock(block))

        await time_out_assert(5, get_tx_count, 0, 1)
        await time_out_assert(5, wallet.get_confirmed_balance, 0)
Exemple #7
0
    async def test_assert_fee_condition_wrong_fee(self, two_nodes):
        reward_ph = WALLET_A.get_new_puzzlehash()
        full_node_1, full_node_2, server_1, server_2 = two_nodes
        blocks = await full_node_1.get_all_full_blocks()
        start_sub_height = blocks[-1].sub_block_height
        blocks = bt.get_consecutive_blocks(
            3,
            block_list_input=blocks,
            guarantee_block=True,
            farmer_reward_puzzle_hash=reward_ph,
            pool_reward_puzzle_hash=reward_ph,
        )
        peer = await connect_and_get_peer(server_1, server_2)

        for block in blocks:
            await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(block))

        await time_out_assert(60, node_height_at_least, True, full_node_1, start_sub_height + 3)

        cvp = ConditionVarPair(ConditionOpcode.ASSERT_FEE, [int_to_bytes(10)])
        dic = {cvp.opcode: [cvp]}

        spend_bundle1 = generate_test_spend_bundle(list(blocks[-1].get_included_reward_coins())[0], dic, uint64(9))

        assert spend_bundle1 is not None

        tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(spend_bundle1)

        await full_node_1.respond_transaction(tx1, peer)

        mempool_bundle = full_node_1.full_node.mempool_manager.get_spendbundle(spend_bundle1.name())

        assert mempool_bundle is None
Exemple #8
0
    async def test_basic_mempool(self, two_nodes):
        reward_ph = WALLET_A.get_new_puzzlehash()
        blocks = bt.get_consecutive_blocks(
            3,
            guarantee_block=True,
            farmer_reward_puzzle_hash=reward_ph,
            pool_reward_puzzle_hash=reward_ph,
        )
        full_node_1, full_node_2, server_1, server_2 = two_nodes
        peer = await connect_and_get_peer(server_1, server_2)

        for block in blocks:
            await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(block))

        await time_out_assert(60, node_height_at_least, True, full_node_2, 2)

        spend_bundle = generate_test_spend_bundle(list(blocks[-1].get_included_reward_coins())[0])
        assert spend_bundle is not None
        tx: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(spend_bundle)
        await full_node_1.respond_transaction(tx, peer)

        await time_out_assert(
            10,
            full_node_1.full_node.mempool_manager.get_spendbundle,
            spend_bundle,
            spend_bundle.name(),
        )
Exemple #9
0
    async def test_agg_sig_condition(self, two_nodes):
        reward_ph = WALLET_A.get_new_puzzlehash()
        full_node_1, full_node_2, server_1, server_2 = two_nodes
        blocks = await full_node_1.get_all_full_blocks()
        start_sub_height = blocks[-1].sub_block_height
        blocks = bt.get_consecutive_blocks(
            3,
            block_list_input=blocks,
            guarantee_block=True,
            farmer_reward_puzzle_hash=reward_ph,
            pool_reward_puzzle_hash=reward_ph,
        )

        for block in blocks:
            await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(block))

        await time_out_assert(60, node_height_at_least, True, full_node_1, start_sub_height + 3)

        # this code has been changed to use generate_test_spend_bundle
        # not quite sure why all the gymnastics are being performed

        coin = list(blocks[-1].get_included_reward_coins())[0]
        spend_bundle_0 = generate_test_spend_bundle(coin)
        unsigned: List[CoinSolution] = spend_bundle_0.coin_solutions

        assert len(unsigned) == 1
        coin_solution = unsigned[0]

        err, con, cost = conditions_for_solution(coin_solution.solution)
        assert con is not None
Exemple #10
0
    async def test_invalid_block_age(self, two_nodes):
        reward_ph = WALLET_A.get_new_puzzlehash()
        blocks = bt.get_consecutive_blocks(
            3,
            guarantee_block=True,
            farmer_reward_puzzle_hash=reward_ph,
            pool_reward_puzzle_hash=reward_ph,
        )
        full_node_1, full_node_2, server_1, server_2 = two_nodes
        peer = await connect_and_get_peer(server_1, server_2)

        for block in blocks:
            await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(block))

        await time_out_assert(60, node_height_at_least, True, full_node_1, 2)

        cvp = ConditionVarPair(ConditionOpcode.ASSERT_BLOCK_AGE_EXCEEDS, [uint64(5).to_bytes(4, "big")])
        dic = {cvp.opcode: [cvp]}

        spend_bundle1 = generate_test_spend_bundle(list(blocks[-1].get_included_reward_coins())[0], dic)

        assert spend_bundle1 is not None
        tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(spend_bundle1)
        await full_node_1.respond_transaction(tx1, peer)

        sb1 = full_node_1.full_node.mempool_manager.get_spendbundle(spend_bundle1.name())
        assert sb1 is None
Exemple #11
0
    async def test_stealing_fee(self, two_nodes):
        reward_ph = WALLET_A.get_new_puzzlehash()
        full_node_1, full_node_2, server_1, server_2 = two_nodes
        blocks = await full_node_1.get_all_full_blocks()
        start_height = blocks[-1].height
        blocks = bt.get_consecutive_blocks(
            5,
            block_list_input=blocks,
            guarantee_block=True,
            farmer_reward_puzzle_hash=reward_ph,
            pool_reward_puzzle_hash=reward_ph,
        )

        full_node_1, full_node_2, server_1, server_2 = two_nodes
        peer = await connect_and_get_peer(server_1, server_2)

        for block in blocks:
            await full_node_1.full_node.respond_sub_block(
                full_node_protocol.RespondSubBlock(block))

        await time_out_assert(60, node_height_at_least, True, full_node_1,
                              start_height + 5)

        receiver_puzzlehash = BURN_PUZZLE_HASH

        cvp = ConditionVarPair(ConditionOpcode.ASSERT_FEE, [int_to_bytes(10)])
        dic = {cvp.opcode: [cvp]}

        fee = 9

        coin_1 = list(blocks[-2].get_included_reward_coins())[0]
        coin_2 = None
        for coin in list(blocks[-1].get_included_reward_coins()):
            if coin.amount == coin_1.amount:
                coin_2 = coin
        spend_bundle1 = generate_test_spend_bundle(coin_1, dic, uint64(fee))

        steal_fee_spendbundle = WALLET_A.generate_signed_transaction(
            coin_1.amount + fee - 4, receiver_puzzlehash, coin_2)

        assert spend_bundle1 is not None
        assert steal_fee_spendbundle is not None

        combined = SpendBundle.aggregate(
            [spend_bundle1, steal_fee_spendbundle])

        assert combined.fees() == 4

        tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
            spend_bundle1)

        await full_node_1.respond_transaction(tx1, peer)

        mempool_bundle = full_node_1.full_node.mempool_manager.get_spendbundle(
            spend_bundle1.name())

        assert mempool_bundle is None
    async def test_close_height_but_big_reorg(self, three_nodes):
        blocks_a = bt.get_consecutive_blocks(50)
        blocks_b = bt.get_consecutive_blocks(51, seed=b"B")
        blocks_c = bt.get_consecutive_blocks(90, seed=b"C")
        full_node_1, full_node_2, full_node_3 = three_nodes
        server_1 = full_node_1.full_node.server
        server_2 = full_node_2.full_node.server
        server_3 = full_node_3.full_node.server

        for block in blocks_a:
            await full_node_1.full_node.respond_sub_block(
                full_node_protocol.RespondSubBlock(block))
        for block in blocks_b:
            await full_node_2.full_node.respond_sub_block(
                full_node_protocol.RespondSubBlock(block))
        for block in blocks_c:
            await full_node_3.full_node.respond_sub_block(
                full_node_protocol.RespondSubBlock(block))

        await server_2.start_client(
            PeerInfo(self_hostname, uint16(server_1._port)),
            on_connect=full_node_2.full_node.on_connect,
        )
        await time_out_assert(60, node_height_exactly, True, full_node_1, 50)
        await time_out_assert(60, node_height_exactly, True, full_node_2, 50)
        await time_out_assert(60, node_height_exactly, True, full_node_3, 89)

        await server_3.start_client(
            PeerInfo(self_hostname, uint16(server_1._port)),
            on_connect=full_node_3.full_node.on_connect,
        )

        await server_3.start_client(
            PeerInfo(self_hostname, uint16(server_2._port)),
            on_connect=full_node_3.full_node.on_connect,
        )
        await time_out_assert(60, node_height_exactly, True, full_node_1, 89)
        await time_out_assert(60, node_height_exactly, True, full_node_2, 89)
        await time_out_assert(60, node_height_exactly, True, full_node_3, 89)
Exemple #13
0
    async def test_invalid_announcement_consumed_two(self, two_nodes):
        reward_ph = WALLET_A.get_new_puzzlehash()
        full_node_1, full_node_2, server_1, server_2 = two_nodes
        blocks = await full_node_1.get_all_full_blocks()
        start_height = blocks[-1].height if len(blocks) > 0 else -1
        blocks = bt.get_consecutive_blocks(
            3,
            block_list_input=blocks,
            guarantee_block=True,
            farmer_reward_puzzle_hash=reward_ph,
            pool_reward_puzzle_hash=reward_ph,
        )
        peer = await connect_and_get_peer(server_1, server_2)

        for block in blocks:
            await full_node_1.full_node.respond_sub_block(
                full_node_protocol.RespondSubBlock(block))

        await time_out_assert(60, node_height_at_least, True, full_node_1,
                              start_height + 3)

        coin_1 = list(blocks[-2].get_included_reward_coins())[0]
        coin_2 = list(blocks[-1].get_included_reward_coins())[0]

        announce = Announcement(coin_1.name(), bytes("test", "utf-8"))

        cvp = ConditionVarPair(ConditionOpcode.ASSERT_ANNOUNCEMENT,
                               [announce.name()])

        dic = {cvp.opcode: [cvp]}

        cvp2 = ConditionVarPair(
            ConditionOpcode.CREATE_ANNOUNCEMENT,
            [bytes("test", "utf-8")],
        )
        dic2 = {cvp.opcode: [cvp2]}
        spend_bundle1 = generate_test_spend_bundle(coin_1, dic)

        spend_bundle2 = generate_test_spend_bundle(coin_2, dic2)

        bundle = SpendBundle.aggregate([spend_bundle1, spend_bundle2])

        tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
            spend_bundle1)
        await full_node_1.respond_transaction(tx1, peer)

        mempool_bundle = full_node_1.full_node.mempool_manager.get_spendbundle(
            bundle.name())

        assert mempool_bundle is None
    async def test_backtrack_sync_2(self, two_nodes):
        blocks = bt.get_consecutive_blocks(1, skip_slots=3)
        blocks = bt.get_consecutive_blocks(8, blocks, skip_slots=0)
        full_node_1, full_node_2, server_1, server_2 = two_nodes

        # 3 blocks to node_1 in different sub slots
        for block in blocks:
            await full_node_1.full_node.respond_sub_block(
                full_node_protocol.RespondSubBlock(block))

        await server_2.start_client(
            PeerInfo(self_hostname, uint16(server_1._port)),
            on_connect=full_node_2.full_node.on_connect,
        )
        await time_out_assert(60, node_height_exactly, True, full_node_2, 8)
    async def test_batch_sync(self, two_nodes):
        # Must be below "sync_block_behind_threshold" in the config
        num_blocks = 20
        num_blocks_2 = 9
        blocks = bt.get_consecutive_blocks(num_blocks)
        blocks_2 = bt.get_consecutive_blocks(num_blocks_2, seed=b"123")
        full_node_1, full_node_2, server_1, server_2 = two_nodes

        # 12 blocks to node_1
        for block in blocks:
            await full_node_1.full_node.respond_sub_block(
                full_node_protocol.RespondSubBlock(block))

        # 9 different blocks to node_2
        for block in blocks_2:
            await full_node_2.full_node.respond_sub_block(
                full_node_protocol.RespondSubBlock(block))

        await server_2.start_client(
            PeerInfo(self_hostname, uint16(server_1._port)),
            on_connect=full_node_2.full_node.on_connect,
        )
        await time_out_assert(60, node_height_exactly, True, full_node_2,
                              num_blocks - 1)
Exemple #16
0
    async def test_assert_time_exceeds_both_cases(self, two_nodes):
        reward_ph = WALLET_A.get_new_puzzlehash()
        full_node_1, full_node_2, server_1, server_2 = two_nodes
        blocks = await full_node_1.get_all_full_blocks()
        start_height = blocks[-1].height if len(blocks) > 0 else -1
        blocks = bt.get_consecutive_blocks(
            3,
            block_list_input=blocks,
            guarantee_block=True,
            farmer_reward_puzzle_hash=reward_ph,
            pool_reward_puzzle_hash=reward_ph,
        )
        peer = await connect_and_get_peer(server_1, server_2)

        for block in blocks:
            await full_node_1.full_node.respond_sub_block(
                full_node_protocol.RespondSubBlock(block))

        await time_out_assert(60, node_height_at_least, True, full_node_1,
                              start_height + 3)

        time_now = uint64(int(time() * 1000))
        time_now_plus_3 = time_now + 3000

        cvp = ConditionVarPair(ConditionOpcode.ASSERT_TIME_EXCEEDS,
                               [time_now_plus_3.to_bytes(8, "big")])
        dic = {cvp.opcode: [cvp]}

        spend_bundle1 = generate_test_spend_bundle(
            list(blocks[-1].get_included_reward_coins())[0], dic)

        assert spend_bundle1 is not None
        tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
            spend_bundle1)
        await full_node_1.respond_transaction(tx1, peer)

        # Sleep so that 3 sec passes
        await asyncio.sleep(3)

        tx2: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
            spend_bundle1)
        await full_node_1.respond_transaction(tx2, peer)

        sb1 = full_node_1.full_node.mempool_manager.get_spendbundle(
            spend_bundle1.name())

        assert sb1 is spend_bundle1
Exemple #17
0
    async def test_sync_from_zero(self, two_nodes, default_400_blocks):
        # Must be larger than "sync_block_behind_threshold" in the config
        num_blocks = len(default_400_blocks)
        blocks = default_400_blocks
        full_node_1, full_node_2, server_1, server_2 = two_nodes

        for block in blocks:
            await full_node_1.full_node.respond_sub_block(
                full_node_protocol.RespondSubBlock(block))

        await server_2.start_client(
            PeerInfo(self_hostname, uint16(server_1._port)), None)

        # The second node should eventually catch up to the first one, and have the
        # same tip at height num_blocks - 1 (or at least num_blocks - 3, in case we sync to below the tip)
        await time_out_assert(60, node_height_at_least, True, full_node_2,
                              num_blocks - 1)
Exemple #18
0
    async def test_double_spend_with_higher_fee(self, two_nodes):
        reward_ph = WALLET_A.get_new_puzzlehash()

        full_node_1, full_node_2, server_1, server_2 = two_nodes
        blocks = await full_node_1.get_all_full_blocks()
        start_height = blocks[-1].height
        blocks = bt.get_consecutive_blocks(
            3,
            block_list_input=blocks,
            guarantee_block=True,
            farmer_reward_puzzle_hash=reward_ph,
            pool_reward_puzzle_hash=reward_ph,
        )
        peer = await connect_and_get_peer(server_1, server_2)

        for block in blocks:
            await full_node_1.full_node.respond_sub_block(
                full_node_protocol.RespondSubBlock(block))
        await time_out_assert(60, node_height_at_least, True, full_node_1,
                              start_height + 3)

        spend_bundle1 = generate_test_spend_bundle(
            list(blocks[-1].get_included_reward_coins())[0])
        assert spend_bundle1 is not None
        tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
            spend_bundle1)

        await full_node_1.respond_transaction(tx1, peer)

        spend_bundle2 = generate_test_spend_bundle(list(
            blocks[-1].get_included_reward_coins())[0],
                                                   fee=uint64(1))

        assert spend_bundle2 is not None
        tx2: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
            spend_bundle2)

        await full_node_1.respond_transaction(tx2, peer)

        sb1 = full_node_1.full_node.mempool_manager.get_spendbundle(
            spend_bundle1.name())
        sb2 = full_node_1.full_node.mempool_manager.get_spendbundle(
            spend_bundle2.name())

        assert sb1 is None
        assert sb2 == spend_bundle2
    async def test_validate_blockchain_duplicate_output(self, two_nodes):
        num_blocks = 3
        wallet_a = WALLET_A
        coinbase_puzzlehash = WALLET_A_PUZZLE_HASHES[0]
        receiver_puzzlehash = BURN_PUZZLE_HASH

        blocks = bt.get_consecutive_blocks(
            num_blocks,
            farmer_reward_puzzle_hash=coinbase_puzzlehash,
            guarantee_block=True)
        full_node_api_1, full_node_api_2, server_1, server_2 = two_nodes
        full_node_1 = full_node_api_1.full_node

        for block in blocks:
            await full_node_api_1.full_node.respond_sub_block(
                full_node_protocol.RespondSubBlock(block))

        spend_block = blocks[2]

        spend_coin = None
        for coin in list(spend_block.get_included_reward_coins()):
            if coin.puzzle_hash == coinbase_puzzlehash:
                spend_coin = coin

        spend_bundle = wallet_a.generate_signed_transaction(
            1000, receiver_puzzlehash, spend_coin)
        spend_bundle_double = wallet_a.generate_signed_transaction(
            1000, receiver_puzzlehash, spend_coin)

        block_spendbundle = SpendBundle.aggregate(
            [spend_bundle, spend_bundle_double])

        new_blocks = bt.get_consecutive_blocks(
            1,
            block_list_input=blocks,
            farmer_reward_puzzle_hash=coinbase_puzzlehash,
            transaction_data=block_spendbundle,
            guarantee_block=True,
        )

        next_block = new_blocks[-1]
        res, err, _ = await full_node_1.blockchain.receive_block(next_block)
        assert res == ReceiveBlockResult.INVALID_BLOCK
        assert err == Err.DUPLICATE_OUTPUT
Exemple #20
0
    async def test_double_spend_same_bundle(self, two_nodes):
        reward_ph = WALLET_A.get_new_puzzlehash()
        full_node_1, full_node_2, server_1, server_2 = two_nodes
        blocks = await full_node_1.get_all_full_blocks()
        start_height = blocks[-1].height
        blocks = bt.get_consecutive_blocks(
            3,
            block_list_input=blocks,
            guarantee_block=True,
            farmer_reward_puzzle_hash=reward_ph,
            pool_reward_puzzle_hash=reward_ph,
        )
        peer = await connect_and_get_peer(server_1, server_2)

        for block in blocks:
            await full_node_1.full_node.respond_sub_block(
                full_node_protocol.RespondSubBlock(block))

        await time_out_assert(60, node_height_at_least, True, full_node_1,
                              start_height + 3)
        coin = list(blocks[-1].get_included_reward_coins())[0]
        spend_bundle1 = generate_test_spend_bundle(coin)

        assert spend_bundle1 is not None

        spend_bundle2 = generate_test_spend_bundle(
            coin,
            new_puzzle_hash=BURN_PUZZLE_HASH_2,
        )

        assert spend_bundle2 is not None

        spend_bundle_combined = SpendBundle.aggregate(
            [spend_bundle1, spend_bundle2])

        tx: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
            spend_bundle_combined)

        await full_node_1.respond_transaction(tx, peer)

        sb = full_node_1.full_node.mempool_manager.get_spendbundle(
            spend_bundle_combined.name())
        assert sb is None
Exemple #21
0
    async def test_invalid_my_id(self, two_nodes):
        reward_ph = WALLET_A.get_new_puzzlehash()
        full_node_1, full_node_2, server_1, server_2 = two_nodes
        blocks = await full_node_1.get_all_full_blocks()
        start_height = blocks[-1].height if len(blocks) > 0 else -1
        blocks = bt.get_consecutive_blocks(
            3,
            block_list_input=blocks,
            guarantee_block=True,
            farmer_reward_puzzle_hash=reward_ph,
            pool_reward_puzzle_hash=reward_ph,
        )
        peer = await connect_and_get_peer(server_1, server_2)

        for block in blocks:
            await full_node_1.full_node.respond_sub_block(
                full_node_protocol.RespondSubBlock(block))

        await time_out_assert(60, node_height_at_least, True, full_node_1,
                              start_height + 3)

        coin = list(blocks[-1].get_included_reward_coins())[0]
        coin_2 = list(blocks[-2].get_included_reward_coins())[0]
        cvp = ConditionVarPair(ConditionOpcode.ASSERT_MY_COIN_ID,
                               [coin_2.name()])
        dic = {cvp.opcode: [cvp]}

        spend_bundle1 = generate_test_spend_bundle(coin, dic)

        assert spend_bundle1 is not None
        tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
            spend_bundle1)
        await full_node_1.respond_transaction(tx1, peer)

        sb1 = full_node_1.full_node.mempool_manager.get_spendbundle(
            spend_bundle1.name())

        assert sb1 is None
Exemple #22
0
    async def test_correct_coin_consumed(self, two_nodes):
        reward_ph = WALLET_A.get_new_puzzlehash()
        full_node_1, full_node_2, server_1, server_2 = two_nodes
        blocks = await full_node_1.get_all_full_blocks()
        start_sub_height = blocks[-1].sub_block_height
        blocks = bt.get_consecutive_blocks(
            4,
            block_list_input=blocks,
            guarantee_block=True,
            farmer_reward_puzzle_hash=reward_ph,
            pool_reward_puzzle_hash=reward_ph,
        )
        peer = await connect_and_get_peer(server_1, server_2)

        for block in blocks:
            await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(block))

        await time_out_assert(60, node_height_at_least, True, full_node_1, start_sub_height + 4)

        coin_1 = list(blocks[-2].get_included_reward_coins())[0]
        coin_2 = list(blocks[-1].get_included_reward_coins())[0]
        cvp = ConditionVarPair(ConditionOpcode.ASSERT_COIN_CONSUMED, [coin_2.name()])
        dic = {cvp.opcode: [cvp]}

        spend_bundle1 = generate_test_spend_bundle(coin_1, dic)

        spend_bundle2 = generate_test_spend_bundle(coin_2)

        bundle = SpendBundle.aggregate([spend_bundle1, spend_bundle2])

        tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(bundle)
        await full_node_1.respond_transaction(tx1, peer)

        mempool_bundle = full_node_1.full_node.mempool_manager.get_spendbundle(bundle.name())

        assert mempool_bundle is bundle
    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()
    async def test_mempool_tx_sync(self, three_nodes_two_wallets):
        num_blocks = 5
        full_nodes, wallets = three_nodes_two_wallets

        wallet_0, wallet_server_0 = wallets[0]
        full_node_api_0 = full_nodes[0]
        server_0 = full_node_api_0.server
        full_node_api_1 = full_nodes[1]
        server_1 = full_node_api_1.server
        full_node_api_2 = full_nodes[2]
        server_2 = full_node_api_2.server

        ph = await wallet_0.wallet_state_manager.main_wallet.get_new_puzzlehash(
        )

        # wallet0 <-> sever0 <-> server1

        await wallet_server_0.start_client(
            PeerInfo(self_hostname, uint16(server_0._port)), None)
        await server_0.start_client(
            PeerInfo(self_hostname, uint16(server_1._port)), None)

        for i in range(num_blocks):
            await full_node_api_0.farm_new_block(FarmNewBlockProtocol(ph))

        all_blocks = await full_node_api_0.get_all_full_blocks()

        for block in all_blocks:
            await full_node_api_2.full_node.respond_sub_block(
                full_node_protocol.RespondSubBlock(block))

        funds = sum([
            calculate_pool_reward(uint32(i)) +
            calculate_base_farmer_reward(uint32(i))
            for i in range(1, num_blocks)
        ])
        await time_out_assert(
            10,
            wallet_0.wallet_state_manager.main_wallet.get_confirmed_balance,
            funds)

        tx = await wallet_0.wallet_state_manager.main_wallet.generate_signed_transaction(
            10, token_bytes(), 0)
        await wallet_0.wallet_state_manager.main_wallet.push_transaction(tx)

        await time_out_assert(
            10,
            full_node_api_0.full_node.mempool_manager.get_spendbundle,
            tx.spend_bundle,
            tx.name,
        )
        await time_out_assert(
            10,
            full_node_api_1.full_node.mempool_manager.get_spendbundle,
            tx.spend_bundle,
            tx.name,
        )
        await time_out_assert(
            10,
            full_node_api_2.full_node.mempool_manager.get_spendbundle,
            None,
            tx.name,
        )

        # make a final connection.
        # wallet0 <-> sever0 <-> server1 <-> server2

        await server_1.start_client(
            PeerInfo(self_hostname, uint16(server_2._port)), None)

        await time_out_assert(
            10,
            full_node_api_0.full_node.mempool_manager.get_spendbundle,
            tx.spend_bundle,
            tx.name,
        )
        await time_out_assert(
            10,
            full_node_api_1.full_node.mempool_manager.get_spendbundle,
            tx.spend_bundle,
            tx.name,
        )
        await time_out_assert(
            10,
            full_node_api_2.full_node.mempool_manager.get_spendbundle,
            tx.spend_bundle,
            tx.name,
        )
    async def test_basic_blockchain_tx(self, two_nodes):
        num_blocks = 10
        wallet_a = WALLET_A
        coinbase_puzzlehash = WALLET_A_PUZZLE_HASHES[0]
        receiver_puzzlehash = BURN_PUZZLE_HASH

        blocks = bt.get_consecutive_blocks(
            num_blocks,
            farmer_reward_puzzle_hash=coinbase_puzzlehash,
            guarantee_block=True)
        full_node_api_1, full_node_api_2, server_1, server_2 = two_nodes
        peer = await connect_and_get_peer(server_1, server_2)
        full_node_1 = full_node_api_1.full_node

        for block in blocks:
            await full_node_api_1.full_node.respond_sub_block(
                full_node_protocol.RespondSubBlock(block), None)

        spend_block = blocks[2]
        spend_coin = None
        for coin in list(spend_block.get_included_reward_coins()):
            if coin.puzzle_hash == coinbase_puzzlehash:
                spend_coin = coin

        spend_bundle = wallet_a.generate_signed_transaction(
            1000, receiver_puzzlehash, spend_coin)

        assert spend_bundle is not None
        tx: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
            spend_bundle)
        await full_node_api_1.respond_transaction(tx, peer)

        sb = full_node_1.mempool_manager.get_spendbundle(spend_bundle.name())
        assert sb is spend_bundle

        last_block = blocks[-1]
        next_spendbundle = await full_node_1.mempool_manager.create_bundle_from_mempool(
            last_block.header_hash)
        assert next_spendbundle is not None

        new_blocks = bt.get_consecutive_blocks(
            1,
            block_list_input=blocks,
            farmer_reward_puzzle_hash=coinbase_puzzlehash,
            transaction_data=next_spendbundle,
            guarantee_block=True,
        )

        next_block = new_blocks[-1]
        await full_node_1.respond_sub_block(
            full_node_protocol.RespondSubBlock(next_block))

        assert next_block.header_hash == full_node_1.blockchain.get_peak(
        ).header_hash

        added_coins = next_spendbundle.additions()

        # Two coins are added, main spend and change
        assert len(added_coins) == 2
        for coin in added_coins:
            unspent = await full_node_1.coin_store.get_coin_record(coin.name())
            assert unspent is not None
            assert not unspent.spent
            assert not unspent.coinbase
    async def test_assert_my_coin_id(self, two_nodes):
        num_blocks = 10
        wallet_a = WALLET_A
        coinbase_puzzlehash = WALLET_A_PUZZLE_HASHES[0]
        receiver_puzzlehash = BURN_PUZZLE_HASH

        # Farm blocks
        blocks = bt.get_consecutive_blocks(
            num_blocks,
            farmer_reward_puzzle_hash=coinbase_puzzlehash,
            guarantee_block=True)
        full_node_api_1, full_node_api_2, server_1, server_2 = two_nodes
        full_node_1 = full_node_api_1.full_node

        for block in blocks:
            await full_node_api_1.full_node.respond_sub_block(
                full_node_protocol.RespondSubBlock(block))

        # Coinbase that gets spent

        spend_block = blocks[2]
        bad_block = blocks[3]
        spend_coin = None
        bad_spend_coin = None
        for coin in list(spend_block.get_included_reward_coins()):
            if coin.puzzle_hash == coinbase_puzzlehash:
                spend_coin = coin
        for coin in list(bad_block.get_included_reward_coins()):
            if coin.puzzle_hash == coinbase_puzzlehash:
                bad_spend_coin = coin
        valid_cvp = ConditionVarPair(ConditionOpcode.ASSERT_MY_COIN_ID,
                                     [spend_coin.name()])
        valid_dic = {valid_cvp.opcode: [valid_cvp]}
        bad_cvp = ConditionVarPair(ConditionOpcode.ASSERT_MY_COIN_ID,
                                   [bad_spend_coin.name()])

        bad_dic = {bad_cvp.opcode: [bad_cvp]}
        bad_spend_bundle = wallet_a.generate_signed_transaction(
            1000, receiver_puzzlehash, spend_coin, bad_dic)

        valid_spend_bundle = wallet_a.generate_signed_transaction(
            1000, receiver_puzzlehash, spend_coin, valid_dic)

        assert bad_spend_bundle is not None
        assert valid_spend_bundle is not None

        # Invalid block bundle
        # Create another block that includes our transaction
        invalid_new_blocks = bt.get_consecutive_blocks(
            1,
            blocks,
            farmer_reward_puzzle_hash=coinbase_puzzlehash,
            transaction_data=bad_spend_bundle,
            guarantee_block=True,
        )

        # Try to validate that block
        res, err, _ = await full_node_1.blockchain.receive_block(
            invalid_new_blocks[-1])
        assert res == ReceiveBlockResult.INVALID_BLOCK
        assert err == Err.ASSERT_MY_COIN_ID_FAILED

        # Valid block bundle
        # Create another block that includes our transaction
        new_blocks = bt.get_consecutive_blocks(
            1,
            blocks,
            farmer_reward_puzzle_hash=coinbase_puzzlehash,
            transaction_data=valid_spend_bundle,
            guarantee_block=True,
        )
        res, err, _ = await full_node_1.blockchain.receive_block(new_blocks[-1]
                                                                 )
        assert res == ReceiveBlockResult.NEW_PEAK
        assert err is None
    async def test_assert_fee_condition(self, two_nodes):

        num_blocks = 10
        wallet_a = WALLET_A
        coinbase_puzzlehash = WALLET_A_PUZZLE_HASHES[0]
        receiver_puzzlehash = BURN_PUZZLE_HASH

        # Farm blocks
        blocks = bt.get_consecutive_blocks(
            num_blocks,
            farmer_reward_puzzle_hash=coinbase_puzzlehash,
            guarantee_block=True)
        full_node_api_1, full_node_api_2, server_1, server_2 = two_nodes
        full_node_1 = full_node_api_1.full_node

        for block in blocks:
            await full_node_api_1.full_node.respond_sub_block(
                full_node_protocol.RespondSubBlock(block))

        # Coinbase that gets spent
        block1 = blocks[2]
        spend_coin_block_1 = None
        for coin in list(block1.get_included_reward_coins()):
            if coin.puzzle_hash == coinbase_puzzlehash:
                spend_coin_block_1 = coin

        # This condition requires fee to be 10 mojo
        cvp_fee = ConditionVarPair(ConditionOpcode.ASSERT_FEE,
                                   [int_to_bytes(10)])
        # This spend bundle has 9 mojo as fee
        block1_dic_bad = {cvp_fee.opcode: [cvp_fee]}
        block1_dic_good = {cvp_fee.opcode: [cvp_fee]}
        block1_spend_bundle_bad = wallet_a.generate_signed_transaction(
            1000,
            receiver_puzzlehash,
            spend_coin_block_1,
            block1_dic_bad,
            fee=9)
        block1_spend_bundle_good = wallet_a.generate_signed_transaction(
            1000,
            receiver_puzzlehash,
            spend_coin_block_1,
            block1_dic_good,
            fee=10)
        log.warning(block1_spend_bundle_good.additions())
        log.warning(f"Spend bundle fees: {block1_spend_bundle_good.fees()}")
        invalid_new_blocks = bt.get_consecutive_blocks(
            1,
            blocks,
            farmer_reward_puzzle_hash=coinbase_puzzlehash,
            transaction_data=block1_spend_bundle_bad,
            guarantee_block=True,
        )

        res, err, _ = await full_node_1.blockchain.receive_block(
            invalid_new_blocks[-1])
        assert res == ReceiveBlockResult.INVALID_BLOCK
        assert err == Err.ASSERT_FEE_CONDITION_FAILED

        valid_new_blocks = bt.get_consecutive_blocks(
            1,
            blocks,
            farmer_reward_puzzle_hash=coinbase_puzzlehash,
            transaction_data=block1_spend_bundle_good,
            guarantee_block=True,
        )
        res, err, _ = await full_node_1.blockchain.receive_block(
            valid_new_blocks[-1])
        assert err is None
        assert res == ReceiveBlockResult.NEW_PEAK
    async def test_assert_time_exceeds(self, two_nodes):

        num_blocks = 10
        wallet_a = WALLET_A
        coinbase_puzzlehash = WALLET_A_PUZZLE_HASHES[0]
        receiver_puzzlehash = BURN_PUZZLE_HASH

        # Farm blocks
        blocks = bt.get_consecutive_blocks(
            num_blocks,
            farmer_reward_puzzle_hash=coinbase_puzzlehash,
            guarantee_block=True)
        full_node_api_1, full_node_api_2, server_1, server_2 = two_nodes
        full_node_1 = full_node_api_1.full_node

        for block in blocks:
            await full_node_api_1.full_node.respond_sub_block(
                full_node_protocol.RespondSubBlock(block))

        # Coinbase that gets spent
        block1 = blocks[2]
        spend_coin_block_1 = None
        for coin in list(block1.get_included_reward_coins()):
            if coin.puzzle_hash == coinbase_puzzlehash:
                spend_coin_block_1 = coin

        # This condition requires block1 coinbase to be spent after 30 seconds from now
        current_time_plus3 = uint64(blocks[-1].foliage_block.timestamp + 30)
        block1_cvp = ConditionVarPair(ConditionOpcode.ASSERT_TIME_EXCEEDS,
                                      [int_to_bytes(current_time_plus3)])
        block1_dic = {block1_cvp.opcode: [block1_cvp]}
        block1_spend_bundle = wallet_a.generate_signed_transaction(
            1000, receiver_puzzlehash, spend_coin_block_1, block1_dic)

        # program that will be sent to early
        assert block1_spend_bundle is not None
        invalid_new_blocks = bt.get_consecutive_blocks(
            1,
            blocks,
            farmer_reward_puzzle_hash=coinbase_puzzlehash,
            transaction_data=block1_spend_bundle,
            time_per_sub_block=20,
            guarantee_block=True,
        )

        # Try to validate that block before 3 sec
        res, err, _ = await full_node_1.blockchain.receive_block(
            invalid_new_blocks[-1])
        assert res == ReceiveBlockResult.INVALID_BLOCK
        assert err == Err.ASSERT_TIME_EXCEEDS_FAILED

        valid_new_blocks = bt.get_consecutive_blocks(
            1,
            blocks,
            farmer_reward_puzzle_hash=coinbase_puzzlehash,
            transaction_data=block1_spend_bundle,
            guarantee_block=True,
            time_per_sub_block=31,
        )
        res, err, _ = await full_node_1.blockchain.receive_block(
            valid_new_blocks[-1])
        assert err is None
        assert res == ReceiveBlockResult.NEW_PEAK
    async def test_assert_block_age_exceeds(self, two_nodes):
        num_blocks = 11
        wallet_a = WALLET_A
        coinbase_puzzlehash = WALLET_A_PUZZLE_HASHES[0]
        receiver_puzzlehash = BURN_PUZZLE_HASH

        # Farm blocks
        blocks = bt.get_consecutive_blocks(
            num_blocks,
            farmer_reward_puzzle_hash=coinbase_puzzlehash,
            guarantee_block=True)
        full_node_api_1, full_node_api_2, server_1, server_2 = two_nodes
        full_node_1 = full_node_api_1.full_node

        for block in blocks:
            await full_node_api_1.full_node.respond_sub_block(
                full_node_protocol.RespondSubBlock(block))

        # Coinbase that gets spent
        block1 = blocks[2]
        spend_coin_block_1 = None
        for coin in list(block1.get_included_reward_coins()):
            if coin.puzzle_hash == coinbase_puzzlehash:
                spend_coin_block_1 = coin

        # This condition requires block1 coinbase to be spent after index 11
        # This condition requires block1 coinbase to be spent more than 10 block after it was farmed
        # block index has to be greater than (2 + 9 = 11)
        block1_cvp = ConditionVarPair(ConditionOpcode.ASSERT_BLOCK_AGE_EXCEEDS,
                                      [int_to_bytes(9)])
        block1_dic = {block1_cvp.opcode: [block1_cvp]}
        block1_spend_bundle = wallet_a.generate_signed_transaction(
            1000, receiver_puzzlehash, spend_coin_block_1, block1_dic)

        # program that will be sent too early
        assert block1_spend_bundle is not None
        invalid_new_blocks = bt.get_consecutive_blocks(
            1,
            blocks,
            farmer_reward_puzzle_hash=coinbase_puzzlehash,
            transaction_data=block1_spend_bundle,
            guarantee_block=True,
        )

        # Try to validate that block at index 11
        res, err, _ = await full_node_1.blockchain.receive_block(
            invalid_new_blocks[-1])
        assert res == ReceiveBlockResult.INVALID_BLOCK
        assert err == Err.ASSERT_BLOCK_AGE_EXCEEDS_FAILED

        new_blocks = bt.get_consecutive_blocks(
            1,
            blocks,
            farmer_reward_puzzle_hash=coinbase_puzzlehash,
            guarantee_block=True,
        )
        res, _, _ = await full_node_1.blockchain.receive_block(new_blocks[-1])
        assert res == ReceiveBlockResult.NEW_PEAK

        # At index 12, it can be spent
        new_blocks = bt.get_consecutive_blocks(
            1,
            new_blocks,
            farmer_reward_puzzle_hash=coinbase_puzzlehash,
            transaction_data=block1_spend_bundle,
            guarantee_block=True,
        )
        res, err, _ = await full_node_1.blockchain.receive_block(new_blocks[-1]
                                                                 )
        assert err is None
        assert res == ReceiveBlockResult.NEW_PEAK
    async def test_assert_announcement_consumed(self, two_nodes):

        num_blocks = 10
        wallet_a = WALLET_A
        coinbase_puzzlehash = WALLET_A_PUZZLE_HASHES[0]
        receiver_puzzlehash = BURN_PUZZLE_HASH

        # Farm blocks
        blocks = bt.get_consecutive_blocks(
            num_blocks,
            farmer_reward_puzzle_hash=coinbase_puzzlehash,
            guarantee_block=True)
        full_node_api_1, full_node_api_2, server_1, server_2 = two_nodes
        full_node_1 = full_node_api_1.full_node

        for block in blocks:
            await full_node_api_1.full_node.respond_sub_block(
                full_node_protocol.RespondSubBlock(block))

        # Coinbase that gets spent
        block1 = blocks[2]
        block2 = blocks[3]

        spend_coin_block_1 = None
        spend_coin_block_2 = None
        for coin in list(block1.get_included_reward_coins()):
            if coin.puzzle_hash == coinbase_puzzlehash:
                spend_coin_block_1 = coin
        for coin in list(block2.get_included_reward_coins()):
            if coin.puzzle_hash == coinbase_puzzlehash:
                spend_coin_block_2 = coin

        # This condition requires block2 coinbase to be spent
        block1_cvp = ConditionVarPair(
            ConditionOpcode.ASSERT_ANNOUNCEMENT,
            [
                Announcement(spend_coin_block_2.name(), bytes("test",
                                                              "utf-8")).name()
            ],
        )
        block1_dic = {block1_cvp.opcode: [block1_cvp]}
        block1_spend_bundle = wallet_a.generate_signed_transaction(
            1000, receiver_puzzlehash, spend_coin_block_1, block1_dic)

        # This condition requires block1 coinbase to be spent
        block2_cvp = ConditionVarPair(
            ConditionOpcode.CREATE_ANNOUNCEMENT,
            [bytes("test", "utf-8")],
        )
        block2_dic = {block2_cvp.opcode: [block2_cvp]}
        block2_spend_bundle = wallet_a.generate_signed_transaction(
            1000, receiver_puzzlehash, spend_coin_block_2, block2_dic)

        # Invalid block bundle
        assert block1_spend_bundle is not None
        # Create another block that includes our transaction
        invalid_new_blocks = bt.get_consecutive_blocks(
            1,
            blocks,
            farmer_reward_puzzle_hash=coinbase_puzzlehash,
            transaction_data=block1_spend_bundle,
            guarantee_block=True,
        )

        # Try to validate that block
        res, err, _ = await full_node_1.blockchain.receive_block(
            invalid_new_blocks[-1])
        assert res == ReceiveBlockResult.INVALID_BLOCK
        assert err == Err.ASSERT_ANNOUNCE_CONSUMED_FAILED

        # bundle_together contains both transactions
        bundle_together = SpendBundle.aggregate(
            [block1_spend_bundle, block2_spend_bundle])

        # Create another block that includes our transaction
        new_blocks = bt.get_consecutive_blocks(
            1,
            blocks,
            farmer_reward_puzzle_hash=coinbase_puzzlehash,
            transaction_data=bundle_together,
            guarantee_block=True,
        )

        # Try to validate newly created block
        res, err, _ = await full_node_1.blockchain.receive_block(new_blocks[-1]
                                                                 )
        assert res == ReceiveBlockResult.NEW_PEAK
        assert err is None