Esempio n. 1
0
    async def test_validate_blockchain_spend_reorg_cb_coin(self, two_nodes):
        num_blocks = 10
        wallet_a = WalletTool()
        coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
        receiver_1_puzzlehash = wallet_a.get_new_puzzlehash()

        blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10,
                                           b"", coinbase_puzzlehash)
        full_node_1, full_node_2, server_1, server_2 = two_nodes

        for block in blocks:
            async for _ in full_node_1.respond_block(
                    full_node_protocol.RespondBlock(block)):
                pass

        # Spends a coinbase created in reorg
        new_blocks = bt.get_consecutive_blocks(test_constants, 1, blocks[:6],
                                               10, b"reorg cb coin",
                                               coinbase_puzzlehash)
        [
            _ async for _ in full_node_1.respond_block(
                full_node_protocol.RespondBlock(new_blocks[-1]))
        ]
        assert new_blocks[-1].header_hash in full_node_1.blockchain.headers

        spent_block = new_blocks[-1]
        spend_bundle = wallet_a.generate_signed_transaction(
            1000, receiver_1_puzzlehash, spent_block.get_coinbase())
        spend_bundle_2 = wallet_a.generate_signed_transaction(
            1000, receiver_1_puzzlehash, spent_block.get_fees_coin())

        block_spendbundle = SpendBundle.aggregate(
            [spend_bundle, spend_bundle_2])
        program = best_solution_program(block_spendbundle)
        aggsig = block_spendbundle.aggregated_signature

        dic_h = {7: (program, aggsig)}
        new_blocks = bt.get_consecutive_blocks(
            test_constants,
            1,
            new_blocks,
            10,
            b"reorg cb coin",
            coinbase_puzzlehash,
            dic_h,
        )
        error = await full_node_1.blockchain._validate_transactions(
            new_blocks[-1], new_blocks[-1].get_fees_coin().amount)
        assert error is None
        [
            _ async for _ in full_node_1.respond_block(
                full_node_protocol.RespondBlock(new_blocks[-1]))
        ]
        assert new_blocks[-1].header_hash in full_node_1.blockchain.headers

        coins_created = []
        for coin in new_blocks[-1].additions():
            if coin.puzzle_hash == receiver_1_puzzlehash:
                coins_created.append(coin)
        assert len(coins_created) == 2
    async def test_validate_blockchain_spend_reorg_since_genesis(self, two_nodes):
        num_blocks = 10
        wallet_a = WalletTool()
        coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
        receiver_1_puzzlehash = wallet_a.get_new_puzzlehash()

        blocks = bt.get_consecutive_blocks(
            test_constants, num_blocks, [], 10, b"", coinbase_puzzlehash
        )
        full_node_1, full_node_2, server_1, server_2 = two_nodes

        for block in blocks:
            async for _ in full_node_1.respond_block(
                full_node_protocol.RespondBlock(block)
            ):
                pass

        spent_block = blocks[1]

        spend_bundle = wallet_a.generate_signed_transaction(
            1000, receiver_1_puzzlehash, spent_block.get_coinbase()
        )
        block_spendbundle = SpendBundle.aggregate([spend_bundle])
        program = best_solution_program(block_spendbundle)
        aggsig = block_spendbundle.aggregated_signature

        dic_h = {11: (program, aggsig)}
        new_blocks = bt.get_consecutive_blocks(
            test_constants, 1, blocks, 10, b"", coinbase_puzzlehash, dic_h
        )
        [
            _
            async for _ in full_node_1.respond_block(
                full_node_protocol.RespondBlock(new_blocks[-1])
            )
        ]

        # Spends a coin in a genesis reorg, that was already spent
        dic_h = {5: (program, aggsig)}
        new_blocks = bt.get_consecutive_blocks(
            test_constants,
            12,
            [],
            10,
            b"reorg since genesis",
            coinbase_puzzlehash,
            dic_h,
        )
        for block in new_blocks:
            [
                _
                async for _ in full_node_1.respond_block(
                    full_node_protocol.RespondBlock(block)
                )
            ]
        assert new_blocks[-1].header_hash in full_node_1.blockchain.headers
    async def test_validate_blockchain_spend_reorg_cb_coin_freeze(
        self, two_nodes_standard_freeze
    ):
        num_blocks = 10
        wallet_a = WalletTool()
        coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
        receiver_1_puzzlehash = wallet_a.get_new_puzzlehash()

        blocks = bt.get_consecutive_blocks(
            test_constants, num_blocks, [], 10, b"", coinbase_puzzlehash
        )
        full_node_1, full_node_2, server_1, server_2 = two_nodes_standard_freeze

        for block in blocks:
            async for _ in full_node_1.respond_block(
                full_node_protocol.RespondBlock(block)
            ):
                pass

        # Spends a coinbase created in reorg
        new_blocks = bt.get_consecutive_blocks(
            test_constants, 1, blocks[:6], 10, b"reorg cb coin", coinbase_puzzlehash
        )
        [
            _
            async for _ in full_node_1.respond_block(
                full_node_protocol.RespondBlock(new_blocks[-1])
            )
        ]
        assert new_blocks[-1].header_hash in full_node_1.blockchain.headers

        spent_block = new_blocks[-1]
        spend_bundle = wallet_a.generate_signed_transaction(
            1000, receiver_1_puzzlehash, spent_block.get_coinbase()
        )
        block_spendbundle = SpendBundle.aggregate([spend_bundle])
        program = best_solution_program(block_spendbundle)
        aggsig = block_spendbundle.aggregated_signature

        dic_h = {7: (program, aggsig)}
        new_blocks = bt.get_consecutive_blocks(
            test_constants,
            1,
            new_blocks,
            10,
            b"reorg cb coin",
            coinbase_puzzlehash,
            dic_h,
        )
        error = await full_node_1.blockchain._validate_transactions(
            new_blocks[-1], new_blocks[-1].get_coinbase().amount
        )
        assert error is Err.COINBASE_NOT_YET_SPENDABLE
Esempio n. 4
0
    async def test_basics(self):
        wallet_tool = bt.get_pool_wallet_tool()
        receiver = WalletTool()

        num_blocks = 2
        blocks = bt.get_consecutive_blocks(
            test_constants,
            num_blocks,
            [],
            10,
        )

        spend_bundle = wallet_tool.generate_signed_transaction(
            blocks[1].get_coinbase().amount,
            receiver.get_new_puzzlehash(),
            blocks[1].get_coinbase(),
        )
        assert spend_bundle is not None
        program = best_solution_program(spend_bundle)

        ratio = test_constants.CLVM_COST_RATIO_CONSTANT

        error, npc_list, clvm_cost = calculate_cost_of_program(program, ratio)

        error, npc_list, cost = get_name_puzzle_conditions(program)

        # Create condition + agg_sig_condition + length + cpu_cost
        assert (clvm_cost == 200 * ratio + 20 * ratio +
                len(bytes(program)) * ratio + cost)
