async def test_wallet_coinbase_reorg(self, wallet_node):
        num_blocks = 10
        full_nodes, wallets = wallet_node
        full_node_1, server_1 = full_nodes[0]
        wallet_node, server_2 = wallets[0]
        wallet = wallet_node.wallet_state_manager.main_wallet
        ph = await wallet.get_new_puzzlehash()

        await server_2.start_client(PeerInfo("localhost", uint16(server_1._port)), None)
        for i in range(1, num_blocks):
            await full_node_1.farm_new_block(FarmNewBlockProtocol(ph))

        await asyncio.sleep(3)
        funds = sum(
            [
                calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
                for i in range(1, num_blocks - 2)
            ]
        )
        assert await wallet.get_confirmed_balance() == funds

        await full_node_1.reorg_from_index_to_new_index(
            ReorgProtocol(uint32(5), uint32(num_blocks + 3), token_bytes())
        )
        await asyncio.sleep(3)

        funds = sum(
            [
                calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
                for i in range(1, 5)
            ]
        )

        assert await wallet.get_confirmed_balance() == funds
    async def test_wallet_make_transaction(self, two_wallet_nodes):
        num_blocks = 10
        full_nodes, wallets = two_wallet_nodes
        full_node_1, server_1 = full_nodes[0]
        wallet_node, server_2 = wallets[0]
        wallet_node_2, server_3 = wallets[1]
        wallet = wallet_node.wallet_state_manager.main_wallet
        ph = await wallet.get_new_puzzlehash()

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

        for i in range(0, num_blocks):
            await full_node_1.farm_new_block(FarmNewBlockProtocol(ph))

        funds = sum(
            [
                calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
                for i in range(0, num_blocks - 2)
            ]
        )

        await asyncio.sleep(2)

        assert await wallet.get_confirmed_balance() == funds
        assert await wallet.get_unconfirmed_balance() == funds

        spend_bundle = await wallet.generate_signed_transaction(
            10,
            await wallet_node_2.wallet_state_manager.main_wallet.get_new_puzzlehash(),
            0,
        )
        await wallet.push_transaction(spend_bundle)

        await asyncio.sleep(2)
        confirmed_balance = await wallet.get_confirmed_balance()
        unconfirmed_balance = await wallet.get_unconfirmed_balance()

        assert confirmed_balance == funds
        assert unconfirmed_balance == funds - 10

        for i in range(0, num_blocks):
            await full_node_1.farm_new_block(FarmNewBlockProtocol(ph))

        await asyncio.sleep(2)

        new_funds = sum(
            [
                calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
                for i in range(0, (2 * num_blocks) - 2)
            ]
        )

        confirmed_balance = await wallet.get_confirmed_balance()
        unconfirmed_balance = await wallet.get_unconfirmed_balance()

        assert confirmed_balance == new_funds - 10
        assert unconfirmed_balance == new_funds - 10
    async def test_colour_creation(self, two_wallet_nodes):
        num_blocks = 5
        full_nodes, wallets = two_wallet_nodes
        full_node_1, server_1 = full_nodes[0]
        wallet_node, server_2 = wallets[0]
        wallet = wallet_node.wallet_state_manager.main_wallet

        ph = await wallet.get_new_puzzlehash()

        await server_2.start_client(PeerInfo("localhost", uint16(server_1._port)), None)
        for i in range(1, 4):
            await full_node_1.farm_new_block(FarmNewBlockProtocol(ph))

        funds = sum(
            [
                calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
                for i in range(1, 4 - 2)
            ]
        )

        await time_out_assert(15, wallet.get_confirmed_balance, funds)

        cc_wallet: CCWallet = await CCWallet.create_new_cc(
            wallet_node.wallet_state_manager, wallet, uint64(100)
        )

        for i in range(1, num_blocks):
            await full_node_1.farm_new_block(FarmNewBlockProtocol(ph))

        await time_out_assert(15, cc_wallet.get_confirmed_balance, 100)
        await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 100)
    async def test_generate_zero_val(self, two_wallet_nodes):
        num_blocks = 10
        full_nodes, wallets = two_wallet_nodes
        full_node_1, server_1 = full_nodes[0]
        wallet_node, server_2 = wallets[0]
        wallet_node_2, server_3 = wallets[1]
        wallet = wallet_node.wallet_state_manager.main_wallet
        wallet2 = wallet_node_2.wallet_state_manager.main_wallet

        ph = await wallet.get_new_puzzlehash()

        await server_2.start_client(PeerInfo("localhost", uint16(server_1._port)), None)
        await server_3.start_client(PeerInfo("localhost", uint16(server_1._port)), None)
        for i in range(1, 4):
            await full_node_1.farm_new_block(FarmNewBlockProtocol(ph))

        funds = sum(
            [
                calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
                for i in range(1, 4 - 2)
            ]
        )
        await time_out_assert(15, wallet.get_confirmed_balance, funds)

        cc_wallet: CCWallet = await CCWallet.create_new_cc(
            wallet_node.wallet_state_manager, wallet, uint64(100)
        )

        ph = await wallet2.get_new_puzzlehash()
        for i in range(1, num_blocks):
            await full_node_1.farm_new_block(FarmNewBlockProtocol(ph))

        await time_out_assert(15, cc_wallet.get_confirmed_balance, 100)
        await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 100)

        assert cc_wallet.cc_info.my_genesis_checker is not None
        colour = cc_wallet.get_colour()

        cc_wallet_2: CCWallet = await CCWallet.create_wallet_for_cc(
            wallet_node_2.wallet_state_manager, wallet2, colour
        )

        assert (
            cc_wallet.cc_info.my_genesis_checker
            == cc_wallet_2.cc_info.my_genesis_checker
        )

        await cc_wallet_2.generate_zero_val_coin()

        for i in range(1, num_blocks):
            await full_node_1.farm_new_block(FarmNewBlockProtocol(ph))

        unspent: List[WalletCoinRecord] = list(
            await cc_wallet_2.wallet_state_manager.get_spendable_coins_for_wallet(
                cc_wallet_2.id()
            )
        )
        assert len(unspent) == 1
        assert unspent.pop().coin.amount == 0
Beispiel #5
0
    async def test_coin_backup(self, two_wallet_nodes):
        num_blocks = 5
        full_nodes, wallets = two_wallet_nodes
        full_node_1, server_1 = full_nodes[0]
        wallet_node, server_2 = wallets[0]
        wallet = wallet_node.wallet_state_manager.main_wallet

        ph = await wallet.get_new_puzzlehash()

        await server_2.start_client(
            PeerInfo("localhost", uint16(server_1._port)), None)
        for i in range(1, 4):
            await full_node_1.farm_new_block(FarmNewBlockProtocol(ph))

        funds = sum([
            calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
            for i in range(1, 4 - 2)
        ])

        await time_out_assert(15, wallet.get_confirmed_balance, funds)

        cc_wallet: CCWallet = await CCWallet.create_new_cc(
            wallet_node.wallet_state_manager, wallet, uint64(100))

        for i in range(1, num_blocks):
            await full_node_1.farm_new_block(FarmNewBlockProtocol(ph))

        await time_out_assert(15, cc_wallet.get_confirmed_balance, 100)
        await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 100)

        # Write backup to file
        filename = f"test-backup-{token_bytes(16).hex()}"
        file_path = Path(filename)
        await wallet_node.wallet_state_manager.create_wallet_backup(file_path)

        # Close wallet and restart
        db_path = wallet_node.wallet_state_manager.db_path
        wallet_node._close()
        await wallet_node._await_closed()

        db_path.unlink()

        started = await wallet_node._start()
        assert started is False

        await wallet_node._start(backup_file=file_path)
        await server_2.start_client(
            PeerInfo("localhost", uint16(server_1._port)), None)

        all_wallets = wallet_node.wallet_state_manager.wallets
        assert len(all_wallets) == 2

        cc_wallet_from_backup = wallet_node.wallet_state_manager.wallets[2]

        await time_out_assert(15, cc_wallet_from_backup.get_confirmed_balance,
                              100)
        if file_path.exists():
            file_path.unlink()
