Clawback fixes (#15475)

Fix Clawback known issues
This commit is contained in:
Kronus91 2023-06-09 10:15:40 -07:00 committed by GitHub
parent 0099379835
commit 82c9ed953d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 34 additions and 12 deletions

View File

@ -904,7 +904,7 @@ class WalletRpcApi:
try:
tx = (await self._convert_tx_puzzle_hash(tr)).to_json_dict_convenience(self.service.config)
tx_list.append(tx)
if tx["type"] not in clawback_types or tx["spend_bundle"] is None:
if tx["type"] not in clawback_types:
continue
coin: Coin = tr.additions[0]
record: Optional[WalletCoinRecord] = await self.service.wallet_state_manager.coin_store.get_coin_record(

View File

@ -43,6 +43,11 @@ class WalletInterestedStore:
cursor = await conn.execute("INSERT OR REPLACE INTO interested_coins VALUES (?)", (coin_id.hex(),))
await cursor.close()
async def remove_interested_coin_id(self, coin_id: bytes32) -> None:
async with self.db_wrapper.writer_maybe_transaction() as conn:
cursor = await conn.execute("DELETE FROM interested_coins WHERE coin_name=?", (coin_id.hex(),))
await cursor.close()
async def get_interested_puzzle_hashes(self) -> List[Tuple[bytes32, int]]:
async with self.db_wrapper.reader_no_transaction() as conn:
cursor = await conn.execute("SELECT puzzle_hash, wallet_id FROM interested_puzzle_hashes")

View File

@ -87,7 +87,6 @@ from chia.wallet.util.wallet_sync_utils import (
PeerRequestException,
fetch_coin_spend_for_coin_state,
last_change_height_cs,
subscribe_to_coin_updates,
)
from chia.wallet.util.wallet_types import CoinType, WalletIdentifier, WalletType
from chia.wallet.vc_wallet.vc_drivers import VerifiedCredential
@ -770,8 +769,6 @@ class WalletStateManager:
)
coin_spend: CoinSpend = generate_clawback_spend_bundle(coin, metadata, inner_puzzle, inner_solution)
coin_spends.append(coin_spend)
# Update incoming tx to prevent double spend and mark it is pending
await self.tx_store.increment_sent(incoming_tx.name, "", MempoolInclusionStatus.PENDING, None)
except Exception as e:
self.log.error(f"Failed to create clawback spend bundle for {coin.name().hex()}: {e}")
if len(coin_spends) == 0:
@ -803,6 +800,9 @@ class WalletStateManager:
memos=list(compute_memos(spend_bundle).items()),
)
await self.add_pending_transaction(tx_record)
# Update incoming tx to prevent double spend and mark it is pending
for coin_spend in coin_spends:
await self.tx_store.increment_sent(coin_spend.coin.name(), "", MempoolInclusionStatus.PENDING, None)
return [tx_record.name]
async def filter_spam(self, new_coin_state: List[CoinState]) -> List[CoinState]:
@ -1145,7 +1145,7 @@ class WalletStateManager:
self.log.info("Found Clawback merkle coin %s as the recipient.", coin_state.coin.name().hex())
is_recipient = True
# For the recipient we need to manually subscribe the merkle coin
await subscribe_to_coin_updates([coin_state.coin.name()], peer, uint32(0))
await self.add_interested_coin_ids([coin_state.coin.name()])
if is_recipient is not None:
spend_bundle = SpendBundle([coin_spend], G2Element())
memos = compute_memos(spend_bundle)
@ -1171,9 +1171,9 @@ class WalletStateManager:
to_puzzle_hash=metadata.recipient_puzzle_hash,
amount=uint64(coin_state.coin.amount),
fee_amount=uint64(0),
confirmed=True,
confirmed=False,
sent=uint32(0),
spend_bundle=spend_bundle,
spend_bundle=None,
additions=[coin_state.coin],
removals=[coin_spend.coin],
wallet_id=uint32(1),
@ -1438,13 +1438,23 @@ class WalletStateManager:
await self.tx_store.add_transaction_record(tx_record)
else:
await self.coin_store.set_spent(coin_name, uint32(coin_state.spent_height))
rem_tx_records: List[TransactionRecord] = []
if record.coin_type == CoinType.CLAWBACK:
await self.interested_store.remove_interested_coin_id(coin_state.coin.name())
confirmed_tx_records: List[TransactionRecord] = []
for tx_record in all_unconfirmed:
for rem_coin in tx_record.removals:
if rem_coin == coin_state.coin:
rem_tx_records.append(tx_record)
if tx_record.type in {
TransactionType.INCOMING_CLAWBACK_SEND.value,
TransactionType.INCOMING_CLAWBACK_RECEIVE.value,
}:
for add_coin in tx_record.additions:
if add_coin == coin_state.coin:
confirmed_tx_records.append(tx_record)
else:
for rem_coin in tx_record.removals:
if rem_coin == coin_state.coin:
confirmed_tx_records.append(tx_record)
for tx_record in rem_tx_records:
for tx_record in confirmed_tx_records:
await self.tx_store.set_confirmed(tx_record.name, uint32(coin_state.spent_height))
for unconfirmed_record in all_unconfirmed:
for rem_coin in unconfirmed_record.removals:

View File

@ -345,7 +345,10 @@ class TestWalletSimulator:
assert await wallet.get_confirmed_balance() == 3999999999500
# clawback merkle coin
merkle_coin = tx.additions[0] if tx.additions[0].amount == 500 else tx.additions[1]
interested_coins = await wallet_node_2.wallet_state_manager.interested_store.get_interested_coin_ids()
assert merkle_coin.name() in set(interested_coins)
assert len(txs["transactions"]) == 1
assert not txs["transactions"][0]["confirmed"]
assert txs["transactions"][0]["metadata"]["recipient_puzzle_hash"][2:] == normal_puzhash.hex()
assert txs["transactions"][0]["metadata"]["coin_id"] == merkle_coin.name().hex()
has_exception = False
@ -402,6 +405,8 @@ class TestWalletSimulator:
)
assert len(txs["transactions"]) == 1
assert txs["transactions"][0]["confirmed"]
interested_coins = await wallet_node_2.wallet_state_manager.interested_store.get_interested_coin_ids()
assert merkle_coin.name() not in set(interested_coins)
@pytest.mark.parametrize(
"trusted",

View File

@ -24,6 +24,8 @@ class TestWalletInterestedStore:
assert (await store.get_interested_coin_ids()) == [coin_1.name()]
await store.add_interested_coin_id(coin_2.name())
assert set(await store.get_interested_coin_ids()) == {coin_1.name(), coin_2.name()}
await store.remove_interested_coin_id(coin_1.name())
assert set(await store.get_interested_coin_ids()) == {coin_2.name()}
puzzle_hash = token_bytes(32)
assert len(await store.get_interested_puzzle_hashes()) == 0