Esempio n. 5
0
    async def test_correct_my_id(self, two_nodes):
        num_blocks = 2
        wallet_a = bt.get_pool_wallet_tool()
        wallet_receiver = WalletTool()
        receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()

        blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10,
                                           b"")
        full_node_1, full_node_2, server_1, server_2 = two_nodes

        block = blocks[1]

        for b in blocks:
            async for _ in full_node_1.respond_block(
                    full_node_protocol.RespondBlock(b)):
                pass

        cvp = ConditionVarPair(ConditionOpcode.ASSERT_MY_COIN_ID,
                               block.get_coinbase().name(), None)
        dic = {cvp.opcode: [cvp]}

        spend_bundle1 = wallet_a.generate_signed_transaction(
            1000, receiver_puzzlehash, block.get_coinbase(), dic)

        assert spend_bundle1 is not None
        tx1: full_node_protocol.RespondTransaction = (
            full_node_protocol.RespondTransaction(spend_bundle1))
        async for _ in full_node_1.respond_transaction(tx1):
            outbound: OutboundMessage = _
            # Maybe transaction means that it's accepted in mempool
            assert outbound.message.function == "new_transaction"

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

        assert sb1 is spend_bundle1
Esempio n. 6
0
    async def test_basic_mempool(self, two_nodes):
        num_blocks = 2
        wallet_a = bt.get_pool_wallet_tool()
        wallet_receiver = WalletTool()
        receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()

        blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10,
                                           b"")
        full_node_1, full_node_2, server_1, server_2 = two_nodes

        block = blocks[1]
        async for _ in full_node_1.respond_block(
                full_node_protocol.RespondBlock(block)):
            pass

        spend_bundle = wallet_a.generate_signed_transaction(
            1000, receiver_puzzlehash, block.get_coinbase())
        assert spend_bundle is not None
        tx: full_node_protocol.RespondTransaction = (
            full_node_protocol.RespondTransaction(spend_bundle))
        async for _ in full_node_1.respond_transaction(tx):
            outbound: OutboundMessage = _
            # Maybe transaction means that it's accepted in mempool
            assert outbound.message.function == "new_transaction"

        sb = full_node_1.mempool_manager.get_spendbundle(spend_bundle.name())
        assert sb is spend_bundle
    async def test_validate_blockchain_with_double_spend(self, two_nodes):

        num_blocks = 5
        wallet_a = WalletTool()
        coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
        wallet_receiver = WalletTool()
        receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()

        blocks = bt.get_consecutive_blocks(
            test_constants, num_blocks, [], 10, b"", coinbase_puzzlehash
        )
        full_node_1, full_node_2, server_1, server_2 = two_nodes

        for block in blocks:
            async for _ in full_node_1.respond_block(
                full_node_protocol.RespondBlock(block)
            ):
                pass

        spent_block = blocks[1]

        spend_bundle = wallet_a.generate_signed_transaction(
            1000, receiver_puzzlehash, spent_block.get_coinbase()
        )
        spend_bundle_double = wallet_a.generate_signed_transaction(
            1001, receiver_puzzlehash, spent_block.get_coinbase()
        )

        block_spendbundle = SpendBundle.aggregate([spend_bundle, spend_bundle_double])
        program = best_solution_program(block_spendbundle)
        aggsig = block_spendbundle.aggregated_signature

        dic_h = {(num_blocks + 1): (program, aggsig)}
        new_blocks = bt.get_consecutive_blocks(
            test_constants, 1, blocks, 10, b"", coinbase_puzzlehash, dic_h
        )

        next_block = new_blocks[num_blocks + 1]
        error = await full_node_1.blockchain._validate_transactions(
            next_block, next_block.get_fees_coin().amount
        )

        assert error is Err.DOUBLE_SPEND
Esempio n. 8
0
    async def test_double_spend_same_bundle(self, two_nodes):
        num_blocks = 2
        wallet_a = bt.get_pool_wallet_tool()
        wallet_receiver = WalletTool()
        receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()

        blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10,
                                           b"")
        full_node_1, full_node_2, server_1, server_2 = two_nodes

        block = blocks[1]
        async for _ in full_node_1.respond_block(
                full_node_protocol.RespondBlock(block)):
            pass

        spend_bundle1 = wallet_a.generate_signed_transaction(
            1000, receiver_puzzlehash, block.get_coinbase())

        assert spend_bundle1 is not None

        other_receiver = WalletTool()
        spend_bundle2 = wallet_a.generate_signed_transaction(
            1000, other_receiver.get_new_puzzlehash(), block.get_coinbase())

        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))
        messages = []
        async for outbound in full_node_1.respond_transaction(tx):
            messages.append(outbound)

        sb = full_node_1.mempool_manager.get_spendbundle(
            spend_bundle_combined.name())
        assert sb is None
Esempio n. 9
0
    async def test_assert_time_exceeds_both_cases(self, two_nodes):
        num_blocks = 2
        wallet_a = bt.get_pool_wallet_tool()
        wallet_receiver = WalletTool()
        receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()

        blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10,
                                           b"")
        full_node_1, full_node_2, server_1, server_2 = two_nodes

        block = blocks[1]

        for b in blocks:
            async for _ in full_node_1.respond_block(
                    full_node_protocol.RespondBlock(b)):
                pass

        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"),
            None,
        )
        dic = {cvp.opcode: [cvp]}

        spend_bundle1 = wallet_a.generate_signed_transaction(
            1000, receiver_puzzlehash, block.get_coinbase(), dic)

        assert spend_bundle1 is not None
        tx1: full_node_protocol.RespondTransaction = (
            full_node_protocol.RespondTransaction(spend_bundle1))
        async for _ in full_node_1.respond_transaction(tx1):
            outbound: OutboundMessage = _
            assert outbound.message.function != "new_transaction"

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

        tx2: full_node_protocol.RespondTransaction = (
            full_node_protocol.RespondTransaction(spend_bundle1))
        async for _ in full_node_1.respond_transaction(tx2):
            outbound_2: OutboundMessage = _
            # Maybe transaction means that it's accepted in mempool
            assert outbound_2.message.function == "new_transaction"

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

        assert sb1 is spend_bundle1
Esempio n. 10
0
    async def test_assert_fee_condition_wrong_fee(self, two_nodes):
        num_blocks = 2
        wallet_a = bt.get_pool_wallet_tool()
        wallet_receiver = WalletTool()
        receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()

        blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10,
                                           b"")
        full_node_1, full_node_2, server_1, server_2 = two_nodes

        block = blocks[1]

        for b in blocks:
            async for _ in full_node_1.respond_block(
                    full_node_protocol.RespondBlock(b)):
                pass

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

        spend_bundle1 = wallet_a.generate_signed_transaction(
            1000, receiver_puzzlehash, block.get_coinbase(), dic, 9)

        assert spend_bundle1 is not None

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

        outbound_messages: List[OutboundMessage] = []
        async for outbound in full_node_1.respond_transaction(tx1):
            outbound_messages.append(outbound)

        new_transaction = False
        for msg in outbound_messages:
            if msg.message.function == "new_transaction":
                new_transaction = True

        assert new_transaction is False

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

        assert mempool_bundle is None
