mirror of
https://github.com/Chia-Network/chia-blockchain.git
synced 2024-09-19 23:21:46 +03:00
full_node: Don't send duplicates in register_interest_in_puzzle_hash
(#15560)
* Test self hinted coin in puzzle hash subscription * Don't send duplicates in `register_interest_in_puzzle_hash` * Some tweaks in the test
This commit is contained in:
parent
c7e2acf219
commit
f85e68ee22
@ -365,11 +365,11 @@ class CoinStore:
|
||||
min_height: uint32 = uint32(0),
|
||||
*,
|
||||
max_items: int = 50000,
|
||||
) -> List[CoinState]:
|
||||
) -> Set[CoinState]:
|
||||
if len(puzzle_hashes) == 0:
|
||||
return []
|
||||
return set()
|
||||
|
||||
coins: List[CoinState] = []
|
||||
coins: Set[CoinState] = set()
|
||||
async with self.db_wrapper.reader_no_transaction() as conn:
|
||||
for batch in to_batches(puzzle_hashes, SQLITE_MAX_VARIABLE_NUMBER):
|
||||
puzzle_hashes_db: Tuple[Any, ...]
|
||||
@ -388,7 +388,7 @@ class CoinStore:
|
||||
) as cursor:
|
||||
row: sqlite3.Row
|
||||
for row in await cursor.fetchall():
|
||||
coins.append(self.row_to_coin_state(row))
|
||||
coins.add(self.row_to_coin_state(row))
|
||||
|
||||
if len(coins) >= max_items:
|
||||
break
|
||||
|
@ -1489,7 +1489,7 @@ class FullNodeAPI:
|
||||
# before we send the response
|
||||
|
||||
# Send all coins with requested puzzle hash that have been created after the specified height
|
||||
states: List[CoinState] = await self.full_node.coin_store.get_coin_states_by_puzzle_hashes(
|
||||
states: Set[CoinState] = await self.full_node.coin_store.get_coin_states_by_puzzle_hashes(
|
||||
include_spent_coins=True, puzzle_hashes=puzzle_hashes, min_height=request.min_height, max_items=max_items
|
||||
)
|
||||
max_items -= len(states)
|
||||
@ -1511,7 +1511,7 @@ class FullNodeAPI:
|
||||
min_height=request.min_height,
|
||||
max_items=len(hint_coin_ids),
|
||||
)
|
||||
states.extend(hint_states)
|
||||
states.update(hint_states)
|
||||
|
||||
end_time = time.monotonic()
|
||||
|
||||
@ -1530,7 +1530,7 @@ class FullNodeAPI:
|
||||
end_time - start_time,
|
||||
)
|
||||
|
||||
response = wallet_protocol.RespondToPhUpdates(request.puzzle_hashes, request.min_height, states)
|
||||
response = wallet_protocol.RespondToPhUpdates(request.puzzle_hashes, request.min_height, list(states))
|
||||
msg = make_msg(ProtocolMessageTypes.respond_to_ph_update, response)
|
||||
return msg
|
||||
|
||||
|
@ -14,6 +14,7 @@ from chia.protocols.full_node_protocol import RespondTransaction
|
||||
from chia.protocols.protocol_message_types import ProtocolMessageTypes
|
||||
from chia.protocols.wallet_protocol import CoinStateUpdate, RespondToCoinUpdates, RespondToPhUpdates
|
||||
from chia.server.outbound_message import NodeType
|
||||
from chia.simulator.setup_nodes import SimulatorsAndWallets
|
||||
from chia.simulator.simulator_protocol import FarmNewBlockProtocol, ReorgProtocol
|
||||
from chia.simulator.time_out_assert import time_out_assert
|
||||
from chia.simulator.wallet_tools import WalletTool
|
||||
@ -535,6 +536,40 @@ class TestSimpleSyncProtocol:
|
||||
# ignore the duplicate
|
||||
assert data_response.coin_states == []
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_subscribe_for_puzzle_hash_coin_hint_duplicates(
|
||||
self, simulator_and_wallet: SimulatorsAndWallets, self_hostname: str
|
||||
) -> None:
|
||||
[full_node_api], [[_, wallet_server]], bt = simulator_and_wallet
|
||||
full_node_server = full_node_api.full_node.server
|
||||
|
||||
await wallet_server.start_client(PeerInfo(self_hostname, uint16(full_node_server._port)), None)
|
||||
|
||||
wt: WalletTool = bt.get_pool_wallet_tool()
|
||||
ph = wt.get_new_puzzlehash()
|
||||
await full_node_api.farm_blocks_to_puzzlehash(4, ph)
|
||||
coins = await full_node_api.full_node.coin_store.get_coin_records_by_puzzle_hashes(False, [ph])
|
||||
wallet_connection = full_node_server.all_connections[wallet_server.node_id]
|
||||
|
||||
# Create a coin which is hinted with its own destination puzzle hash
|
||||
tx: SpendBundle = wt.generate_signed_transaction(
|
||||
uint64(10),
|
||||
wt.get_new_puzzlehash(),
|
||||
coins[0].coin,
|
||||
condition_dic={
|
||||
ConditionOpcode.CREATE_COIN: [ConditionWithArgs(ConditionOpcode.CREATE_COIN, [ph, int_to_bytes(1), ph])]
|
||||
},
|
||||
)
|
||||
await full_node_api.respond_transaction(RespondTransaction(tx), wallet_connection)
|
||||
await full_node_api.process_spend_bundles(bundles=[tx])
|
||||
# Query the coin states and make sure it doesn't contain duplicated entries
|
||||
msg = wallet_protocol.RegisterForPhUpdates([ph], uint32(0))
|
||||
msg_response = await full_node_api.register_interest_in_puzzle_hash(msg, wallet_connection)
|
||||
assert msg_response.type == ProtocolMessageTypes.respond_to_ph_update.value
|
||||
response = RespondToCoinUpdates.from_bytes(msg_response.data)
|
||||
assert len(response.coin_states) > 0
|
||||
assert len(set(response.coin_states)) == len(response.coin_states)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_subscribe_for_hint_long_sync(self, wallet_two_node_simulator, self_hostname):
|
||||
num_blocks = 4
|
||||
|
Loading…
Reference in New Issue
Block a user