Beispiel #6
0
    async def test_wallet_make_transaction(self, two_wallet_nodes):
        num_blocks = 5
        full_nodes, wallets = two_wallet_nodes
        full_node_1, server_1 = full_nodes[0]
        wallet_node, server_2 = wallets[0]
        wallet_node_2, server_3 = wallets[1]
        wallet = wallet_node.wallet_state_manager.main_wallet
        ph = await wallet.get_new_puzzlehash()

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

        for i in range(0, num_blocks):
            await full_node_1.farm_new_block(FarmNewBlockProtocol(ph))

        funds = sum([
            calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
            for i in range(1, num_blocks - 1)
        ])

        await time_out_assert(5, wallet.get_confirmed_balance, funds)
        await time_out_assert(5, wallet.get_unconfirmed_balance, funds)

        tx = await wallet.generate_signed_transaction(
            10,
            await
            wallet_node_2.wallet_state_manager.main_wallet.get_new_puzzlehash(
            ),
            0,
        )
        await wallet.push_transaction(tx)

        await time_out_assert(5, wallet.get_confirmed_balance, funds)
        await time_out_assert(5, wallet.get_unconfirmed_balance, funds - 10)

        for i in range(0, num_blocks):
            await full_node_1.farm_new_block(FarmNewBlockProtocol(ph))

        new_funds = sum([
            calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
            for i in range(1, (2 * num_blocks) - 1)
        ])
        await time_out_assert(5, wallet.get_confirmed_balance, new_funds - 10)
        await time_out_assert(5, wallet.get_unconfirmed_balance,
                              new_funds - 10)
Beispiel #7
0
    async def validate_block_body(self, block: FullBlock) -> Optional[Err]:
        """
        Validates the transactions and body of the block. Returns None if everything
        validates correctly, or an Err if something does not validate.
        """

        # 6. The compact block filter must be correct, according to the body (BIP158)
        if std_hash(block.transactions_filter) != block.header.data.filter_hash:
            return Err.INVALID_TRANSACTIONS_FILTER_HASH

        fee_base = calculate_base_fee(block.height)
        # target reward_fee = 1/8 coinbase reward + tx fees
        if block.transactions_generator is not None:
            # 14. Make sure transactions generator hash is valid (or all 0 if not present)
            if (
                block.transactions_generator.get_tree_hash()
                != block.header.data.generator_hash
            ):
                return Err.INVALID_TRANSACTIONS_GENERATOR_HASH

            # 15. If not genesis, the transactions must be valid and fee must be valid
            # Verifies that fee_base + TX fees = fee_coin.amount
            err = await self._validate_transactions(block, fee_base)
            if err is not None:
                return err
        else:
            # Make sure transactions generator hash is valid (or all 0 if not present)
            if block.header.data.generator_hash != bytes32(bytes([0] * 32)):
                return Err.INVALID_TRANSACTIONS_GENERATOR_HASH

            # 16. If genesis, the fee must be the base fee, agg_sig must be None, and merkle roots must be valid
            if fee_base != block.header.data.total_transaction_fees:
                return Err.INVALID_BLOCK_FEE_AMOUNT
            root_error = self._validate_merkle_root(block)
            if root_error:
                return root_error

            # 17. Verify the pool signature even if there are no transactions
            pool_target_m = bytes(block.header.data.pool_target)
            validates = AugSchemeMPL.verify(
                block.proof_of_space.pool_public_key,
                pool_target_m,
                block.header.data.aggregated_signature,
            )
            if not validates:
                return Err.BAD_AGGREGATE_SIGNATURE

        return None