Esempio n. 11
0
    async def test_agg_sig_condition(self, two_nodes):
        num_blocks = 2
        wallet_a = bt.get_pool_wallet_tool()
        wallet_receiver = WalletTool()
        receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()

        blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10,
                                           b"")
        full_node_1, full_node_2, server_1, server_2 = two_nodes

        block = blocks[1]
        async for _ in full_node_1.respond_block(
                full_node_protocol.RespondBlock(block)):
            pass

        unsigned: List[Tuple[
            Program, CoinSolution]] = wallet_a.generate_unsigned_transaction(
                1000, receiver_puzzlehash, block.get_coinbase(), {}, 0)
        assert len(unsigned) == 1

        puzzle, solution = unsigned[0]
        code_ = [puzzle, solution.solution]
        sexp = Program.to(code_)

        err, con, cost = conditions_for_solution(sexp)
        assert con is not None

        conditions_dict = conditions_by_opcode(con)
        pkm_pairs = pkm_pairs_for_conditions_dict(conditions_dict,
                                                  solution.coin.name())
        assert len(pkm_pairs) == 1

        assert pkm_pairs[0][1] == solution.solution.first().get_tree_hash()

        spend_bundle = wallet_a.sign_transaction(unsigned)
        assert spend_bundle is not None

        tx: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
            spend_bundle)
        async for _ in full_node_1.respond_transaction(tx):
            outbound: OutboundMessage = _
            # Maybe transaction means that it's accepted in mempool
            assert outbound.message.function == "new_transaction"

        sb = full_node_1.mempool_manager.get_spendbundle(spend_bundle.name())
        assert sb is spend_bundle
Esempio n. 12
0
    async def test_correct_coin_consumed(self, two_nodes):
        num_blocks = 2
        wallet_a = bt.get_pool_wallet_tool()
        wallet_receiver = WalletTool()
        receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()

        blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10,
                                           b"")
        full_node_1, full_node_2, server_1, server_2 = two_nodes

        block = blocks[1]
        block2 = blocks[2]

        for b in blocks:
            async for _ in full_node_1.respond_block(
                    full_node_protocol.RespondBlock(b)):
                pass

        cvp = ConditionVarPair(
            ConditionOpcode.ASSERT_COIN_CONSUMED,
            block2.get_coinbase().name(),
            None,
        )
        dic = {cvp.opcode: [cvp]}

        spend_bundle1 = wallet_a.generate_signed_transaction(
            1000, receiver_puzzlehash, block.get_coinbase(), dic)

        spend_bundle2 = wallet_a.generate_signed_transaction(
            1000, receiver_puzzlehash, block2.get_coinbase())

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

        tx1: full_node_protocol.RespondTransaction = (
            full_node_protocol.RespondTransaction(bundle))
        async for _ in full_node_1.respond_transaction(tx1):
            outbound: OutboundMessage = _
            # Maybe transaction means that it's accepted in mempool
            assert outbound.message.function == "new_transaction"

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

        assert mempool_bundle is bundle
Esempio n. 13
0
    async def test_double_spend_with_higher_fee(self, two_nodes):
        num_blocks = 2
        wallet_a = bt.get_pool_wallet_tool()
        wallet_receiver = WalletTool()
        receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()

        blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10,
                                           b"")
        full_node_1, full_node_2, server_1, server_2 = two_nodes

        block = blocks[1]
        async for _ in full_node_1.respond_block(
                full_node_protocol.RespondBlock(block)):
            pass

        spend_bundle1 = wallet_a.generate_signed_transaction(
            1000, receiver_puzzlehash, block.get_coinbase())
        assert spend_bundle1 is not None
        tx1: full_node_protocol.RespondTransaction = (
            full_node_protocol.RespondTransaction(spend_bundle1))
        async for _ in full_node_1.respond_transaction(tx1):
            outbound: OutboundMessage = _
            # Maybe transaction means that it's accepted in mempool
            assert outbound.message.function == "new_transaction"

        spend_bundle2 = wallet_a.generate_signed_transaction(
            1000, receiver_puzzlehash, block.get_coinbase(), fee=1)

        assert spend_bundle2 is not None
        tx2: full_node_protocol.RespondTransaction = (
            full_node_protocol.RespondTransaction(spend_bundle2))
        async for _ in full_node_1.respond_transaction(tx2):
            pass

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

        assert sb1 is None
        assert sb2 == spend_bundle2
Esempio n. 14
0
    async def test_invalid_block_index(self, two_nodes):
        num_blocks = 2
        wallet_a = bt.get_pool_wallet_tool()
        wallet_receiver = WalletTool()
        receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()

        blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10,
                                           b"")
        full_node_1, full_node_2, server_1, server_2 = two_nodes

        block = blocks[1]
        async for _ in full_node_1.respond_block(
                full_node_protocol.RespondBlock(block)):
            pass

        cvp = ConditionVarPair(
            ConditionOpcode.ASSERT_BLOCK_INDEX_EXCEEDS,
            uint64(2).to_bytes(4, "big"),
            None,
        )
        dic = {ConditionOpcode.ASSERT_BLOCK_INDEX_EXCEEDS: [cvp]}

        spend_bundle1 = wallet_a.generate_signed_transaction(
            1000, receiver_puzzlehash, block.get_coinbase(), dic)

        assert spend_bundle1 is not None
        tx1: full_node_protocol.RespondTransaction = (
            full_node_protocol.RespondTransaction(spend_bundle1))
        async for _ in full_node_1.respond_transaction(tx1):
            outbound: OutboundMessage = _
            # Maybe transaction means that it's accepted in mempool
            assert outbound.message.function != "new_transaction"

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

        assert sb1 is None
