mirror of
https://github.com/Chia-Network/chia-blockchain.git
synced 2024-09-21 00:24:37 +03:00
cf1a328e03
* Implement `test_cat_creation_unique_lineage_store()` Make sure creating CAT wallets leads to unique lineage stores. * Fix `CATLineageStore` creation in `create_new_cat_wallet` We currently create the `CATLineageStore` before the new asset id exists which leads to all CATs created by `create_new_cat_wallet` using the same lineage store table: `lineage_proofs_0000000000000000000000000000000000000000`. * Create `CATLineageStore` in `generate_issuance_bundle`
800 lines
36 KiB
Python
800 lines
36 KiB
Python
import asyncio
|
|
from typing import List
|
|
|
|
import pytest
|
|
|
|
from chia.consensus.block_rewards import calculate_base_farmer_reward, calculate_pool_reward
|
|
from chia.full_node.mempool_manager import MempoolManager
|
|
from chia.simulator.simulator_protocol import FarmNewBlockProtocol
|
|
from chia.types.blockchain_format.coin import Coin
|
|
from chia.types.blockchain_format.sized_bytes import bytes32
|
|
from chia.types.peer_info import PeerInfo
|
|
from chia.util.ints import uint16, uint32, uint64
|
|
from chia.wallet.cat_wallet.cat_constants import DEFAULT_CATS
|
|
from chia.wallet.cat_wallet.cat_info import LegacyCATInfo
|
|
from chia.wallet.cat_wallet.cat_utils import construct_cat_puzzle
|
|
from chia.wallet.cat_wallet.cat_wallet import CATWallet
|
|
from chia.wallet.puzzles.cat_loader import CAT_MOD
|
|
from chia.wallet.transaction_record import TransactionRecord
|
|
from chia.wallet.wallet_info import WalletInfo
|
|
from tests.pools.test_pool_rpc import wallet_is_synced
|
|
from tests.time_out_assert import time_out_assert
|
|
|
|
|
|
async def tx_in_pool(mempool: MempoolManager, tx_id: bytes32):
|
|
tx = mempool.get_spendbundle(tx_id)
|
|
if tx is None:
|
|
return False
|
|
return True
|
|
|
|
|
|
class TestCATWallet:
|
|
@pytest.mark.parametrize(
|
|
"trusted",
|
|
[True, False],
|
|
)
|
|
@pytest.mark.asyncio
|
|
async def test_cat_creation(self, self_hostname, two_wallet_nodes, trusted):
|
|
num_blocks = 3
|
|
full_nodes, wallets = two_wallet_nodes
|
|
full_node_api = full_nodes[0]
|
|
full_node_server = full_node_api.server
|
|
wallet_node, server_2 = wallets[0]
|
|
wallet = wallet_node.wallet_state_manager.main_wallet
|
|
|
|
ph = await wallet.get_new_puzzlehash()
|
|
if trusted:
|
|
wallet_node.config["trusted_peers"] = {full_node_server.node_id.hex(): full_node_server.node_id.hex()}
|
|
else:
|
|
wallet_node.config["trusted_peers"] = {}
|
|
|
|
await server_2.start_client(PeerInfo(self_hostname, uint16(full_node_server._port)), None)
|
|
for i in range(0, num_blocks):
|
|
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
|
|
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(32 * b"0"))
|
|
|
|
funds = sum(
|
|
[
|
|
calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i))
|
|
for i in range(1, num_blocks + 1)
|
|
]
|
|
)
|
|
|
|
await time_out_assert(15, wallet.get_confirmed_balance, funds)
|
|
await time_out_assert(10, wallet_is_synced, True, wallet_node, full_node_api)
|
|
|
|
async with wallet_node.wallet_state_manager.lock:
|
|
cat_wallet: CATWallet = await CATWallet.create_new_cat_wallet(
|
|
wallet_node.wallet_state_manager, wallet, {"identifier": "genesis_by_id"}, uint64(100)
|
|
)
|
|
# The next 2 lines are basically a noop, it just adds test coverage
|
|
cat_wallet = await CATWallet.create(wallet_node.wallet_state_manager, wallet, cat_wallet.wallet_info)
|
|
await wallet_node.wallet_state_manager.add_new_wallet(cat_wallet, cat_wallet.id())
|
|
|
|
tx_queue: List[TransactionRecord] = await wallet_node.wallet_state_manager.tx_store.get_not_sent()
|
|
tx_record = tx_queue[0]
|
|
await time_out_assert(
|
|
15, tx_in_pool, True, full_node_api.full_node.mempool_manager, tx_record.spend_bundle.name()
|
|
)
|
|
|
|
for i in range(1, num_blocks):
|
|
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(32 * b"0"))
|
|
|
|
await time_out_assert(15, cat_wallet.get_confirmed_balance, 100)
|
|
await time_out_assert(15, cat_wallet.get_spendable_balance, 100)
|
|
await time_out_assert(15, cat_wallet.get_unconfirmed_balance, 100)
|
|
|
|
# Test migration
|
|
all_lineage = await cat_wallet.lineage_store.get_all_lineage_proofs()
|
|
current_info = cat_wallet.wallet_info
|
|
data_str = bytes(
|
|
LegacyCATInfo(
|
|
cat_wallet.cat_info.limitations_program_hash, cat_wallet.cat_info.my_tail, list(all_lineage.items())
|
|
)
|
|
).hex()
|
|
wallet_info = WalletInfo(current_info.id, current_info.name, current_info.type, data_str)
|
|
new_cat_wallet = await CATWallet.create(wallet_node.wallet_state_manager, wallet, wallet_info)
|
|
assert new_cat_wallet.cat_info.limitations_program_hash == cat_wallet.cat_info.limitations_program_hash
|
|
assert new_cat_wallet.cat_info.my_tail == cat_wallet.cat_info.my_tail
|
|
assert await cat_wallet.lineage_store.get_all_lineage_proofs() == all_lineage
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_cat_creation_unique_lineage_store(self, self_hostname, two_wallet_nodes):
|
|
num_blocks = 3
|
|
full_nodes, wallets = two_wallet_nodes
|
|
full_node_api = full_nodes[0]
|
|
full_node_server = full_node_api.server
|
|
wallet_node, wallet_server = wallets[0]
|
|
wallet = wallet_node.wallet_state_manager.main_wallet
|
|
ph = await wallet.get_new_puzzlehash()
|
|
wallet_node.config["trusted_peers"] = {full_node_server.node_id.hex(): full_node_server.node_id.hex()}
|
|
|
|
await wallet_server.start_client(PeerInfo(self_hostname, uint16(full_node_server._port)), None)
|
|
for i in range(0, num_blocks):
|
|
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
|
|
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(32 * b"0"))
|
|
|
|
funds = sum(
|
|
[
|
|
calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i))
|
|
for i in range(1, num_blocks + 1)
|
|
]
|
|
)
|
|
|
|
await time_out_assert(15, wallet.get_confirmed_balance, funds)
|
|
await time_out_assert(10, wallet_is_synced, True, wallet_node, full_node_api)
|
|
|
|
async with wallet_node.wallet_state_manager.lock:
|
|
cat_wallet_1: CATWallet = await CATWallet.create_new_cat_wallet(
|
|
wallet_node.wallet_state_manager, wallet, {"identifier": "genesis_by_id"}, uint64(100)
|
|
)
|
|
cat_wallet_2: CATWallet = await CATWallet.create_new_cat_wallet(
|
|
wallet_node.wallet_state_manager, wallet, {"identifier": "genesis_by_id"}, uint64(200)
|
|
)
|
|
|
|
proofs_1 = await cat_wallet_1.lineage_store.get_all_lineage_proofs()
|
|
proofs_2 = await cat_wallet_2.lineage_store.get_all_lineage_proofs()
|
|
assert len(proofs_1) == len(proofs_2)
|
|
assert proofs_1 != proofs_2
|
|
assert cat_wallet_1.lineage_store.table_name != cat_wallet_2.lineage_store.table_name
|
|
|
|
@pytest.mark.parametrize(
|
|
"trusted",
|
|
[True, False],
|
|
)
|
|
@pytest.mark.asyncio
|
|
async def test_cat_spend(self, self_hostname, two_wallet_nodes, trusted):
|
|
num_blocks = 3
|
|
full_nodes, wallets = two_wallet_nodes
|
|
full_node_api = full_nodes[0]
|
|
full_node_server = full_node_api.server
|
|
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()
|
|
if trusted:
|
|
wallet_node.config["trusted_peers"] = {full_node_server.node_id.hex(): full_node_server.node_id.hex()}
|
|
wallet_node_2.config["trusted_peers"] = {full_node_server.node_id.hex(): full_node_server.node_id.hex()}
|
|
else:
|
|
wallet_node.config["trusted_peers"] = {}
|
|
wallet_node_2.config["trusted_peers"] = {}
|
|
await server_2.start_client(PeerInfo(self_hostname, uint16(full_node_server._port)), None)
|
|
await server_3.start_client(PeerInfo(self_hostname, uint16(full_node_server._port)), None)
|
|
|
|
for i in range(0, num_blocks):
|
|
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
|
|
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(32 * b"0"))
|
|
|
|
funds = sum(
|
|
[
|
|
calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i))
|
|
for i in range(1, num_blocks + 1)
|
|
]
|
|
)
|
|
|
|
await time_out_assert(15, wallet.get_confirmed_balance, funds)
|
|
|
|
async with wallet_node.wallet_state_manager.lock:
|
|
cat_wallet: CATWallet = await CATWallet.create_new_cat_wallet(
|
|
wallet_node.wallet_state_manager, wallet, {"identifier": "genesis_by_id"}, uint64(100)
|
|
)
|
|
tx_queue: List[TransactionRecord] = await wallet_node.wallet_state_manager.tx_store.get_not_sent()
|
|
tx_record = tx_queue[0]
|
|
await time_out_assert(
|
|
15, tx_in_pool, True, full_node_api.full_node.mempool_manager, tx_record.spend_bundle.name()
|
|
)
|
|
|
|
for i in range(1, num_blocks):
|
|
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(32 * b"0"))
|
|
|
|
await time_out_assert(15, cat_wallet.get_confirmed_balance, 100)
|
|
await time_out_assert(15, cat_wallet.get_unconfirmed_balance, 100)
|
|
|
|
assert cat_wallet.cat_info.limitations_program_hash is not None
|
|
asset_id = cat_wallet.get_asset_id()
|
|
|
|
cat_wallet_2: CATWallet = await CATWallet.create_wallet_for_cat(
|
|
wallet_node_2.wallet_state_manager, wallet2, asset_id
|
|
)
|
|
|
|
assert cat_wallet.cat_info.limitations_program_hash == cat_wallet_2.cat_info.limitations_program_hash
|
|
|
|
cat_2_hash = await cat_wallet_2.get_new_inner_hash()
|
|
tx_records = await cat_wallet.generate_signed_transaction([uint64(60)], [cat_2_hash], fee=uint64(1))
|
|
for tx_record in tx_records:
|
|
await wallet.wallet_state_manager.add_pending_transaction(tx_record)
|
|
if tx_record.spend_bundle is not None:
|
|
await time_out_assert(
|
|
15, tx_in_pool, True, full_node_api.full_node.mempool_manager, tx_record.spend_bundle.name()
|
|
)
|
|
if tx_record.wallet_id is cat_wallet.id():
|
|
assert tx_record.to_puzzle_hash == cat_2_hash
|
|
|
|
await time_out_assert(15, cat_wallet.get_pending_change_balance, 40)
|
|
|
|
for i in range(1, num_blocks):
|
|
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(32 * b"\0"))
|
|
|
|
await time_out_assert(30, wallet.get_confirmed_balance, funds - 101)
|
|
|
|
await time_out_assert(15, cat_wallet.get_confirmed_balance, 40)
|
|
await time_out_assert(15, cat_wallet.get_unconfirmed_balance, 40)
|
|
|
|
await time_out_assert(30, cat_wallet_2.get_confirmed_balance, 60)
|
|
await time_out_assert(30, cat_wallet_2.get_unconfirmed_balance, 60)
|
|
|
|
cat_hash = await cat_wallet.get_new_inner_hash()
|
|
tx_records = await cat_wallet_2.generate_signed_transaction([uint64(15)], [cat_hash])
|
|
for tx_record in tx_records:
|
|
await wallet.wallet_state_manager.add_pending_transaction(tx_record)
|
|
await time_out_assert(
|
|
15, tx_in_pool, True, full_node_api.full_node.mempool_manager, tx_record.spend_bundle.name()
|
|
)
|
|
|
|
for i in range(1, num_blocks):
|
|
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
|
|
|
|
await time_out_assert(15, cat_wallet.get_confirmed_balance, 55)
|
|
await time_out_assert(15, cat_wallet.get_unconfirmed_balance, 55)
|
|
|
|
@pytest.mark.parametrize(
|
|
"trusted",
|
|
[True, False],
|
|
)
|
|
@pytest.mark.asyncio
|
|
async def test_get_wallet_for_asset_id(self, self_hostname, two_wallet_nodes, trusted):
|
|
num_blocks = 3
|
|
full_nodes, wallets = two_wallet_nodes
|
|
full_node_api = full_nodes[0]
|
|
full_node_server = full_node_api.server
|
|
wallet_node, server_2 = wallets[0]
|
|
wallet = wallet_node.wallet_state_manager.main_wallet
|
|
|
|
ph = await wallet.get_new_puzzlehash()
|
|
if trusted:
|
|
wallet_node.config["trusted_peers"] = {full_node_server.node_id.hex(): full_node_server.node_id.hex()}
|
|
else:
|
|
wallet_node.config["trusted_peers"] = {}
|
|
await server_2.start_client(PeerInfo(self_hostname, uint16(full_node_server._port)), None)
|
|
|
|
for i in range(0, num_blocks):
|
|
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
|
|
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(32 * b"0"))
|
|
|
|
funds = sum(
|
|
[
|
|
calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i))
|
|
for i in range(1, num_blocks + 1)
|
|
]
|
|
)
|
|
|
|
await time_out_assert(15, wallet.get_confirmed_balance, funds)
|
|
|
|
async with wallet_node.wallet_state_manager.lock:
|
|
cat_wallet: CATWallet = await CATWallet.create_new_cat_wallet(
|
|
wallet_node.wallet_state_manager, wallet, {"identifier": "genesis_by_id"}, uint64(100)
|
|
)
|
|
|
|
for i in range(1, num_blocks):
|
|
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(32 * b"0"))
|
|
|
|
asset_id = cat_wallet.get_asset_id()
|
|
await cat_wallet.set_tail_program(bytes(cat_wallet.cat_info.my_tail).hex())
|
|
assert await wallet_node.wallet_state_manager.get_wallet_for_asset_id(asset_id) == cat_wallet
|
|
|
|
# Test that the a default CAT will initialize correctly
|
|
asset = DEFAULT_CATS[next(iter(DEFAULT_CATS))]
|
|
asset_id = asset["asset_id"]
|
|
cat_wallet_2 = await CATWallet.create_wallet_for_cat(wallet_node.wallet_state_manager, wallet, asset_id)
|
|
assert await cat_wallet_2.get_name() == asset["name"]
|
|
await cat_wallet_2.set_name("Test Name")
|
|
assert await cat_wallet_2.get_name() == "Test Name"
|
|
|
|
@pytest.mark.parametrize(
|
|
"trusted",
|
|
[True, False],
|
|
)
|
|
@pytest.mark.asyncio
|
|
async def test_cat_doesnt_see_eve(self, self_hostname, two_wallet_nodes, trusted):
|
|
num_blocks = 3
|
|
full_nodes, wallets = two_wallet_nodes
|
|
full_node_api = full_nodes[0]
|
|
full_node_server = full_node_api.server
|
|
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()
|
|
if trusted:
|
|
wallet_node.config["trusted_peers"] = {full_node_server.node_id.hex(): full_node_server.node_id.hex()}
|
|
wallet_node_2.config["trusted_peers"] = {full_node_server.node_id.hex(): full_node_server.node_id.hex()}
|
|
else:
|
|
wallet_node.config["trusted_peers"] = {}
|
|
wallet_node_2.config["trusted_peers"] = {}
|
|
await server_2.start_client(PeerInfo(self_hostname, uint16(full_node_server._port)), None)
|
|
await server_3.start_client(PeerInfo(self_hostname, uint16(full_node_server._port)), None)
|
|
|
|
for i in range(0, num_blocks):
|
|
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
|
|
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(32 * b"0"))
|
|
|
|
funds = sum(
|
|
[
|
|
calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i))
|
|
for i in range(1, num_blocks + 1)
|
|
]
|
|
)
|
|
|
|
await time_out_assert(15, wallet.get_confirmed_balance, funds)
|
|
|
|
async with wallet_node.wallet_state_manager.lock:
|
|
cat_wallet: CATWallet = await CATWallet.create_new_cat_wallet(
|
|
wallet_node.wallet_state_manager, wallet, {"identifier": "genesis_by_id"}, uint64(100)
|
|
)
|
|
tx_queue: List[TransactionRecord] = await wallet_node.wallet_state_manager.tx_store.get_not_sent()
|
|
tx_record = tx_queue[0]
|
|
await time_out_assert(
|
|
15, tx_in_pool, True, full_node_api.full_node.mempool_manager, tx_record.spend_bundle.name()
|
|
)
|
|
for i in range(1, num_blocks):
|
|
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(32 * b"0"))
|
|
|
|
await time_out_assert(15, cat_wallet.get_confirmed_balance, 100)
|
|
await time_out_assert(15, cat_wallet.get_unconfirmed_balance, 100)
|
|
|
|
assert cat_wallet.cat_info.limitations_program_hash is not None
|
|
asset_id = cat_wallet.get_asset_id()
|
|
|
|
cat_wallet_2: CATWallet = await CATWallet.create_wallet_for_cat(
|
|
wallet_node_2.wallet_state_manager, wallet2, asset_id
|
|
)
|
|
|
|
assert cat_wallet.cat_info.limitations_program_hash == cat_wallet_2.cat_info.limitations_program_hash
|
|
|
|
cat_2_hash = await cat_wallet_2.get_new_inner_hash()
|
|
tx_records = await cat_wallet.generate_signed_transaction([uint64(60)], [cat_2_hash], fee=uint64(1))
|
|
for tx_record in tx_records:
|
|
await wallet.wallet_state_manager.add_pending_transaction(tx_record)
|
|
if tx_record.spend_bundle is not None:
|
|
await time_out_assert(
|
|
15, tx_in_pool, True, full_node_api.full_node.mempool_manager, tx_record.spend_bundle.name()
|
|
)
|
|
for i in range(1, num_blocks):
|
|
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(32 * b"0"))
|
|
|
|
await time_out_assert(30, wallet.get_confirmed_balance, funds - 101)
|
|
await time_out_assert(30, wallet.get_unconfirmed_balance, funds - 101)
|
|
|
|
await time_out_assert(15, cat_wallet.get_confirmed_balance, 40)
|
|
await time_out_assert(15, cat_wallet.get_unconfirmed_balance, 40)
|
|
|
|
await time_out_assert(15, cat_wallet_2.get_confirmed_balance, 60)
|
|
await time_out_assert(15, cat_wallet_2.get_unconfirmed_balance, 60)
|
|
|
|
cc2_ph = await cat_wallet_2.get_new_cat_puzzle_hash()
|
|
tx_record = await wallet.wallet_state_manager.main_wallet.generate_signed_transaction(10, cc2_ph, 0)
|
|
await wallet.wallet_state_manager.add_pending_transaction(tx_record)
|
|
await time_out_assert(
|
|
15, tx_in_pool, True, full_node_api.full_node.mempool_manager, tx_record.spend_bundle.name()
|
|
)
|
|
for i in range(0, num_blocks):
|
|
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(32 * b"0"))
|
|
|
|
id = cat_wallet_2.id()
|
|
wsm = cat_wallet_2.wallet_state_manager
|
|
|
|
async def query_and_assert_transactions(wsm, id):
|
|
all_txs = await wsm.tx_store.get_all_transactions_for_wallet(id)
|
|
return len(list(filter(lambda tx: tx.amount == 10, all_txs)))
|
|
|
|
await time_out_assert(15, query_and_assert_transactions, 0, wsm, id)
|
|
await time_out_assert(15, wsm.get_confirmed_balance_for_wallet, 60, id)
|
|
await time_out_assert(15, cat_wallet_2.get_confirmed_balance, 60)
|
|
await time_out_assert(15, cat_wallet_2.get_unconfirmed_balance, 60)
|
|
|
|
@pytest.mark.parametrize(
|
|
"trusted",
|
|
[True, False],
|
|
)
|
|
@pytest.mark.asyncio
|
|
async def test_cat_spend_multiple(self, self_hostname, three_wallet_nodes, trusted):
|
|
num_blocks = 3
|
|
full_nodes, wallets = three_wallet_nodes
|
|
full_node_api = full_nodes[0]
|
|
full_node_server = full_node_api.server
|
|
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()
|
|
if trusted:
|
|
wallet_node_0.config["trusted_peers"] = {full_node_server.node_id.hex(): full_node_server.node_id.hex()}
|
|
wallet_node_1.config["trusted_peers"] = {full_node_server.node_id.hex(): full_node_server.node_id.hex()}
|
|
wallet_node_2.config["trusted_peers"] = {full_node_server.node_id.hex(): full_node_server.node_id.hex()}
|
|
else:
|
|
wallet_node_0.config["trusted_peers"] = {}
|
|
wallet_node_1.config["trusted_peers"] = {}
|
|
wallet_node_2.config["trusted_peers"] = {}
|
|
await wallet_server_0.start_client(PeerInfo(self_hostname, uint16(full_node_server._port)), None)
|
|
await wallet_server_1.start_client(PeerInfo(self_hostname, uint16(full_node_server._port)), None)
|
|
await wallet_server_2.start_client(PeerInfo(self_hostname, uint16(full_node_server._port)), None)
|
|
|
|
for i in range(0, num_blocks):
|
|
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
|
|
|
|
funds = sum(
|
|
[calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, num_blocks)]
|
|
)
|
|
|
|
await time_out_assert(15, wallet_0.get_confirmed_balance, funds)
|
|
|
|
async with wallet_node_0.wallet_state_manager.lock:
|
|
cat_wallet_0: CATWallet = await CATWallet.create_new_cat_wallet(
|
|
wallet_node_0.wallet_state_manager, wallet_0, {"identifier": "genesis_by_id"}, uint64(100)
|
|
)
|
|
tx_queue: List[TransactionRecord] = await wallet_node_0.wallet_state_manager.tx_store.get_not_sent()
|
|
tx_record = tx_queue[0]
|
|
await time_out_assert(
|
|
15, tx_in_pool, True, full_node_api.full_node.mempool_manager, tx_record.spend_bundle.name()
|
|
)
|
|
for i in range(1, num_blocks):
|
|
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(32 * b"0"))
|
|
|
|
await time_out_assert(15, cat_wallet_0.get_confirmed_balance, 100)
|
|
await time_out_assert(15, cat_wallet_0.get_unconfirmed_balance, 100)
|
|
|
|
assert cat_wallet_0.cat_info.limitations_program_hash is not None
|
|
asset_id = cat_wallet_0.get_asset_id()
|
|
|
|
cat_wallet_1: CATWallet = await CATWallet.create_wallet_for_cat(
|
|
wallet_node_1.wallet_state_manager, wallet_1, asset_id
|
|
)
|
|
|
|
cat_wallet_2: CATWallet = await CATWallet.create_wallet_for_cat(
|
|
wallet_node_2.wallet_state_manager, wallet_2, asset_id
|
|
)
|
|
|
|
assert cat_wallet_0.cat_info.limitations_program_hash == cat_wallet_1.cat_info.limitations_program_hash
|
|
assert cat_wallet_0.cat_info.limitations_program_hash == cat_wallet_2.cat_info.limitations_program_hash
|
|
|
|
cat_1_hash = await cat_wallet_1.get_new_inner_hash()
|
|
cat_2_hash = await cat_wallet_2.get_new_inner_hash()
|
|
|
|
tx_records = await cat_wallet_0.generate_signed_transaction([uint64(60), uint64(20)], [cat_1_hash, cat_2_hash])
|
|
for tx_record in tx_records:
|
|
await wallet_0.wallet_state_manager.add_pending_transaction(tx_record)
|
|
await time_out_assert(
|
|
15, tx_in_pool, True, full_node_api.full_node.mempool_manager, tx_record.spend_bundle.name()
|
|
)
|
|
for i in range(1, num_blocks):
|
|
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(32 * b"0"))
|
|
|
|
await time_out_assert(15, cat_wallet_0.get_confirmed_balance, 20)
|
|
await time_out_assert(15, cat_wallet_0.get_unconfirmed_balance, 20)
|
|
|
|
await time_out_assert(30, cat_wallet_1.get_confirmed_balance, 60)
|
|
await time_out_assert(30, cat_wallet_1.get_unconfirmed_balance, 60)
|
|
|
|
await time_out_assert(30, cat_wallet_2.get_confirmed_balance, 20)
|
|
await time_out_assert(30, cat_wallet_2.get_unconfirmed_balance, 20)
|
|
|
|
cat_hash = await cat_wallet_0.get_new_inner_hash()
|
|
|
|
tx_records = await cat_wallet_1.generate_signed_transaction([uint64(15)], [cat_hash])
|
|
for tx_record in tx_records:
|
|
await wallet_1.wallet_state_manager.add_pending_transaction(tx_record)
|
|
await time_out_assert(
|
|
15, tx_in_pool, True, full_node_api.full_node.mempool_manager, tx_record.spend_bundle.name()
|
|
)
|
|
|
|
tx_records_2 = await cat_wallet_2.generate_signed_transaction([uint64(20)], [cat_hash])
|
|
for tx_record in tx_records_2:
|
|
await wallet_2.wallet_state_manager.add_pending_transaction(tx_record)
|
|
await time_out_assert(
|
|
15, tx_in_pool, True, full_node_api.full_node.mempool_manager, tx_record.spend_bundle.name()
|
|
)
|
|
|
|
for i in range(1, num_blocks):
|
|
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(32 * b"0"))
|
|
|
|
await time_out_assert(15, cat_wallet_0.get_confirmed_balance, 55)
|
|
await time_out_assert(15, cat_wallet_0.get_unconfirmed_balance, 55)
|
|
|
|
await time_out_assert(30, cat_wallet_1.get_confirmed_balance, 45)
|
|
await time_out_assert(30, cat_wallet_1.get_unconfirmed_balance, 45)
|
|
|
|
await time_out_assert(30, cat_wallet_2.get_confirmed_balance, 0)
|
|
await time_out_assert(30, cat_wallet_2.get_unconfirmed_balance, 0)
|
|
|
|
txs = await wallet_1.wallet_state_manager.tx_store.get_transactions_between(cat_wallet_1.id(), 0, 100000)
|
|
print(len(txs))
|
|
# Test with Memo
|
|
tx_records_3: TransactionRecord = await cat_wallet_1.generate_signed_transaction(
|
|
[uint64(30)], [cat_hash], memos=[[b"Markus Walburg"]]
|
|
)
|
|
with pytest.raises(ValueError):
|
|
await cat_wallet_1.generate_signed_transaction(
|
|
[uint64(30)], [cat_hash], memos=[[b"too"], [b"many"], [b"memos"]]
|
|
)
|
|
|
|
for tx_record in tx_records_3:
|
|
await wallet_1.wallet_state_manager.add_pending_transaction(tx_record)
|
|
await time_out_assert(
|
|
15, tx_in_pool, True, full_node_api.full_node.mempool_manager, tx_record.spend_bundle.name()
|
|
)
|
|
txs = await wallet_1.wallet_state_manager.tx_store.get_transactions_between(cat_wallet_1.id(), 0, 100000)
|
|
for tx in txs:
|
|
if tx.amount == 30:
|
|
memos = tx.get_memos()
|
|
assert len(memos) == 1
|
|
assert b"Markus Walburg" in [v for v_list in memos.values() for v in v_list]
|
|
assert list(memos.keys())[0] in [a.name() for a in tx.spend_bundle.additions()]
|
|
|
|
@pytest.mark.parametrize(
|
|
"trusted",
|
|
[True, False],
|
|
)
|
|
@pytest.mark.asyncio
|
|
async def test_cat_max_amount_send(self, self_hostname, two_wallet_nodes, trusted):
|
|
num_blocks = 3
|
|
full_nodes, wallets = two_wallet_nodes
|
|
full_node_api = full_nodes[0]
|
|
full_node_server = full_node_api.server
|
|
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()
|
|
if trusted:
|
|
wallet_node.config["trusted_peers"] = {full_node_server.node_id.hex(): full_node_server.node_id.hex()}
|
|
wallet_node_2.config["trusted_peers"] = {full_node_server.node_id.hex(): full_node_server.node_id.hex()}
|
|
else:
|
|
wallet_node.config["trusted_peers"] = {}
|
|
wallet_node_2.config["trusted_peers"] = {}
|
|
await server_2.start_client(PeerInfo(self_hostname, uint16(full_node_server._port)), None)
|
|
await server_3.start_client(PeerInfo(self_hostname, uint16(full_node_server._port)), None)
|
|
|
|
for i in range(0, num_blocks):
|
|
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
|
|
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(32 * b"0"))
|
|
|
|
funds = sum(
|
|
[
|
|
calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i))
|
|
for i in range(1, num_blocks + 1)
|
|
]
|
|
)
|
|
|
|
await time_out_assert(15, wallet.get_confirmed_balance, funds)
|
|
|
|
async with wallet_node.wallet_state_manager.lock:
|
|
cat_wallet: CATWallet = await CATWallet.create_new_cat_wallet(
|
|
wallet_node.wallet_state_manager, wallet, {"identifier": "genesis_by_id"}, uint64(100000)
|
|
)
|
|
tx_queue: List[TransactionRecord] = await wallet_node.wallet_state_manager.tx_store.get_not_sent()
|
|
tx_record = tx_queue[0]
|
|
await time_out_assert(
|
|
15, tx_in_pool, True, full_node_api.full_node.mempool_manager, tx_record.spend_bundle.name()
|
|
)
|
|
for i in range(1, num_blocks):
|
|
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(32 * b"0"))
|
|
|
|
await time_out_assert(15, cat_wallet.get_confirmed_balance, 100000)
|
|
await time_out_assert(15, cat_wallet.get_unconfirmed_balance, 100000)
|
|
|
|
assert cat_wallet.cat_info.limitations_program_hash is not None
|
|
|
|
cat_2 = await cat_wallet.get_new_inner_puzzle()
|
|
cat_2_hash = cat_2.get_tree_hash()
|
|
amounts = []
|
|
puzzle_hashes = []
|
|
for i in range(1, 50):
|
|
amounts.append(uint64(i))
|
|
puzzle_hashes.append(cat_2_hash)
|
|
spent_coint = (await cat_wallet.get_cat_spendable_coins())[0].coin
|
|
tx_records = await cat_wallet.generate_signed_transaction(amounts, puzzle_hashes, coins={spent_coint})
|
|
for tx_record in tx_records:
|
|
await wallet.wallet_state_manager.add_pending_transaction(tx_record)
|
|
await time_out_assert(
|
|
15, tx_in_pool, True, full_node_api.full_node.mempool_manager, tx_record.spend_bundle.name()
|
|
)
|
|
|
|
for i in range(1, num_blocks):
|
|
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
|
|
|
|
await asyncio.sleep(2)
|
|
|
|
async def check_all_there():
|
|
spendable = await cat_wallet.get_cat_spendable_coins()
|
|
spendable_name_set = set()
|
|
for record in spendable:
|
|
spendable_name_set.add(record.coin.name())
|
|
puzzle_hash = construct_cat_puzzle(
|
|
CAT_MOD, cat_wallet.cat_info.limitations_program_hash, cat_2
|
|
).get_tree_hash()
|
|
for i in range(1, 50):
|
|
coin = Coin(spent_coint.name(), puzzle_hash, i)
|
|
if coin.name() not in spendable_name_set:
|
|
return False
|
|
return True
|
|
|
|
await time_out_assert(15, check_all_there, True)
|
|
await asyncio.sleep(5)
|
|
max_sent_amount = await cat_wallet.get_max_send_amount()
|
|
|
|
# 1) Generate transaction that is under the limit
|
|
under_limit_txs = None
|
|
try:
|
|
under_limit_txs = await cat_wallet.generate_signed_transaction(
|
|
[max_sent_amount - 1],
|
|
[ph],
|
|
)
|
|
except ValueError:
|
|
assert ValueError
|
|
|
|
assert under_limit_txs is not None
|
|
|
|
# 2) Generate transaction that is equal to limit
|
|
at_limit_txs = None
|
|
try:
|
|
at_limit_txs = await cat_wallet.generate_signed_transaction(
|
|
[max_sent_amount],
|
|
[ph],
|
|
)
|
|
except ValueError:
|
|
assert ValueError
|
|
|
|
assert at_limit_txs is not None
|
|
|
|
# 3) Generate transaction that is greater than limit
|
|
above_limit_txs = None
|
|
try:
|
|
above_limit_txs = await cat_wallet.generate_signed_transaction(
|
|
[max_sent_amount + 1],
|
|
[ph],
|
|
)
|
|
except ValueError:
|
|
pass
|
|
|
|
assert above_limit_txs is None
|
|
|
|
@pytest.mark.parametrize(
|
|
"trusted",
|
|
[True, False],
|
|
)
|
|
@pytest.mark.parametrize(
|
|
"autodiscovery",
|
|
[True, False],
|
|
)
|
|
@pytest.mark.asyncio
|
|
async def test_cat_hint(self, self_hostname, two_wallet_nodes, trusted, autodiscovery):
|
|
num_blocks = 3
|
|
full_nodes, wallets = two_wallet_nodes
|
|
full_node_api = full_nodes[0]
|
|
full_node_server = full_node_api.server
|
|
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()
|
|
if trusted:
|
|
wallet_node.config["trusted_peers"] = {full_node_server.node_id.hex(): full_node_server.node_id.hex()}
|
|
wallet_node_2.config["trusted_peers"] = {full_node_server.node_id.hex(): full_node_server.node_id.hex()}
|
|
else:
|
|
wallet_node.config["trusted_peers"] = {}
|
|
wallet_node_2.config["trusted_peers"] = {}
|
|
wallet_node.config["automatically_add_unknown_cats"] = autodiscovery
|
|
wallet_node_2.config["automatically_add_unknown_cats"] = autodiscovery
|
|
await server_2.start_client(PeerInfo(self_hostname, uint16(full_node_server._port)), None)
|
|
await server_3.start_client(PeerInfo(self_hostname, uint16(full_node_server._port)), None)
|
|
|
|
for i in range(0, num_blocks):
|
|
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
|
|
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(32 * b"0"))
|
|
|
|
funds = sum(
|
|
[
|
|
calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i))
|
|
for i in range(1, num_blocks + 1)
|
|
]
|
|
)
|
|
|
|
await time_out_assert(15, wallet.get_confirmed_balance, funds)
|
|
|
|
async with wallet_node.wallet_state_manager.lock:
|
|
cat_wallet: CATWallet = await CATWallet.create_new_cat_wallet(
|
|
wallet_node.wallet_state_manager, wallet, {"identifier": "genesis_by_id"}, uint64(100)
|
|
)
|
|
tx_queue: List[TransactionRecord] = await wallet_node.wallet_state_manager.tx_store.get_not_sent()
|
|
tx_record = tx_queue[0]
|
|
await time_out_assert(
|
|
15, tx_in_pool, True, full_node_api.full_node.mempool_manager, tx_record.spend_bundle.name()
|
|
)
|
|
for i in range(1, num_blocks):
|
|
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(32 * b"0"))
|
|
|
|
await time_out_assert(15, cat_wallet.get_confirmed_balance, 100)
|
|
await time_out_assert(15, cat_wallet.get_unconfirmed_balance, 100)
|
|
assert cat_wallet.cat_info.limitations_program_hash is not None
|
|
|
|
cat_2_hash = await wallet2.get_new_puzzlehash()
|
|
tx_records = await cat_wallet.generate_signed_transaction([uint64(60)], [cat_2_hash], memos=[[cat_2_hash]])
|
|
|
|
for tx_record in tx_records:
|
|
await wallet.wallet_state_manager.add_pending_transaction(tx_record)
|
|
|
|
await time_out_assert(
|
|
15, tx_in_pool, True, full_node_api.full_node.mempool_manager, tx_record.spend_bundle.name()
|
|
)
|
|
|
|
for i in range(1, num_blocks):
|
|
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
|
|
|
|
await time_out_assert(15, cat_wallet.get_confirmed_balance, 40)
|
|
await time_out_assert(15, cat_wallet.get_unconfirmed_balance, 40)
|
|
|
|
async def check_wallets(node):
|
|
return len(node.wallet_state_manager.wallets.keys())
|
|
|
|
if autodiscovery:
|
|
# Autodiscovery enabled: test that wallet was created at this point
|
|
await time_out_assert(10, check_wallets, 2, wallet_node_2)
|
|
else:
|
|
# Autodiscovery disabled: test that no wallet was created
|
|
await time_out_assert(10, check_wallets, 1, wallet_node_2)
|
|
|
|
# Then we update the wallet's default CATs
|
|
wallet_node_2.wallet_state_manager.default_cats = {
|
|
cat_wallet.cat_info.limitations_program_hash.hex(): {
|
|
"asset_id": cat_wallet.cat_info.limitations_program_hash.hex(),
|
|
"name": "Test",
|
|
"symbol": "TST",
|
|
}
|
|
}
|
|
|
|
# Then we send another transaction
|
|
tx_records = await cat_wallet.generate_signed_transaction([uint64(10)], [cat_2_hash], memos=[[cat_2_hash]])
|
|
|
|
for tx_record in tx_records:
|
|
await wallet.wallet_state_manager.add_pending_transaction(tx_record)
|
|
|
|
await time_out_assert(
|
|
15, tx_in_pool, True, full_node_api.full_node.mempool_manager, tx_record.spend_bundle.name()
|
|
)
|
|
|
|
for i in range(1, num_blocks):
|
|
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
|
|
|
|
await time_out_assert(15, cat_wallet.get_confirmed_balance, 30)
|
|
await time_out_assert(15, cat_wallet.get_unconfirmed_balance, 30)
|
|
|
|
# Now we check that another wallet WAS created, even if autodiscovery was disabled
|
|
await time_out_assert(10, check_wallets, 2, wallet_node_2)
|
|
cat_wallet_2 = wallet_node_2.wallet_state_manager.wallets[2]
|
|
|
|
# Previous balance + balance that triggered creation in case of disabled autodiscovery
|
|
await time_out_assert(30, cat_wallet_2.get_confirmed_balance, 70)
|
|
await time_out_assert(30, cat_wallet_2.get_unconfirmed_balance, 70)
|
|
|
|
cat_hash = await cat_wallet.get_new_inner_hash()
|
|
tx_records = await cat_wallet_2.generate_signed_transaction([uint64(5)], [cat_hash])
|
|
for tx_record in tx_records:
|
|
await wallet.wallet_state_manager.add_pending_transaction(tx_record)
|
|
|
|
await time_out_assert(
|
|
15, tx_in_pool, True, full_node_api.full_node.mempool_manager, tx_record.spend_bundle.name()
|
|
)
|
|
|
|
for i in range(1, num_blocks):
|
|
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
|
|
|
|
await time_out_assert(15, cat_wallet.get_confirmed_balance, 35)
|
|
await time_out_assert(15, cat_wallet.get_unconfirmed_balance, 35)
|