Beispiel #8
0
    async def test_wallet_coinbase(self, wallet_node):
        num_blocks = 5
        full_nodes, wallets = wallet_node
        full_node_1, server_1 = full_nodes[0]
        wallet_node, server_2 = wallets[0]
        wallet = wallet_node.wallet_state_manager.main_wallet
        ph = await wallet.get_new_puzzlehash()

        await server_2.start_client(
            PeerInfo("localhost", uint16(server_1._port)), None)
        for i in range(1, num_blocks):
            await full_node_1.farm_new_block(FarmNewBlockProtocol(ph))

        funds = sum([
            calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
            for i in range(1, num_blocks - 2)
        ])
        await time_out_assert(5, wallet.get_confirmed_balance, funds)
    async def test_wallet_make_transaction_hop(self, two_wallet_nodes_five_freeze):
        num_blocks = 10
        full_nodes, wallets = two_wallet_nodes_five_freeze
        full_node_0, full_node_server = full_nodes[0]
        wallet_node_0, wallet_0_server = wallets[0]
        wallet_node_1, wallet_1_server = wallets[1]
        wallet_0 = wallet_node_0.wallet_state_manager.main_wallet
        wallet_1 = wallet_node_1.wallet_state_manager.main_wallet
        ph = await wallet_0.get_new_puzzlehash()

        await wallet_0_server.start_client(
            PeerInfo("localhost", uint16(full_node_server._port)), None
        )

        await wallet_1_server.start_client(
            PeerInfo("localhost", uint16(full_node_server._port)), None
        )

        for i in range(0, num_blocks):
            await full_node_0.farm_new_block(FarmNewBlockProtocol(ph))

        funds = sum(
            [
                calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
                for i in range(0, num_blocks - 2)
            ]
        )

        await asyncio.sleep(2)

        assert await wallet_0.get_confirmed_balance() == funds
        assert await wallet_0.get_unconfirmed_balance() == funds

        spend_bundle = await wallet_0.generate_signed_transaction(
            10,
            await wallet_node_1.wallet_state_manager.main_wallet.get_new_puzzlehash(),
            0,
        )

        await wallet_0.push_transaction(spend_bundle)

        await asyncio.sleep(1)
        # Full node height 11, wallet height 9
        confirmed_balance = await wallet_0.get_confirmed_balance()
        unconfirmed_balance = await wallet_0.get_unconfirmed_balance()

        assert confirmed_balance == funds
        assert unconfirmed_balance == funds - 10

        for i in range(0, 7):
            await full_node_0.farm_new_block(FarmNewBlockProtocol(token_bytes()))

        await asyncio.sleep(1)

        new_funds = sum(
            [
                calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
                for i in range(0, num_blocks)
            ]
        )

        # Full node height 17, wallet height 15
        confirmed_balance = await wallet_0.get_confirmed_balance()
        unconfirmed_balance = await wallet_0.get_unconfirmed_balance()
        wallet_2_confirmed_balance = await wallet_1.get_confirmed_balance()

        assert confirmed_balance == new_funds - 10
        assert unconfirmed_balance == new_funds - 10
        assert wallet_2_confirmed_balance == 10

        spend_bundle = await wallet_1.generate_signed_transaction(
            5, await wallet_0.get_new_puzzlehash(), 0
        )
        await wallet_1.push_transaction(spend_bundle)

        for i in range(0, 7):
            await full_node_0.farm_new_block(FarmNewBlockProtocol(token_bytes()))

        await asyncio.sleep(1)

        confirmed_balance = await wallet_0.get_confirmed_balance()
        unconfirmed_balance = await wallet_0.get_unconfirmed_balance()
        wallet_2_confirmed_balance = await wallet_1.get_confirmed_balance()

        assert confirmed_balance == new_funds - 5
        assert unconfirmed_balance == new_funds - 5
        assert wallet_2_confirmed_balance == 5
    async def test_wallet_send_to_three_peers(self, three_sim_two_wallets):
        num_blocks = 10
        full_nodes, wallets = three_sim_two_wallets

        wallet_0, wallet_server_0 = wallets[0]
        full_node_0, server_0 = full_nodes[0]
        full_node_1, server_1 = full_nodes[1]
        full_node_2, server_2 = full_nodes[2]

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

        # wallet0 <-> sever0
        await wallet_server_0.start_client(
            PeerInfo("localhost", uint16(server_0._port)), None
        )

        for i in range(1, num_blocks):
            await full_node_0.farm_new_block(FarmNewBlockProtocol(ph))

        all_blocks = await full_node_0.get_current_blocks(full_node_0.get_tip())

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

        await asyncio.sleep(2)
        funds = sum(
            [
                calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
                for i in range(1, num_blocks - 2)
            ]
        )
        assert (
            await wallet_0.wallet_state_manager.main_wallet.get_confirmed_balance()
            == funds
        )

        spend_bundle = 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(spend_bundle)

        await asyncio.sleep(1)

        bundle0 = full_node_0.mempool_manager.get_spendbundle(spend_bundle.name())
        assert bundle0 is not None

        # wallet0 <-> sever1
        await wallet_server_0.start_client(
            PeerInfo("localhost", uint16(server_1._port)), wallet_0._on_connect
        )
        await asyncio.sleep(1)

        bundle1 = full_node_1.mempool_manager.get_spendbundle(spend_bundle.name())
        assert bundle1 is not None

        # wallet0 <-> sever2
        await wallet_server_0.start_client(
            PeerInfo("localhost", uint16(server_2._port)), wallet_0._on_connect
        )
        await asyncio.sleep(1)

        bundle2 = full_node_2.mempool_manager.get_spendbundle(spend_bundle.name())
        assert bundle2 is not None
    async def test_cc_spend_multiple(self, three_wallet_nodes):
        num_blocks = 8
        full_nodes, wallets = three_wallet_nodes
        full_node_1, server_1 = full_nodes[0]
        wallet_node_0, wallet_server_0 = wallets[0]
        wallet_node_1, wallet_server_1 = wallets[1]
        wallet_node_2, wallet_server_2 = wallets[2]
        wallet_0 = wallet_node_0.wallet_state_manager.main_wallet
        wallet_1 = wallet_node_1.wallet_state_manager.main_wallet
        wallet_2 = wallet_node_2.wallet_state_manager.main_wallet

        ph = await wallet_0.get_new_puzzlehash()

        await wallet_server_0.start_client(
            PeerInfo("localhost", uint16(server_1._port)), None
        )
        await wallet_server_1.start_client(
            PeerInfo("localhost", uint16(server_1._port)), None
        )
        await wallet_server_2.start_client(
            PeerInfo("localhost", uint16(server_1._port)), None
        )

        for i in range(1, 4):
            await full_node_1.farm_new_block(FarmNewBlockProtocol(ph))

        funds = sum(
            [
                calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
                for i in range(1, 4 - 2)
            ]
        )

        await time_out_assert(15, wallet_0.get_confirmed_balance, funds)

        cc_wallet_0: CCWallet = await CCWallet.create_new_cc(
            wallet_node_0.wallet_state_manager, wallet_0, uint64(100)
        )

        for i in range(1, num_blocks):
            await full_node_1.farm_new_block(FarmNewBlockProtocol(ph))

        await time_out_assert(15, cc_wallet_0.get_confirmed_balance, 100)
        await time_out_assert(15, cc_wallet_0.get_unconfirmed_balance, 100)

        assert cc_wallet_0.cc_info.my_genesis_checker is not None
        colour = cc_wallet_0.get_colour()

        cc_wallet_1: CCWallet = await CCWallet.create_wallet_for_cc(
            wallet_node_1.wallet_state_manager, wallet_1, colour
        )

        cc_wallet_2: CCWallet = await CCWallet.create_wallet_for_cc(
            wallet_node_2.wallet_state_manager, wallet_2, colour
        )

        assert (
            cc_wallet_0.cc_info.my_genesis_checker
            == cc_wallet_1.cc_info.my_genesis_checker
        )
        assert (
            cc_wallet_0.cc_info.my_genesis_checker
            == cc_wallet_2.cc_info.my_genesis_checker
        )

        cc_1_hash = await cc_wallet_1.get_new_inner_hash()
        cc_2_hash = await cc_wallet_2.get_new_inner_hash()

        tx_record = await cc_wallet_0.generate_signed_transaction(
            [uint64(60), uint64(20)], [cc_1_hash, cc_2_hash]
        )
        await wallet_0.wallet_state_manager.add_pending_transaction(tx_record)

        for i in range(1, num_blocks):
            await full_node_1.farm_new_block(FarmNewBlockProtocol(ph))

        await time_out_assert(15, cc_wallet_0.get_confirmed_balance, 20)
        await time_out_assert(15, cc_wallet_0.get_unconfirmed_balance, 20)

        await time_out_assert(30, cc_wallet_1.get_confirmed_balance, 60)
        await time_out_assert(30, cc_wallet_1.get_unconfirmed_balance, 60)

        await time_out_assert(30, cc_wallet_2.get_confirmed_balance, 20)
        await time_out_assert(30, cc_wallet_2.get_unconfirmed_balance, 20)

        cc_hash = await cc_wallet_0.get_new_inner_hash()

        tx_record = await cc_wallet_1.generate_signed_transaction(
            [uint64(15)], [cc_hash]
        )
        await wallet_1.wallet_state_manager.add_pending_transaction(tx_record)

        tx_record_2 = await cc_wallet_2.generate_signed_transaction(
            [uint64(20)], [cc_hash]
        )
        await wallet_2.wallet_state_manager.add_pending_transaction(tx_record_2)

        for i in range(1, num_blocks):
            await full_node_1.farm_new_block(FarmNewBlockProtocol(ph))

        await time_out_assert(15, cc_wallet_0.get_confirmed_balance, 55)
        await time_out_assert(15, cc_wallet_0.get_unconfirmed_balance, 55)

        await time_out_assert(30, cc_wallet_1.get_confirmed_balance, 45)
        await time_out_assert(30, cc_wallet_1.get_unconfirmed_balance, 45)

        await time_out_assert(30, cc_wallet_2.get_confirmed_balance, 0)
        await time_out_assert(30, cc_wallet_2.get_unconfirmed_balance, 0)