Esempio n. 15
0
    async def test_assert_my_coin_id(self, two_nodes):
        num_blocks = 10
        wallet_a = WalletTool()
        coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
        wallet_receiver = WalletTool()
        receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()

        # Farm blocks
        blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10,
                                           b"", coinbase_puzzlehash)
        full_node_1, full_node_2, server_1, server_2 = two_nodes

        for block in blocks:
            async for _ in full_node_1.respond_block(
                    full_node_protocol.RespondBlock(block)):
                pass

        # Coinbase that gets spent
        spent_block = blocks[1]
        bad_block = blocks[2]
        valid_cvp = ConditionVarPair(
            ConditionOpcode.ASSERT_MY_COIN_ID,
            spent_block.get_coinbase().name(),
            None,
        )
        valid_dic = {valid_cvp.opcode: [valid_cvp]}
        bad_cvp = ConditionVarPair(
            ConditionOpcode.ASSERT_MY_COIN_ID,
            bad_block.get_coinbase().name(),
            None,
        )

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

        valid_spend_bundle = wallet_a.generate_signed_transaction(
            1000, receiver_puzzlehash, spent_block.get_coinbase(), valid_dic)

        # Invalid block bundle
        assert bad_spend_bundle is not None
        invalid_program = best_solution_program(bad_spend_bundle)
        aggsig = bad_spend_bundle.aggregated_signature

        # Create another block that includes our transaction
        dic_h = {11: (invalid_program, aggsig)}
        invalid_new_blocks = bt.get_consecutive_blocks(test_constants, 1,
                                                       blocks, 10, b"",
                                                       coinbase_puzzlehash,
                                                       dic_h)

        # Try to validate that block
        next_block = invalid_new_blocks[11]
        error = await full_node_1.blockchain._validate_transactions(
            next_block,
            next_block.get_fees_coin().amount)

        assert error is Err.ASSERT_MY_COIN_ID_FAILED

        # Valid block bundle
        assert valid_spend_bundle is not None
        valid_program = best_solution_program(valid_spend_bundle)
        aggsig = valid_spend_bundle.aggregated_signature

        # Create another block that includes our transaction
        dic_h = {11: (valid_program, aggsig)}
        new_blocks = bt.get_consecutive_blocks(test_constants, 1, blocks[:11],
                                               10, b"1", coinbase_puzzlehash,
                                               dic_h)
        next_block = new_blocks[11]
        error = await full_node_1.blockchain._validate_transactions(
            next_block,
            next_block.get_fees_coin().amount)
        assert error is None
Esempio n. 16
0
    async def test_short_sync_with_transactions_wallet(self, wallet_node):
        full_node_1, wallet_node, server_1, server_2 = wallet_node
        wallet_a = wallet_node.wallet_state_manager.main_wallet
        wallet_a_dummy = WalletTool()
        wallet_b = WalletTool()
        coinbase_puzzlehash = await wallet_a.get_new_puzzlehash()
        coinbase_puzzlehash_rest = wallet_b.get_new_puzzlehash()
        puzzle_hashes = [
            await wallet_a.get_new_puzzlehash() for _ in range(10)
        ]
        puzzle_hashes.append(wallet_b.get_new_puzzlehash())

        blocks = bt.get_consecutive_blocks(test_constants, 3, [], 10, b"",
                                           coinbase_puzzlehash)
        for block in blocks:
            [
                _ async for _ in full_node_1.respond_block(
                    full_node_protocol.RespondBlock(block))
            ]
        await server_2.start_client(
            PeerInfo("localhost", uint16(server_1._port)), None)
        await time_out_assert(60, wallet_height_at_least, True, wallet_node, 1)

        server_2.global_connections.close_all_connections()

        dic_h = {}
        prev_coin = blocks[1].get_coinbase()
        for i in range(11):
            pk, sk = await wallet_a.wallet_state_manager.get_keys(
                prev_coin.puzzle_hash)
            transaction_unsigned = wallet_a_dummy.generate_unsigned_transaction(
                1000, puzzle_hashes[i], prev_coin, {}, 0, secretkey=sk)
            spend_bundle = await wallet_a.sign_transaction(transaction_unsigned
                                                           )
            block_spendbundle = SpendBundle.aggregate([spend_bundle])
            program = best_solution_program(block_spendbundle)
            aggsig = block_spendbundle.aggregated_signature
            prev_coin = Coin(prev_coin.name(), puzzle_hashes[i], uint64(1000))
            dic_h[i + 4] = (program, aggsig)

        blocks = bt.get_consecutive_blocks(test_constants, 13, blocks, 10, b"",
                                           coinbase_puzzlehash_rest, dic_h)
        # Move chain to height 16, with consecutive transactions in blocks 4 to 14
        for block in blocks:
            async for _ in full_node_1.respond_block(
                    full_node_protocol.RespondBlock(block)):
                pass

        # Do a short sync from 0 to 14
        await server_2.start_client(
            PeerInfo("localhost", uint16(server_1._port)), None)
        await time_out_assert(60, wallet_height_at_least, True, wallet_node,
                              14)

        server_2.global_connections.close_all_connections()

        # 2 block rewards and 3 fees
        assert await wallet_a.get_confirmed_balance() == (
            blocks[1].get_coinbase().amount *
            2) + (blocks[1].get_fees_coin().amount * 3)
        # All of our coins are spent and puzzle hashes present
        for puzzle_hash in puzzle_hashes[:-1]:
            records = await wallet_node.wallet_state_manager.wallet_store.get_coin_records_by_puzzle_hash(
                puzzle_hash)
            assert len(records) == 1
            assert records[0].spent and not records[0].coinbase

        # Then do the same but in a reorg chain
        dic_h = {}
        prev_coin = blocks[1].get_coinbase()
        for i in range(11):
            pk, sk = await wallet_a.wallet_state_manager.get_keys(
                prev_coin.puzzle_hash)
            transaction_unsigned = wallet_a_dummy.generate_unsigned_transaction(
                1000, puzzle_hashes[i], prev_coin, {}, 0, secretkey=sk)
            spend_bundle = await wallet_a.sign_transaction(transaction_unsigned
                                                           )
            block_spendbundle = SpendBundle.aggregate([spend_bundle])
            program = best_solution_program(block_spendbundle)
            aggsig = block_spendbundle.aggregated_signature
            prev_coin = Coin(prev_coin.name(), puzzle_hashes[i], uint64(1000))
            dic_h[i + 4] = (program, aggsig)

        blocks = bt.get_consecutive_blocks(
            test_constants,
            31,
            blocks[:4],
            10,
            b"this is a reorg",
            coinbase_puzzlehash_rest,
            dic_h,
        )

        # Move chain to height 34, with consecutive transactions in blocks 4 to 14
        for block in blocks:
            async for _ in full_node_1.respond_block(
                    full_node_protocol.RespondBlock(block)):
                pass

        # Do a sync from 0 to 22
        await server_2.start_client(
            PeerInfo("localhost", uint16(server_1._port)), None)

        await time_out_assert(60, wallet_height_at_least, True, wallet_node,
                              28)
        server_2.global_connections.close_all_connections()

        # 2 block rewards and 3 fees
        assert await wallet_a.get_confirmed_balance() == (
            blocks[1].get_coinbase().amount *
            2) + (blocks[1].get_fees_coin().amount * 3)
        # All of our coins are spent and puzzle hashes present
        for puzzle_hash in puzzle_hashes[:-1]:
            records = await wallet_node.wallet_state_manager.wallet_store.get_coin_records_by_puzzle_hash(
                puzzle_hash)
            assert len(records) == 1
            assert records[0].spent and not records[0].coinbase

        # Test spending the rewards earned in reorg
        new_coinbase_puzzlehash = await wallet_a.get_new_puzzlehash()
        another_puzzlehash = await wallet_a.get_new_puzzlehash()

        dic_h = {}
        pk, sk = await wallet_a.wallet_state_manager.get_keys(
            new_coinbase_puzzlehash)
        coinbase_coin = create_coinbase_coin(uint32(25),
                                             new_coinbase_puzzlehash,
                                             uint64(14000000000000))
        transaction_unsigned = wallet_a_dummy.generate_unsigned_transaction(
            7000000000000,
            another_puzzlehash,
            coinbase_coin, {},
            0,
            secretkey=sk)
        spend_bundle = await wallet_a.sign_transaction(transaction_unsigned)
        block_spendbundle = SpendBundle.aggregate([spend_bundle])
        program = best_solution_program(block_spendbundle)
        aggsig = block_spendbundle.aggregated_signature
        dic_h[26] = (program, aggsig)

        # Farm a block (25) to ourselves
        blocks = bt.get_consecutive_blocks(
            test_constants,
            1,
            blocks[:25],
            10,
            b"this is yet another reorg",
            new_coinbase_puzzlehash,
        )

        # Brings height up to 40, with block 31 having half our reward spent to us
        blocks = bt.get_consecutive_blocks(
            test_constants,
            15,
            blocks,
            10,
            b"this is yet another reorg more blocks",
            coinbase_puzzlehash_rest,
            dic_h,
        )
        for block in blocks:
            async for _ in full_node_1.respond_block(
                    full_node_protocol.RespondBlock(block)):
                pass

        await server_2.start_client(
            PeerInfo("localhost", uint16(server_1._port)), None)
        await time_out_assert(60, wallet_height_at_least, True, wallet_node,
                              38)

        # 2 block rewards and 4 fees, plus 7000000000000 coins
        assert (await wallet_a.get_confirmed_balance() ==
                (blocks[1].get_coinbase().amount * 2) +
                (blocks[1].get_fees_coin().amount * 4) + 7000000000000)
        records = await wallet_node.wallet_state_manager.wallet_store.get_coin_records_by_puzzle_hash(
            new_coinbase_puzzlehash)
        # Fee and coinbase
        assert len(records) == 2
        print(records)
        assert records[0].spent != records[1].spent
        assert records[0].coinbase == records[1].coinbase
        records = await wallet_node.wallet_state_manager.wallet_store.get_coin_records_by_puzzle_hash(
            another_puzzlehash)
        assert len(records) == 1
        assert not records[0].spent
        assert not records[0].coinbase
Esempio n. 17
0
    async def test_assert_fee_condition(self, two_nodes):

        num_blocks = 10
        wallet_a = WalletTool()
        coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
        wallet_receiver = WalletTool()
        receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()

        # Farm blocks
        blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10,
                                           b"", coinbase_puzzlehash)
        full_node_1, full_node_2, server_1, server_2 = two_nodes

        for block in blocks:
            async for _ in full_node_1.respond_block(
                    full_node_protocol.RespondBlock(block)):
                pass

        # Coinbase that gets spent
        block1 = blocks[1]

        # This condition requires fee to be 10 mojo
        cvp_fee = ConditionVarPair(ConditionOpcode.ASSERT_FEE,
                                   int_to_bytes(10), None)
        block1_dic = {cvp_fee.opcode: [cvp_fee]}
        # This spendbundle has 9 mojo as fee
        invalid_spend_bundle = wallet_a.generate_signed_transaction(
            1000, receiver_puzzlehash, block1.get_coinbase(), block1_dic, 9)

        assert invalid_spend_bundle is not None
        program = best_solution_program(invalid_spend_bundle)
        aggsig = invalid_spend_bundle.aggregated_signature

        # Create another block that includes our transaction
        dic_h = {11: (program, aggsig)}
        invalid_new_blocks = bt.get_consecutive_blocks(
            test_constants,
            1,
            blocks,
            10,
            b"",
            coinbase_puzzlehash,
            dic_h,
            fees=uint64(9),
        )

        # Try to validate that block at index 11
        next_block = invalid_new_blocks[11]
        error = await full_node_1.blockchain._validate_transactions(
            next_block,
            next_block.get_fees_coin().amount)

        assert error is Err.ASSERT_FEE_CONDITION_FAILED

        # This condition requires fee to be 10 mojo
        cvp_fee = ConditionVarPair(ConditionOpcode.ASSERT_FEE,
                                   int_to_bytes(10), None)
        condition_dict = {cvp_fee.opcode: [cvp_fee]}
        valid_spend_bundle = wallet_a.generate_signed_transaction(
            1000, receiver_puzzlehash, block1.get_coinbase(), condition_dict,
            10)

        assert valid_spend_bundle is not None
        valid_program = best_solution_program(valid_spend_bundle)
        aggsig = valid_spend_bundle.aggregated_signature

        dic_h = {11: (valid_program, aggsig)}
        valid_new_blocks = bt.get_consecutive_blocks(
            test_constants,
            1,
            blocks[:11],
            10,
            b"",
            coinbase_puzzlehash,
            dic_h,
            fees=uint64(10),
        )

        next_block = valid_new_blocks[11]
        fee_base = calculate_base_fee(next_block.height)
        error = await full_node_1.blockchain._validate_transactions(
            next_block, fee_base)

        assert error is None

        for block in valid_new_blocks:
            async for _ in full_node_1.respond_block(
                    full_node_protocol.RespondBlock(block)):
                pass