Beispiel #12
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
    def _create_block(
        self,
        test_constants: Dict,
        challenge_hash: bytes32,
        height: uint32,
        prev_header_hash: bytes32,
        prev_iters: uint64,
        prev_weight: uint128,
        timestamp: uint64,
        difficulty: uint64,
        min_iters: uint64,
        seed: bytes,
        genesis: bool = False,
        reward_puzzlehash: bytes32 = None,
        transactions: Program = None,
        aggsig: BLSSignature = None,
        fees: uint64 = uint64(0),
    ) -> FullBlock:
        """
        Creates a block with the specified details. Uses the stored plots to create a proof of space,
        and also evaluates the VDF for the proof of time.
        """
        selected_prover = None
        selected_plot_sk = None
        selected_pool_sk = None
        selected_proof_index = 0
        plots = list(self.plot_config["plots"].items())
        selected_quality: Optional[bytes] = None
        best_quality = 0
        if self.use_any_pos:
            for i in range(len(plots) * 3):
                # Allow passing in seed, to create reorgs and different chains
                random.seed(seed + i.to_bytes(4, "big"))
                seeded_pn = random.randint(0, len(plots) - 1)
                pool_sk = PrivateKey.from_bytes(
                    bytes.fromhex(plots[seeded_pn][1]["pool_sk"])
                )
                plot_sk = PrivateKey.from_bytes(
                    bytes.fromhex(plots[seeded_pn][1]["sk"])
                )
                prover = DiskProver(plots[seeded_pn][0])
                qualities = prover.get_qualities_for_challenge(challenge_hash)
                if len(qualities) > 0:
                    if self.use_any_pos:
                        selected_quality = qualities[0]
                        selected_prover = prover
                        selected_pool_sk = pool_sk
                        selected_plot_sk = plot_sk
                        break
        else:
            for i in range(len(plots)):
                pool_sk = PrivateKey.from_bytes(bytes.fromhex(plots[i][1]["pool_sk"]))
                plot_sk = PrivateKey.from_bytes(bytes.fromhex(plots[i][1]["sk"]))
                prover = DiskProver(plots[i][0])
                qualities = prover.get_qualities_for_challenge(challenge_hash)
                j = 0
                for quality in qualities:
                    qual_int = int.from_bytes(quality, "big", signed=False)
                    if qual_int > best_quality:
                        best_quality = qual_int
                        selected_quality = quality
                        selected_prover = prover
                        selected_pool_sk = pool_sk
                        selected_plot_sk = plot_sk
                        selected_proof_index = j
                    j += 1

        assert selected_prover
        assert selected_pool_sk
        assert selected_plot_sk
        pool_pk = selected_pool_sk.get_public_key()
        plot_pk = selected_plot_sk.get_public_key()
        if selected_quality is None:
            raise RuntimeError("No proofs for this challenge")

        proof_xs: bytes = selected_prover.get_full_proof(
            challenge_hash, selected_proof_index
        )
        proof_of_space: ProofOfSpace = ProofOfSpace(
            challenge_hash, pool_pk, plot_pk, selected_prover.get_size(), proof_xs
        )
        number_iters: uint64 = pot_iterations.calculate_iterations(
            proof_of_space, difficulty, min_iters
        )
        # print("Doing iters", number_iters)
        int_size = (test_constants["DISCRIMINANT_SIZE_BITS"] + 16) >> 4

        result = prove(
            challenge_hash, test_constants["DISCRIMINANT_SIZE_BITS"], number_iters
        )

        output = ClassgroupElement(
            int512(int.from_bytes(result[0:int_size], "big", signed=True,)),
            int512(
                int.from_bytes(result[int_size : 2 * int_size], "big", signed=True,)
            ),
        )
        proof_bytes = result[2 * int_size : 4 * int_size]

        proof_of_time = ProofOfTime(
            challenge_hash, number_iters, output, self.n_wesolowski, proof_bytes,
        )

        if not reward_puzzlehash:
            reward_puzzlehash = self.fee_target

        # Use the extension data to create different blocks based on header hash
        extension_data: bytes32 = bytes32([random.randint(0, 255) for _ in range(32)])
        cost = uint64(0)

        coinbase_reward = block_rewards.calculate_block_reward(height)
        fee_reward = uint64(block_rewards.calculate_base_fee(height) + fees)

        coinbase_coin, coinbase_signature = create_coinbase_coin_and_signature(
            height, reward_puzzlehash, coinbase_reward, selected_pool_sk
        )

        parent_coin_name = std_hash(std_hash(height))
        fees_coin = Coin(parent_coin_name, reward_puzzlehash, uint64(fee_reward))

        # Create filter
        byte_array_tx: List[bytes32] = []
        tx_additions: List[Coin] = []
        tx_removals: List[bytes32] = []
        encoded = None
        if transactions:
            error, npc_list, _ = get_name_puzzle_conditions(transactions)
            additions: List[Coin] = additions_for_npc(npc_list)
            for coin in additions:
                tx_additions.append(coin)
                byte_array_tx.append(bytearray(coin.puzzle_hash))
            for npc in npc_list:
                tx_removals.append(npc.coin_name)
                byte_array_tx.append(bytearray(npc.coin_name))

            bip158: PyBIP158 = PyBIP158(byte_array_tx)
            encoded = bytes(bip158.GetEncoded())

        removal_merkle_set = MerkleSet()
        addition_merkle_set = MerkleSet()

        # Create removal Merkle set
        for coin_name in tx_removals:
            removal_merkle_set.add_already_hashed(coin_name)

        # Create addition Merkle set
        puzzlehash_coin_map: Dict[bytes32, List[Coin]] = {}
        for coin in tx_additions:
            if coin.puzzle_hash in puzzlehash_coin_map:
                puzzlehash_coin_map[coin.puzzle_hash].append(coin)
            else:
                puzzlehash_coin_map[coin.puzzle_hash] = [coin]

        # Addition Merkle set contains puzzlehash and hash of all coins with that puzzlehash
        for puzzle, coins in puzzlehash_coin_map.items():
            addition_merkle_set.add_already_hashed(puzzle)
            addition_merkle_set.add_already_hashed(hash_coin_list(coins))

        additions_root = addition_merkle_set.get_root()
        removal_root = removal_merkle_set.get_root()

        generator_hash = (
            transactions.get_tree_hash()
            if transactions is not None
            else bytes32([0] * 32)
        )
        filter_hash = std_hash(encoded) if encoded is not None else bytes32([0] * 32)

        header_data: HeaderData = HeaderData(
            height,
            prev_header_hash,
            timestamp,
            filter_hash,
            proof_of_space.get_hash(),
            uint128(prev_weight + difficulty),
            uint64(prev_iters + number_iters),
            additions_root,
            removal_root,
            coinbase_coin,
            coinbase_signature,
            fees_coin,
            aggsig,
            cost,
            extension_data,
            generator_hash,
        )

        header_hash_sig: PrependSignature = selected_plot_sk.sign_prepend(
            header_data.get_hash()
        )

        header: Header = Header(header_data, header_hash_sig)

        full_block: FullBlock = FullBlock(
            proof_of_space, proof_of_time, header, transactions, encoded
        )

        return full_block