Esempio n. 18
0
    async def test_validate_blockchain_with_reorg_double_spend(
            self, two_nodes):
        num_blocks = 10
        wallet_a = WalletTool()
        coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
        wallet_receiver = WalletTool()
        receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()

        blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10,
                                           b"", coinbase_puzzlehash)
        full_node_1, full_node_2, server_1, server_2 = two_nodes

        for block in blocks:
            async for _ in full_node_1.respond_block(
                    full_node_protocol.RespondBlock(block)):
                pass

        spent_block = blocks[1]

        spend_bundle = wallet_a.generate_signed_transaction(
            1000, receiver_puzzlehash, spent_block.get_coinbase())
        block_spendbundle = SpendBundle.aggregate([spend_bundle])
        program = best_solution_program(block_spendbundle)
        aggsig = block_spendbundle.aggregated_signature

        dic_h = {11: (program, aggsig)}
        blocks = bt.get_consecutive_blocks(test_constants, 10, blocks, 10, b"",
                                           coinbase_puzzlehash, dic_h)
        # Move chain to height 20, with a spend at height 11
        for block in blocks:
            async for _ in full_node_1.respond_block(
                    full_node_protocol.RespondBlock(block)):
                pass

        # Reorg at block 5, same spend at block 13 and 14 that was previously at block 11
        dic_h = {13: (program, aggsig), 14: (program, aggsig)}
        new_blocks = bt.get_consecutive_blocks(
            test_constants,
            9,
            blocks[:6],
            10,
            b"another seed",
            coinbase_puzzlehash,
            dic_h,
        )

        for block in new_blocks[:13]:
            async for _ in full_node_1.respond_block(
                    full_node_protocol.RespondBlock(block)):
                pass
        next_block = new_blocks[13]
        error = await full_node_1.blockchain._validate_transactions(
            next_block,
            next_block.get_fees_coin().amount)
        assert error is None
        [
            _ async for _ in full_node_1.respond_block(
                full_node_protocol.RespondBlock(new_blocks[13]))
        ]
        next_block = new_blocks[14]
        error = await full_node_1.blockchain._validate_transactions(
            next_block,
            next_block.get_fees_coin().amount)
        assert error is Err.DOUBLE_SPEND

        # Now test Reorg at block 5, same spend at block 9 that was previously at block 11
        dic_h = {9: (program, aggsig)}
        new_blocks = bt.get_consecutive_blocks(
            test_constants,
            4,
            blocks[:6],
            10,
            b"another seed 2",
            coinbase_puzzlehash,
            dic_h,
        )
        for block in new_blocks[:9]:
            async for _ in full_node_1.respond_block(
                    full_node_protocol.RespondBlock(block)):
                pass
        next_block = new_blocks[9]
        error = await full_node_1.blockchain._validate_transactions(
            next_block,
            next_block.get_fees_coin().amount)
        assert error is None

        # Now test Reorg at block 10, same spend at block 11 that was previously at block 11
        dic_h = {11: (program, aggsig)}
        new_blocks = bt.get_consecutive_blocks(
            test_constants,
            4,
            blocks[:11],
            10,
            b"another seed 3",
            coinbase_puzzlehash,
            dic_h,
        )
        for block in new_blocks[:11]:
            async for _ in full_node_1.respond_block(
                    full_node_protocol.RespondBlock(block)):
                pass
        next_block = new_blocks[11]
        error = await full_node_1.blockchain._validate_transactions(
            next_block,
            next_block.get_fees_coin().amount)
        assert error is None

        # Now test Reorg at block 11, same spend at block 12 that was previously at block 11
        dic_h = {12: (program, aggsig)}
        new_blocks = bt.get_consecutive_blocks(
            test_constants,
            4,
            blocks[:12],
            10,
            b"another seed 4",
            coinbase_puzzlehash,
            dic_h,
        )
        for block in new_blocks[:12]:
            async for _ in full_node_1.respond_block(
                    full_node_protocol.RespondBlock(block)):
                pass
        next_block = new_blocks[12]
        error = await full_node_1.blockchain._validate_transactions(
            next_block,
            next_block.get_fees_coin().amount)
        assert error is Err.DOUBLE_SPEND

        # Now test Reorg at block 11, same spend at block 15 that was previously at block 11
        dic_h = {15: (program, aggsig)}
        new_blocks = bt.get_consecutive_blocks(
            test_constants,
            4,
            blocks[:12],
            10,
            b"another seed 5",
            coinbase_puzzlehash,
            dic_h,
        )
        for block in new_blocks[:15]:
            async for _ in full_node_1.respond_block(
                    full_node_protocol.RespondBlock(block)):
                pass
        next_block = new_blocks[15]
        error = await full_node_1.blockchain._validate_transactions(
            next_block,
            next_block.get_fees_coin().amount)
        assert error is Err.DOUBLE_SPEND
Esempio n. 19
0
    async def test_validate_blockchain_spend_reorg_coin(self, two_nodes):
        num_blocks = 10
        wallet_a = WalletTool()
        coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
        receiver_1_puzzlehash = wallet_a.get_new_puzzlehash()
        receiver_2_puzzlehash = wallet_a.get_new_puzzlehash()
        receiver_3_puzzlehash = wallet_a.get_new_puzzlehash()

        blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10,
                                           b"", coinbase_puzzlehash)
        full_node_1, full_node_2, server_1, server_2 = two_nodes

        for block in blocks:
            async for _ in full_node_1.respond_block(
                    full_node_protocol.RespondBlock(block)):
                pass

        spent_block = blocks[1]

        spend_bundle = wallet_a.generate_signed_transaction(
            1000, receiver_1_puzzlehash, spent_block.get_coinbase())
        block_spendbundle = SpendBundle.aggregate([spend_bundle])
        program = best_solution_program(block_spendbundle)
        aggsig = block_spendbundle.aggregated_signature

        dic_h = {5: (program, aggsig)}
        new_blocks = bt.get_consecutive_blocks(
            test_constants,
            1,
            blocks[:5],
            10,
            b"spend_reorg_coin",
            coinbase_puzzlehash,
            dic_h,
        )
        [
            _ async for _ in full_node_1.respond_block(
                full_node_protocol.RespondBlock(new_blocks[-1]))
        ]
        assert new_blocks[-1].header_hash in full_node_1.blockchain.headers

        coin_2 = None
        for coin in new_blocks[-1].additions():
            if coin.puzzle_hash == receiver_1_puzzlehash:
                coin_2 = coin
                break
        assert coin_2 is not None

        spend_bundle = wallet_a.generate_signed_transaction(
            1000, receiver_2_puzzlehash, coin_2)
        block_spendbundle = SpendBundle.aggregate([spend_bundle])
        program = best_solution_program(block_spendbundle)
        aggsig = block_spendbundle.aggregated_signature

        dic_h = {6: (program, aggsig)}
        new_blocks = bt.get_consecutive_blocks(
            test_constants,
            1,
            new_blocks[:6],
            10,
            b"spend_reorg_coin",
            coinbase_puzzlehash,
            dic_h,
        )
        [
            _ async for _ in full_node_1.respond_block(
                full_node_protocol.RespondBlock(new_blocks[-1]))
        ]
        assert new_blocks[-1].header_hash in full_node_1.blockchain.headers

        coin_3 = None
        for coin in new_blocks[-1].additions():
            if coin.puzzle_hash == receiver_2_puzzlehash:
                coin_3 = coin
                break
        assert coin_3 is not None

        spend_bundle = wallet_a.generate_signed_transaction(
            1000, receiver_3_puzzlehash, coin_3)
        block_spendbundle = SpendBundle.aggregate([spend_bundle])
        program = best_solution_program(block_spendbundle)
        aggsig = block_spendbundle.aggregated_signature

        dic_h = {7: (program, aggsig)}
        new_blocks = bt.get_consecutive_blocks(
            test_constants,
            1,
            new_blocks[:7],
            10,
            b"spend_reorg_coin",
            coinbase_puzzlehash,
            dic_h,
        )
        [
            _ async for _ in full_node_1.respond_block(
                full_node_protocol.RespondBlock(new_blocks[-1]))
        ]
        assert new_blocks[-1].header_hash in full_node_1.blockchain.headers

        coin_4 = None
        for coin in new_blocks[-1].additions():
            if coin.puzzle_hash == receiver_3_puzzlehash:
                coin_4 = coin
                break
        assert coin_4 is not None