Beispiel #14
0
    async def test_create_offer_with_zero_val(self, two_wallet_nodes):
        num_blocks = 10
        full_nodes, wallets = two_wallet_nodes
        full_node_1, server_1 = full_nodes[0]
        wallet_node, server_2 = wallets[0]
        wallet_node_2, server_3 = wallets[1]
        wallet = wallet_node.wallet_state_manager.main_wallet
        wallet2 = wallet_node_2.wallet_state_manager.main_wallet

        ph = await wallet.get_new_puzzlehash()
        ph2 = await wallet2.get_new_puzzlehash()

        await server_2.start_client(
            PeerInfo("localhost", uint16(server_1._port)), None)
        await server_3.start_client(
            PeerInfo("localhost", uint16(server_1._port)), None)

        for i in range(1, num_blocks):
            await full_node_1.farm_new_block(FarmNewBlockProtocol(ph))

        funds = sum([
            calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
            for i in range(1, num_blocks - 2)
        ])

        await self.time_out_assert(15, wallet.get_confirmed_balance, funds)

        cc_wallet: CCWallet = await CCWallet.create_new_cc(
            wallet_node.wallet_state_manager, wallet, uint64(100))

        for i in range(1, num_blocks):
            await full_node_1.farm_new_block(FarmNewBlockProtocol(ph))

        await self.time_out_assert(15, cc_wallet.get_unconfirmed_balance, 100)
        await self.time_out_assert(15, cc_wallet.get_confirmed_balance, 100)

        assert cc_wallet.cc_info.my_core is not None
        colour = cc_wallet_puzzles.get_genesis_from_core(
            cc_wallet.cc_info.my_core)

        cc_wallet_2: CCWallet = await CCWallet.create_wallet_for_cc(
            wallet_node_2.wallet_state_manager, wallet2, colour)

        assert cc_wallet.cc_info.my_core == cc_wallet_2.cc_info.my_core

        await full_node_1.farm_new_block(FarmNewBlockProtocol(ph2))
        for i in range(1, num_blocks):
            await full_node_1.farm_new_block(FarmNewBlockProtocol(ph))

        trade_manager_1 = await TradeManager.create(
            wallet_node.wallet_state_manager)
        trade_manager_2 = await TradeManager.create(
            wallet_node_2.wallet_state_manager)

        file = "test_offer_file.offer"
        file_path = Path(file)

        if file_path.exists():
            file_path.unlink()

        offer_dict = {1: -10, 2: 30}

        success, spend_bundle, error = await trade_manager_2.create_offer_for_ids(
            offer_dict)

        assert success is True
        assert spend_bundle is not None
        trade_manager_2.write_offer_to_disk(file_path, spend_bundle)

        success, offer, error = await trade_manager_1.get_discrepancies_for_offer(
            file_path)

        assert error is None
        assert success is True
        assert offer is not None

        assert offer["chia"] == 10
        assert offer[colour] == -30

        success, reason = await trade_manager_1.respond_to_offer(file_path)

        assert success is True

        for i in range(0, num_blocks):
            await full_node_1.farm_new_block(
                FarmNewBlockProtocol(token_bytes()))

        await self.time_out_assert(15, cc_wallet_2.get_confirmed_balance, 30)
        await self.time_out_assert(15, cc_wallet_2.get_confirmed_balance, 30)
Beispiel #15
0
    async def test_cc_spend_uncoloured(self, two_wallet_nodes):
        num_blocks = 10
        full_nodes, wallets = two_wallet_nodes
        full_node_1, server_1 = full_nodes[0]
        wallet_node, server_2 = wallets[0]
        wallet_node_2, server_3 = wallets[1]
        wallet = wallet_node.wallet_state_manager.main_wallet
        wallet2 = wallet_node_2.wallet_state_manager.main_wallet

        ph = await wallet.get_new_puzzlehash()

        await server_2.start_client(
            PeerInfo("localhost", uint16(server_1._port)), None)
        await server_3.start_client(
            PeerInfo("localhost", uint16(server_1._port)), None)

        for i in range(1, num_blocks):
            await full_node_1.farm_new_block(FarmNewBlockProtocol(ph))

        funds = sum([
            calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
            for i in range(1, num_blocks - 2)
        ])

        await self.time_out_assert(15, wallet.get_confirmed_balance, funds)

        cc_wallet: CCWallet = await CCWallet.create_new_cc(
            wallet_node.wallet_state_manager, wallet, uint64(100))

        for i in range(1, num_blocks):
            await full_node_1.farm_new_block(FarmNewBlockProtocol(ph))

        await self.time_out_assert(15, cc_wallet.get_confirmed_balance, 100)
        await self.time_out_assert(15, cc_wallet.get_unconfirmed_balance, 100)

        assert cc_wallet.cc_info.my_core is not None
        colour = cc_wallet_puzzles.get_genesis_from_core(
            cc_wallet.cc_info.my_core)

        cc_wallet_2: CCWallet = await CCWallet.create_wallet_for_cc(
            wallet_node_2.wallet_state_manager, wallet2, colour)

        assert cc_wallet.cc_info.my_core == cc_wallet_2.cc_info.my_core

        cc_2_hash = await cc_wallet_2.get_new_inner_hash()
        await cc_wallet.cc_spend(uint64(60), cc_2_hash)

        for i in range(1, num_blocks):
            await full_node_1.farm_new_block(FarmNewBlockProtocol(ph))

        await self.time_out_assert(15, cc_wallet.get_confirmed_balance, 40)
        await self.time_out_assert(15, cc_wallet.get_unconfirmed_balance, 40)

        await self.time_out_assert(15, cc_wallet_2.get_confirmed_balance, 60)
        await self.time_out_assert(15, cc_wallet_2.get_unconfirmed_balance, 60)

        cc2_ph = await cc_wallet_2.get_new_cc_puzzle_hash()
        spend_bundle = await wallet.wallet_state_manager.main_wallet.generate_signed_transaction(
            10, cc2_ph, 0)
        await wallet.wallet_state_manager.main_wallet.push_transaction(
            spend_bundle)

        for i in range(0, num_blocks):
            await full_node_1.farm_new_block(
                FarmNewBlockProtocol(token_bytes()))

        id = cc_wallet_2.wallet_info.id
        wsm = cc_wallet_2.wallet_state_manager
        await self.time_out_assert(15, wsm.get_confirmed_balance_for_wallet,
                                   70, id)
        await self.time_out_assert(15, cc_wallet_2.get_confirmed_balance, 60)
        await self.time_out_assert(15, cc_wallet_2.get_unconfirmed_balance, 60)