Esempio n. 20
0
    async def test_invalid_filter(self, two_nodes):
        num_blocks = 10
        wallet_a = WalletTool()
        coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
        wallet_receiver = WalletTool()
        receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()

        blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10,
                                           b"", coinbase_puzzlehash)
        full_node_1, full_node_2, server_1, server_2 = two_nodes

        for block in blocks:
            async for _ in full_node_1.respond_block(
                    full_node_protocol.RespondBlock(block)):
                pass

        spent_block = blocks[1]

        spend_bundle = wallet_a.generate_signed_transaction(
            1000, receiver_puzzlehash, spent_block.get_coinbase())

        assert spend_bundle is not None
        tx: full_node_protocol.RespondTransaction = (
            full_node_protocol.RespondTransaction(spend_bundle))
        async for _ in full_node_1.respond_transaction(tx):
            outbound: OutboundMessage = _
            # Maybe transaction means that it's accepted in mempool
            assert outbound.message.function == "new_transaction"

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

        last_block = blocks[10]
        next_spendbundle = await full_node_1.mempool_manager.create_bundle_for_tip(
            last_block.header)
        assert next_spendbundle is not None

        program = best_solution_program(next_spendbundle)
        aggsig = next_spendbundle.aggregated_signature

        dic_h = {11: (program, aggsig)}
        new_blocks = bt.get_consecutive_blocks(test_constants, 1, blocks, 10,
                                               b"", coinbase_puzzlehash, dic_h)

        next_block = new_blocks[11]

        bad_header = HeaderData(
            next_block.header.data.height,
            next_block.header.data.prev_header_hash,
            next_block.header.data.timestamp,
            bytes32(bytes([3] * 32)),
            next_block.header.data.proof_of_space_hash,
            next_block.header.data.weight,
            next_block.header.data.total_iters,
            next_block.header.data.additions_root,
            next_block.header.data.removals_root,
            next_block.header.data.farmer_rewards_puzzle_hash,
            next_block.header.data.total_transaction_fees,
            next_block.header.data.pool_target,
            next_block.header.data.aggregated_signature,
            next_block.header.data.cost,
            next_block.header.data.extension_data,
            next_block.header.data.generator_hash,
        )
        bad_block = FullBlock(
            next_block.proof_of_space,
            next_block.proof_of_time,
            Header(
                bad_header,
                bt.get_plot_signature(
                    bad_header, next_block.proof_of_space.plot_public_key),
            ),
            next_block.transactions_generator,
            next_block.transactions_filter,
        )
        result, removed, error_code = await full_node_1.blockchain.receive_block(
            bad_block)
        assert result == ReceiveBlockResult.INVALID_BLOCK
        assert error_code == Err.INVALID_TRANSACTIONS_FILTER_HASH

        result, removed, error_code = await full_node_1.blockchain.receive_block(
            next_block)
        assert result == ReceiveBlockResult.ADDED_TO_HEAD
Esempio n. 21
0
    async def test_assert_time_exceeds(self, two_nodes):

        num_blocks = 10
        wallet_a = WalletTool()
        coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
        wallet_receiver = WalletTool()
        receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()

        # Farm blocks
        blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10,
                                           b"", coinbase_puzzlehash)
        full_node_1, full_node_2, server_1, server_2 = two_nodes

        for block in blocks:
            async for _ in full_node_1.respond_block(
                    full_node_protocol.RespondBlock(block)):
                pass

        # Coinbase that gets spent
        block1 = blocks[1]

        # This condition requires block1 coinbase to be spent after 3 seconds from now
        current_time_plus3 = uint64(int(time.time() * 1000) + 3000)
        block1_cvp = ConditionVarPair(ConditionOpcode.ASSERT_TIME_EXCEEDS,
                                      int_to_bytes(current_time_plus3), None)
        block1_dic = {block1_cvp.opcode: [block1_cvp]}
        block1_spend_bundle = wallet_a.generate_signed_transaction(
            1000, receiver_puzzlehash, block1.get_coinbase(), block1_dic)

        # program that will be sent to early
        assert block1_spend_bundle is not None
        program = best_solution_program(block1_spend_bundle)
        aggsig = block1_spend_bundle.aggregated_signature

        # Create another block that includes our transaction
        dic_h = {11: (program, aggsig)}
        invalid_new_blocks = bt.get_consecutive_blocks(test_constants, 1,
                                                       blocks, 10, b"",
                                                       coinbase_puzzlehash,
                                                       dic_h)

        # Try to validate that block before 3 sec
        next_block = invalid_new_blocks[11]
        error = await full_node_1.blockchain._validate_transactions(
            next_block,
            next_block.get_fees_coin().amount)

        assert error is Err.ASSERT_TIME_EXCEEDS_FAILED

        # wait 3 sec to pass
        await asyncio.sleep(3.1)

        dic_h = {12: (program, aggsig)}
        valid_new_blocks = bt.get_consecutive_blocks(test_constants, 2,
                                                     blocks[:11], 10, b"",
                                                     coinbase_puzzlehash,
                                                     dic_h)

        for block in valid_new_blocks:
            async for _ in full_node_1.respond_block(
                    full_node_protocol.RespondBlock(block)):
                pass

        # Try to validate that block after 3 sec have passed
        next_block = valid_new_blocks[12]

        error = await full_node_1.blockchain._validate_transactions(
            next_block,
            next_block.get_fees_coin().amount)

        assert error is None
Esempio n. 22
0
    async def test_assert_block_age_exceeds(self, two_nodes):

        num_blocks = 10
        wallet_a = WalletTool()
        coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
        wallet_receiver = WalletTool()
        receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()

        # Farm blocks
        blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10,
                                           b"", coinbase_puzzlehash)
        full_node_1, full_node_2, server_1, server_2 = two_nodes

        for block in blocks:
            async for _ in full_node_1.respond_block(
                    full_node_protocol.RespondBlock(block)):
                pass

        # Coinbase that gets spent
        block1 = blocks[1]

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

        # program that will be sent to early
        assert block1_spend_bundle is not None
        program = best_solution_program(block1_spend_bundle)
        aggsig = block1_spend_bundle.aggregated_signature

        # Create another block that includes our transaction
        dic_h = {11: (program, aggsig)}
        invalid_new_blocks = bt.get_consecutive_blocks(test_constants, 1,
                                                       blocks, 10, b"",
                                                       coinbase_puzzlehash,
                                                       dic_h)

        # Try to validate that block at index 11
        next_block = invalid_new_blocks[11]
        error = await full_node_1.blockchain._validate_transactions(
            next_block,
            next_block.get_fees_coin().amount)

        assert error is Err.ASSERT_BLOCK_AGE_EXCEEDS_FAILED

        dic_h = {12: (program, aggsig)}
        valid_new_blocks = bt.get_consecutive_blocks(test_constants, 2,
                                                     blocks[:11], 10, b"",
                                                     coinbase_puzzlehash,
                                                     dic_h)

        for block in valid_new_blocks:
            async for _ in full_node_1.respond_block(
                    full_node_protocol.RespondBlock(block)):
                pass

        # Try to validate that block at index 12
        next_block = valid_new_blocks[12]

        error = await full_node_1.blockchain._validate_transactions(
            next_block,
            next_block.get_fees_coin().amount)

        assert error is None
Esempio n. 23
0
from src.consensus.blockchain import ReceiveBlockResult
from src.protocols import full_node_protocol
from src.types.condition_opcodes import ConditionOpcode
from src.types.condition_var_pair import ConditionVarPair
from src.types.spend_bundle import SpendBundle
from src.util.errors import Err, ConsensusError
from src.util.ints import uint64
from tests.core.full_node.test_full_node import connect_and_get_peer
from tests.setup_nodes import setup_two_nodes, test_constants, bt
from src.util.wallet_tools import WalletTool
from src.types.announcement import Announcement

BURN_PUZZLE_HASH = b"0" * 32

WALLET_A = WalletTool()
WALLET_A_PUZZLE_HASHES = [WALLET_A.get_new_puzzlehash() for _ in range(5)]

log = logging.getLogger(__name__)


@pytest.fixture(scope="session")
def event_loop():
    loop = asyncio.get_event_loop()
    yield loop


class TestBlockchainTransactions:
    @pytest.fixture(scope="function")
    async def two_nodes(self):
        async for _ in setup_two_nodes(test_constants):
            yield _
Esempio n. 24
0
    async def test_basic_blockchain_tx(self, two_nodes):
        num_blocks = 10
        wallet_a = WalletTool()
        coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
        wallet_receiver = WalletTool()
        receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()

        blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10,
                                           b"", coinbase_puzzlehash)
        full_node_1, full_node_2, server_1, server_2 = two_nodes

        for block in blocks:
            async for _ in full_node_1.respond_block(
                    full_node_protocol.RespondBlock(block)):
                pass

        spent_block = blocks[1]

        spend_bundle = wallet_a.generate_signed_transaction(
            1000, receiver_puzzlehash, spent_block.get_coinbase())

        assert spend_bundle is not None
        tx: full_node_protocol.RespondTransaction = (
            full_node_protocol.RespondTransaction(spend_bundle))
        async for _ in full_node_1.respond_transaction(tx):
            outbound: OutboundMessage = _
            # Maybe transaction means that it's accepted in mempool
            assert outbound.message.function == "new_transaction"

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

        last_block = blocks[10]
        next_spendbundle = await full_node_1.mempool_manager.create_bundle_for_tip(
            last_block.header)
        assert next_spendbundle is not None

        program = best_solution_program(next_spendbundle)
        aggsig = next_spendbundle.aggregated_signature

        dic_h = {11: (program, aggsig)}
        new_blocks = bt.get_consecutive_blocks(test_constants, 1, blocks, 10,
                                               b"", coinbase_puzzlehash, dic_h)

        next_block = new_blocks[11]
        async for _ in full_node_1.respond_block(
                full_node_protocol.RespondBlock(next_block)):
            pass

        tips = full_node_1.blockchain.get_current_tips()
        assert next_block.header in tips

        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(), next_block.header)
            assert unspent is not None

        full_tips = await full_node_1.blockchain.get_full_tips()
        in_full_tips = False

        farmed_block: Optional[FullBlock] = None
        for tip in full_tips:
            if tip.header == next_block.header:
                in_full_tips = True
                farmed_block = tip

        assert in_full_tips
        assert farmed_block is not None
        assert farmed_block.transactions_generator == program
Esempio n. 25
0
    async def test_assert_coin_consumed(self, two_nodes):

        num_blocks = 10
        wallet_a = WalletTool()
        coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
        wallet_receiver = WalletTool()
        receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()

        # Farm blocks
        blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10,
                                           b"", coinbase_puzzlehash)
        full_node_1, full_node_2, server_1, server_2 = two_nodes

        for block in blocks:
            async for _ in full_node_1.respond_block(
                    full_node_protocol.RespondBlock(block)):
                pass

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

        # This condition requires block2 coinbase to be spent
        block1_cvp = ConditionVarPair(
            ConditionOpcode.ASSERT_COIN_CONSUMED,
            block2.get_coinbase().name(),
            None,
        )
        block1_dic = {block1_cvp.opcode: [block1_cvp]}
        block1_spend_bundle = wallet_a.generate_signed_transaction(
            1000, receiver_puzzlehash, block1.get_coinbase(), block1_dic)

        # This condition requires block1 coinbase to be spent
        block2_cvp = ConditionVarPair(
            ConditionOpcode.ASSERT_COIN_CONSUMED,
            block1.get_coinbase().name(),
            None,
        )
        block2_dic = {block2_cvp.opcode: [block2_cvp]}
        block2_spend_bundle = wallet_a.generate_signed_transaction(
            1000, receiver_puzzlehash, block2.get_coinbase(), block2_dic)

        # Invalid block bundle
        assert block1_spend_bundle is not None
        solo_program = best_solution_program(block1_spend_bundle)
        aggsig = block1_spend_bundle.aggregated_signature

        # Create another block that includes our transaction
        dic_h = {11: (solo_program, aggsig)}
        invalid_new_blocks = bt.get_consecutive_blocks(test_constants, 1,
                                                       blocks, 10, b"",
                                                       coinbase_puzzlehash,
                                                       dic_h)

        # Try to validate that block
        next_block = invalid_new_blocks[11]
        error = await full_node_1.blockchain._validate_transactions(
            next_block,
            next_block.get_fees_coin().amount)

        assert error is Err.ASSERT_COIN_CONSUMED_FAILED

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

        # Create another block that includes our transaction
        dic_h = {11: (valid_program, aggsig)}
        new_blocks = bt.get_consecutive_blocks(test_constants, 1, blocks[:11],
                                               10, b"1", coinbase_puzzlehash,
                                               dic_h)

        # Try to validate newly created block
        next_block = new_blocks[11]
        error = await full_node_1.blockchain._validate_transactions(
            next_block,
            next_block.get_fees_coin().amount)

        assert error is None
Esempio n. 26
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()