Beispiel #16
0
    async def test_wallet_make_transaction_hop(self,
                                               two_wallet_nodes_five_freeze):
        num_blocks = 10
        full_nodes, wallets = two_wallet_nodes_five_freeze
        full_node_0, full_node_server = full_nodes[0]
        wallet_node_0, wallet_0_server = wallets[0]
        wallet_node_1, wallet_1_server = wallets[1]
        wallet_0 = wallet_node_0.wallet_state_manager.main_wallet
        wallet_1 = wallet_node_1.wallet_state_manager.main_wallet
        ph = await wallet_0.get_new_puzzlehash()

        await wallet_0_server.start_client(
            PeerInfo("localhost", uint16(full_node_server._port)), None)

        await wallet_1_server.start_client(
            PeerInfo("localhost", uint16(full_node_server._port)), None)

        for i in range(0, num_blocks):
            await full_node_0.farm_new_block(FarmNewBlockProtocol(ph))

        funds = sum([
            calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
            for i in range(1, num_blocks - 1)
        ])

        await time_out_assert(5, wallet_0.get_confirmed_balance, funds)
        await time_out_assert(5, wallet_0.get_unconfirmed_balance, funds)

        assert await wallet_0.get_confirmed_balance() == funds
        assert await wallet_0.get_unconfirmed_balance() == funds

        tx = await wallet_0.generate_signed_transaction(
            10,
            await
            wallet_node_1.wallet_state_manager.main_wallet.get_new_puzzlehash(
            ),
            0,
        )

        await wallet_0.push_transaction(tx)

        # Full node height 11, wallet height 9
        await time_out_assert(5, wallet_0.get_confirmed_balance, funds)
        await time_out_assert(5, wallet_0.get_unconfirmed_balance, funds - 10)

        for i in range(0, 4):
            await full_node_0.farm_new_block(
                FarmNewBlockProtocol(token_bytes()))

        new_funds = sum([
            calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
            for i in range(1, num_blocks + 1)
        ])

        # Full node height 17, wallet height 15
        await time_out_assert(5, wallet_0.get_confirmed_balance,
                              new_funds - 10)
        await time_out_assert(5, wallet_0.get_unconfirmed_balance,
                              new_funds - 10)
        await time_out_assert(5, wallet_1.get_confirmed_balance, 10)

        tx = await wallet_1.generate_signed_transaction(
            5, await wallet_0.get_new_puzzlehash(), 0)
        await wallet_1.push_transaction(tx)

        for i in range(0, 4):
            await full_node_0.farm_new_block(
                FarmNewBlockProtocol(token_bytes()))

        await wallet_0.get_confirmed_balance()
        await wallet_0.get_unconfirmed_balance()
        await wallet_1.get_confirmed_balance()

        await time_out_assert(5, wallet_0.get_confirmed_balance, new_funds - 5)
        await time_out_assert(5, wallet_0.get_unconfirmed_balance,
                              new_funds - 5)
        await time_out_assert(5, wallet_1.get_confirmed_balance, 5)
Beispiel #17
0
    async def test_wallet_make_transaction(self, two_wallet_nodes):
        test_rpc_port = uint16(21529)
        num_blocks = 5
        full_nodes, wallets = two_wallet_nodes
        full_node_1, server_1 = full_nodes[0]
        wallet_node, server_2 = wallets[0]
        wallet_node_2, server_3 = wallets[1]
        wallet = wallet_node.wallet_state_manager.main_wallet
        wallet_2 = wallet_node_2.wallet_state_manager.main_wallet
        ph = await wallet.get_new_puzzlehash()
        ph_2 = await wallet_2.get_new_puzzlehash()

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

        for i in range(0, num_blocks):
            await full_node_1.farm_new_block(FarmNewBlockProtocol(ph))

        initial_funds = sum([
            calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
            for i in range(1, num_blocks - 1)
        ])
        initial_funds_eventually = sum([
            calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
            for i in range(1, num_blocks + 1)
        ])

        wallet_rpc_api = WalletRpcApi(wallet_node)

        config = load_config(bt.root_path, "config.yaml")
        hostname = config["self_hostname"]
        daemon_port = config["daemon_port"]

        def stop_node_cb():
            pass

        rpc_cleanup = await start_rpc_server(
            wallet_rpc_api,
            hostname,
            daemon_port,
            test_rpc_port,
            stop_node_cb,
            connect_to_daemon=False,
        )

        await time_out_assert(5, wallet.get_confirmed_balance, initial_funds)
        await time_out_assert(5, wallet.get_unconfirmed_balance, initial_funds)

        client = await WalletRpcClient.create("localhost", test_rpc_port)
        try:
            addr = encode_puzzle_hash(await wallet_node_2.wallet_state_manager.
                                      main_wallet.get_new_puzzlehash())
            tx_amount = 15600000
            try:
                await client.send_transaction("1", 100000000000000000, addr)
                raise Exception("Should not create high value tx")
            except ValueError:
                pass

            tx = await client.send_transaction("1", tx_amount, addr)
            transaction_id = tx.name()

            async def tx_in_mempool():
                tx = await client.get_transaction("1", transaction_id)
                return tx.is_in_mempool()

            await time_out_assert(5, tx_in_mempool, True)
            await time_out_assert(5, wallet.get_unconfirmed_balance,
                                  initial_funds - tx_amount)
            assert (
                await client.get_wallet_balance("1")
            )["unconfirmed_wallet_balance"] == initial_funds - tx_amount
            assert (await client.get_wallet_balance("1")
                    )["confirmed_wallet_balance"] == initial_funds

            for i in range(0, 5):
                await client.farm_block(encode_puzzle_hash(ph_2))
                await asyncio.sleep(1)

            async def eventual_balance():
                return (
                    await
                    client.get_wallet_balance("1"))["confirmed_wallet_balance"]

            await time_out_assert(5, eventual_balance,
                                  initial_funds_eventually - tx_amount)

            address = await client.get_next_address("1")
            assert len(address) > 10

            transactions = await client.get_transactions("1")
            assert len(transactions) > 1

            pks = await client.get_public_keys()
            assert len(pks) == 1

            assert (await client.get_height_info()) > 0

            sk_dict = await client.get_private_key(pks[0])
            assert sk_dict["fingerprint"] == pks[0]
            assert sk_dict["sk"] is not None
            assert sk_dict["pk"] is not None
            assert sk_dict["seed"] is not None

            mnemonic = await client.generate_mnemonic()
            assert len(mnemonic) == 24

            await client.add_key(mnemonic)

            pks = await client.get_public_keys()
            assert len(pks) == 2

            await client.log_in_and_skip(pks[1])
            sk_dict = await client.get_private_key(pks[1])
            assert sk_dict["fingerprint"] == pks[1]

            await client.delete_key(pks[0])
            await client.log_in_and_skip(pks[1])
            assert len(await client.get_public_keys()) == 1

            assert not (await client.get_sync_status())

            wallets = await client.get_wallets()
            assert len(wallets) == 1
            balance = await client.get_wallet_balance(wallets[0]["id"])
            assert balance["unconfirmed_wallet_balance"] == 0

            test_wallet_backup_path = Path("test_wallet_backup_file")
            await client.create_backup(test_wallet_backup_path)
            assert test_wallet_backup_path.exists()
            test_wallet_backup_path.unlink()

            try:
                await client.send_transaction(wallets[0]["id"], 100, addr)
                raise Exception("Should not create tx if no balance")
            except ValueError:
                pass

            await client.delete_all_keys()

            assert len(await client.get_public_keys()) == 0
        except Exception:
            # Checks that the RPC manages to stop the node
            client.close()
            await client.await_closed()
            await rpc_cleanup()
            raise

        client.close()
        await client.await_closed()
        await rpc_cleanup()
Beispiel #18
0
    async def test_wallet_make_transaction_with_fee(self, two_wallet_nodes):
        num_blocks = 10
        full_nodes, wallets = two_wallet_nodes
        full_node_1, server_1 = full_nodes[0]
        wallet_node, server_2 = wallets[0]
        wallet_node_2, server_3 = wallets[1]
        wallet = wallet_node.wallet_state_manager.main_wallet
        ph = await wallet.get_new_puzzlehash()

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

        for i in range(0, num_blocks):
            await full_node_1.farm_new_block(FarmNewBlockProtocol(ph))

        funds = sum([
            calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
            for i in range(1, num_blocks - 1)
        ])

        await asyncio.sleep(2)

        assert await wallet.get_confirmed_balance() == funds
        assert await wallet.get_unconfirmed_balance() == funds
        tx_amount = 32000000000000
        tx_fee = 10
        tx = await wallet.generate_signed_transaction(
            tx_amount,
            await
            wallet_node_2.wallet_state_manager.main_wallet.get_new_puzzlehash(
            ),
            tx_fee,
        )

        fees = tx.spend_bundle.fees()
        assert fees == tx_fee

        await wallet.push_transaction(tx)

        await asyncio.sleep(2)
        confirmed_balance = await wallet.get_confirmed_balance()
        unconfirmed_balance = await wallet.get_unconfirmed_balance()

        assert confirmed_balance == funds
        assert unconfirmed_balance == funds - tx_amount - tx_fee

        for i in range(0, num_blocks):
            await full_node_1.farm_new_block(
                FarmNewBlockProtocol(token_bytes()))

        await asyncio.sleep(2)

        new_funds = sum([
            calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
            for i in range(1, num_blocks + 1)
        ])

        confirmed_balance = await wallet.get_confirmed_balance()
        unconfirmed_balance = await wallet.get_unconfirmed_balance()

        assert confirmed_balance == new_funds - tx_amount - tx_fee
        assert unconfirmed_balance == new_funds - tx_amount - tx_fee
    async def test_cc_spend(self, two_wallet_nodes):
        num_blocks = 8
        full_nodes, wallets = two_wallet_nodes
        full_node_1, server_1 = full_nodes[0]
        wallet_node, server_2 = wallets[0]
        wallet_node_2, server_3 = wallets[1]
        wallet = wallet_node.wallet_state_manager.main_wallet
        wallet2 = wallet_node_2.wallet_state_manager.main_wallet

        ph = await wallet.get_new_puzzlehash()

        await server_2.start_client(PeerInfo("localhost", uint16(server_1._port)), None)
        await server_3.start_client(PeerInfo("localhost", uint16(server_1._port)), None)

        for i in range(1, 4):
            await full_node_1.farm_new_block(FarmNewBlockProtocol(ph))

        funds = sum(
            [
                calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
                for i in range(1, 4 - 2)
            ]
        )

        await time_out_assert(15, wallet.get_confirmed_balance, funds)

        cc_wallet: CCWallet = await CCWallet.create_new_cc(
            wallet_node.wallet_state_manager, wallet, uint64(100)
        )

        for i in range(1, num_blocks):
            await full_node_1.farm_new_block(FarmNewBlockProtocol(ph))

        await time_out_assert(15, cc_wallet.get_confirmed_balance, 100)
        await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 100)

        assert cc_wallet.cc_info.my_core is not None
        colour = cc_wallet_puzzles.get_genesis_from_core(cc_wallet.cc_info.my_core)

        cc_wallet_2: CCWallet = await CCWallet.create_wallet_for_cc(
            wallet_node_2.wallet_state_manager, wallet2, colour
        )

        assert cc_wallet.cc_info.my_core == cc_wallet_2.cc_info.my_core

        cc_2_hash = await cc_wallet_2.get_new_inner_hash()
        tx_record = await cc_wallet.generate_signed_transaction(uint64(60), cc_2_hash)
        await wallet.wallet_state_manager.add_pending_transaction(tx_record)

        for i in range(1, num_blocks):
            await full_node_1.farm_new_block(FarmNewBlockProtocol(ph))

        await time_out_assert(15, cc_wallet.get_confirmed_balance, 40)
        await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 40)

        await time_out_assert(30, cc_wallet_2.get_confirmed_balance, 60)
        await time_out_assert(30, cc_wallet_2.get_unconfirmed_balance, 60)

        cc_hash = await cc_wallet.get_new_inner_hash()
        tx_record = await cc_wallet_2.generate_signed_transaction(uint64(15), cc_hash)
        await wallet.wallet_state_manager.add_pending_transaction(tx_record)
        for i in range(1, num_blocks):
            await full_node_1.farm_new_block(FarmNewBlockProtocol(ph))

        await time_out_assert(15, cc_wallet.get_confirmed_balance, 55)
        await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 55)
    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_0, server_0 = full_nodes[0]
        full_node_1, server_1 = full_nodes[1]
        full_node_2, server_2 = full_nodes[2]

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

        # wallet0 <-> sever0 <-> server1

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

        for i in range(1, num_blocks):
            await full_node_0.farm_new_block(FarmNewBlockProtocol(ph))

        all_blocks = await full_node_0.get_current_blocks(
            full_node_0.get_tip())

        for block in all_blocks:
            async for _ in full_node_2.respond_block(
                    full_node_protocol.RespondBlock(block)):
                pass

        funds = sum([
            calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
            for i in range(1, num_blocks - 2)
        ])
        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_0.mempool_manager.get_spendbundle,
                              tx.spend_bundle, tx.name())
        await time_out_assert(10, full_node_1.mempool_manager.get_spendbundle,
                              tx.spend_bundle, tx.name())
        await time_out_assert(10, full_node_2.mempool_manager.get_spendbundle,
                              None, tx.name())

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

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

        await time_out_assert(10, full_node_0.mempool_manager.get_spendbundle,
                              tx.spend_bundle, tx.name())
        await time_out_assert(10, full_node_1.mempool_manager.get_spendbundle,
                              tx.spend_bundle, tx.name())
        await time_out_assert(10, full_node_2.mempool_manager.get_spendbundle,
                              tx.spend_bundle, tx.name())
Beispiel #21
0
    def _create_block(
            self,
            test_constants: ConsensusConstants,
            challenge_hash: bytes32,
            height: uint32,
            prev_header_hash: bytes32,
            prev_iters: uint64,
            prev_weight: uint128,
            timestamp: uint64,
            difficulty: int,
            min_iters: int,
            seed: bytes,
            genesis: bool = False,
            reward_puzzlehash: bytes32 = None,
            transactions: Program = None,
            aggsig: G2Element = None,
            fees: uint64 = uint64(0),
    ) -> FullBlock:
        """
        Creates a block with the specified details. Uses the stored plots to create a proof of space,
        and also evaluates the VDF for the proof of time.
        """
        selected_plot_info = None
        selected_proof_index = 0
        selected_quality: Optional[bytes] = None
        best_quality = 0
        plots = [
            pinfo for _, pinfo in sorted(list(self.plots.items()),
                                         key=lambda x: str(x[0]))
        ]
        if self.use_any_pos:
            random.seed(seed)
            for i in range(len(plots) * 3):
                # Allow passing in seed, to create reorgs and different chains
                seeded_pn = random.randint(0, len(plots) - 1)
                plot_info = plots[seeded_pn]
                plot_id = plot_info.prover.get_id()
                ccp = ProofOfSpace.can_create_proof(
                    plot_id,
                    challenge_hash,
                    test_constants.NUMBER_ZERO_BITS_CHALLENGE_SIG,
                )
                if not ccp:
                    continue
                qualities = plot_info.prover.get_qualities_for_challenge(
                    challenge_hash)
                if len(qualities) > 0:
                    selected_plot_info = plot_info
                    selected_quality = qualities[0]
                    break
        else:
            for i in range(len(plots)):
                plot_info = plots[i]
                j = 0
                plot_id = plot_info.prover.get_id()
                ccp = ProofOfSpace.can_create_proof(
                    plot_id,
                    challenge_hash,
                    test_constants.NUMBER_ZERO_BITS_CHALLENGE_SIG,
                )
                if not ccp:
                    continue
                qualities = plot_info.prover.get_qualities_for_challenge(
                    challenge_hash)
                for quality in qualities:
                    qual_int = int.from_bytes(quality, "big", signed=False)
                    if qual_int > best_quality:
                        best_quality = qual_int
                        selected_quality = quality
                        selected_plot_info = plot_info
                        selected_proof_index = j
                    j += 1

        assert selected_plot_info is not None
        if selected_quality is None:
            raise RuntimeError("No proofs for this challenge")

        proof_xs: bytes = selected_plot_info.prover.get_full_proof(
            challenge_hash, selected_proof_index)

        plot_pk = ProofOfSpace.generate_plot_public_key(
            selected_plot_info.local_sk.get_g1(),
            selected_plot_info.farmer_public_key,
        )
        proof_of_space: ProofOfSpace = ProofOfSpace(
            challenge_hash,
            selected_plot_info.pool_public_key,
            plot_pk,
            selected_plot_info.prover.get_size(),
            proof_xs,
        )

        number_iters: uint64 = pot_iterations.calculate_iterations(
            proof_of_space,
            difficulty,
            min_iters,
            test_constants.NUMBER_ZERO_BITS_CHALLENGE_SIG,
        )
        if self.real_plots:
            print(f"Performing {number_iters} VDF iterations")

        int_size = (test_constants.DISCRIMINANT_SIZE_BITS + 16) >> 4

        result = prove(challenge_hash, test_constants.DISCRIMINANT_SIZE_BITS,
                       number_iters)

        output = ClassgroupElement(
            int512(int.from_bytes(
                result[0:int_size],
                "big",
                signed=True,
            )),
            int512(
                int.from_bytes(
                    result[int_size:2 * int_size],
                    "big",
                    signed=True,
                )),
        )
        proof_bytes = result[2 * int_size:4 * int_size]

        proof_of_time = ProofOfTime(
            challenge_hash,
            number_iters,
            output,
            uint8(0),
            proof_bytes,
        )

        # Use the extension data to create different blocks based on header hash
        extension_data: bytes32 = bytes32(
            [random.randint(0, 255) for _ in range(32)])
        cost = uint64(0)

        fee_reward = uint64(block_rewards.calculate_base_fee(height) + fees)

        std_hash(std_hash(height))

        # Create filter
        byte_array_tx: List[bytes32] = []
        tx_additions: List[Coin] = []
        tx_removals: List[bytes32] = []
        if transactions:
            error, npc_list, _ = get_name_puzzle_conditions(transactions)
            additions: List[Coin] = additions_for_npc(npc_list)
            for coin in additions:
                tx_additions.append(coin)
                byte_array_tx.append(bytearray(coin.puzzle_hash))
            for npc in npc_list:
                tx_removals.append(npc.coin_name)
                byte_array_tx.append(bytearray(npc.coin_name))
        farmer_ph = self.farmer_ph
        pool_ph = self.pool_ph
        if reward_puzzlehash is not None:
            farmer_ph = reward_puzzlehash
            pool_ph = reward_puzzlehash

        byte_array_tx.append(bytearray(farmer_ph))
        byte_array_tx.append(bytearray(pool_ph))
        bip158: PyBIP158 = PyBIP158(byte_array_tx)
        encoded = bytes(bip158.GetEncoded())

        removal_merkle_set = MerkleSet()
        addition_merkle_set = MerkleSet()

        # Create removal Merkle set
        for coin_name in tx_removals:
            removal_merkle_set.add_already_hashed(coin_name)

        # Create addition Merkle set
        puzzlehash_coin_map: Dict[bytes32, List[Coin]] = {}
        cb_reward = calculate_block_reward(height)
        cb_coin = create_coinbase_coin(height, pool_ph, cb_reward)
        fees_coin = create_fees_coin(height, farmer_ph, fee_reward)
        for coin in tx_additions + [cb_coin, fees_coin]:
            if coin.puzzle_hash in puzzlehash_coin_map:
                puzzlehash_coin_map[coin.puzzle_hash].append(coin)
            else:
                puzzlehash_coin_map[coin.puzzle_hash] = [coin]

        # Addition Merkle set contains puzzlehash and hash of all coins with that puzzlehash
        for puzzle, coins in puzzlehash_coin_map.items():
            addition_merkle_set.add_already_hashed(puzzle)
            addition_merkle_set.add_already_hashed(hash_coin_list(coins))

        additions_root = addition_merkle_set.get_root()
        removal_root = removal_merkle_set.get_root()

        generator_hash = (transactions.get_tree_hash()
                          if transactions is not None else bytes32([0] * 32))
        filter_hash = std_hash(encoded)

        pool_target = PoolTarget(pool_ph, uint32(height))
        pool_target_signature = self.get_pool_key_signature(
            pool_target, proof_of_space.pool_public_key)
        assert pool_target_signature is not None
        final_aggsig: G2Element = pool_target_signature
        if aggsig is not None:
            final_aggsig = AugSchemeMPL.aggregate([final_aggsig, aggsig])

        header_data: HeaderData = HeaderData(
            height,
            prev_header_hash,
            timestamp,
            filter_hash,
            proof_of_space.get_hash(),
            uint128(prev_weight + difficulty),
            uint64(prev_iters + number_iters),
            additions_root,
            removal_root,
            farmer_ph,
            fee_reward,
            pool_target,
            final_aggsig,
            cost,
            extension_data,
            generator_hash,
        )

        header_hash_sig: G2Element = self.get_plot_signature(
            header_data, plot_pk)

        header: Header = Header(header_data, header_hash_sig)

        full_block: FullBlock = FullBlock(proof_of_space, proof_of_time,
                                          header, transactions, encoded)

        return full_block
    async def test_tx_propagation(self, three_nodes_two_wallets):
        num_blocks = 5
        full_nodes, wallets = three_nodes_two_wallets

        wallet_0, wallet_server_0 = wallets[0]
        wallet_1, wallet_server_1 = wallets[1]
        full_node_0, server_0 = full_nodes[0]
        full_node_1, server_1 = full_nodes[1]
        full_node_2, server_2 = full_nodes[2]

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

        #
        # wallet0 <-> sever0 <-> server1 <-> server2 <-> wallet1
        #
        await wallet_server_0.start_client(
            PeerInfo("localhost", uint16(server_0._port)), None)
        await server_0.start_client(
            PeerInfo("localhost", uint16(server_1._port)), None)
        await server_1.start_client(
            PeerInfo("localhost", uint16(server_2._port)), None)
        await wallet_server_1.start_client(
            PeerInfo("localhost", uint16(server_2._port)), None)

        for i in range(1, num_blocks):
            await full_node_0.farm_new_block(FarmNewBlockProtocol(ph))

        funds = sum([
            calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i))
            for i in range(1, num_blocks - 2)
        ])
        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, ph1, 0))
        await wallet_0.wallet_state_manager.main_wallet.push_transaction(tx)

        await time_out_assert(10, full_node_0.mempool_manager.get_spendbundle,
                              tx.spend_bundle, tx.name())
        await time_out_assert(10, full_node_1.mempool_manager.get_spendbundle,
                              tx.spend_bundle, tx.name())
        await time_out_assert(10, full_node_2.mempool_manager.get_spendbundle,
                              tx.spend_bundle, tx.name())

        # Farm another block
        for i in range(1, 8):
            await full_node_1.farm_new_block(
                FarmNewBlockProtocol(token_bytes()))
        funds = sum([
            calculate_base_fee(uint32(i)) + calculate_block_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 - 10),
        )
        await time_out_assert(
            15,
            wallet_1.wallet_state_manager.main_wallet.get_confirmed_balance,
            (10))