Fix recoverNoScriptTxnWithKey regression, add to more tests.
Some checks are pending
ci / ci (3.12) (push) Waiting to run

This commit is contained in:
tecnovert 2025-01-06 20:15:37 +02:00
parent a53de511ce
commit 28d99c4c0f
No known key found for this signature in database
GPG key ID: 8ED6D8750C4E3F93
10 changed files with 97 additions and 59 deletions

View file

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019-2024 tecnovert
# Copyright (c) 2024 The Basicswap developers
# Copyright (c) 2024-2025 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@ -10327,7 +10327,14 @@ class BasicSwap(BaseApp):
elif coin == Coins.NAV:
rv["immature"] = walletinfo["immature_balance"]
elif coin == Coins.LTC:
rv["mweb_address"] = self.getCachedStealthAddressForCoin(Coins.LTC_MWEB)
try:
rv["mweb_address"] = self.getCachedStealthAddressForCoin(
Coins.LTC_MWEB
)
except Exception as e:
self.log.warning(
f"getCachedStealthAddressForCoin for {ci.coin_name()} failed with: {e}"
)
rv["mweb_balance"] = walletinfo["mweb_balance"]
rv["mweb_pending"] = (
walletinfo["mweb_unconfirmed"] + walletinfo["mweb_immature"]

View file

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2024 tecnovert
# Copyright (c) 2025 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@ -53,6 +54,10 @@ class CoinInterface:
self._mx_wallet = threading.Lock()
self._altruistic = True
def interface_type(self) -> int:
# coin_type() returns the base coin type, interface_type() returns the coin+balance type.
return self.coin_type()
def setDefaults(self):
self._unknown_wallet_seed = True
self._restore_height = None

View file

@ -2,7 +2,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020-2024 tecnovert
# Copyright (c) 2024 The Basicswap developers
# Copyright (c) 2024-2025 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@ -1397,6 +1397,7 @@ class BTCInterface(Secp256k1Interface):
cb_swap_value: int,
b_fee: int,
restore_height: int,
spend_actual_balance: bool = False,
lock_tx_vout=None,
) -> bytes:
self._log.info(

View file

@ -2,7 +2,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2024 tecnovert
# Copyright (c) 2024 The Basicswap developers
# Copyright (c) 2024-2025 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@ -1726,6 +1726,7 @@ class DCRInterface(Secp256k1Interface):
cb_swap_value: int,
b_fee: int,
restore_height: int,
spend_actual_balance: bool = False,
lock_tx_vout=None,
) -> bytes:
self._log.info("spendBLockTx %s:\n", chain_b_lock_txid.hex())

View file

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020-2023 tecnovert
# Copyright (c) 2024-2025 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@ -52,7 +53,6 @@ class LTCInterface(BTCInterface):
def getWalletInfo(self):
rv = super(LTCInterface, self).getWalletInfo()
mweb_info = self.rpc_wallet_mweb("getwalletinfo")
rv["mweb_balance"] = mweb_info["balance"]
rv["mweb_unconfirmed"] = mweb_info["unconfirmed_balance"]
@ -88,8 +88,8 @@ class LTCInterface(BTCInterface):
class LTCInterfaceMWEB(LTCInterface):
@staticmethod
def coin_type():
def interface_type(self) -> int:
return Coins.LTC_MWEB
def __init__(self, coin_settings, network, swap_client=None):

View file

@ -2,7 +2,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2023 tecnovert
# Copyright (c) 2024 The Basicswap developers
# Copyright (c) 2024-2025 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@ -666,6 +666,7 @@ class NAVInterface(BTCInterface):
cb_swap_value: int,
b_fee: int,
restore_height: int,
spend_actual_balance: bool = False,
lock_tx_vout=None,
) -> bytes:
self._log.info("spendBLockTx %s:\n", chain_b_lock_txid.hex())

View file

@ -2,7 +2,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020-2024 tecnovert
# Copyright (c) 2024 The Basicswap developers
# Copyright (c) 2024-2025 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@ -187,6 +187,10 @@ class PARTInterface(BTCInterface):
class PARTInterfaceBlind(PARTInterface):
def interface_type(self) -> int:
return Coins.PART_BLIND
@staticmethod
def balance_type():
return BalanceTypes.BLIND
@ -1174,6 +1178,10 @@ class PARTInterfaceBlind(PARTInterface):
class PARTInterfaceAnon(PARTInterface):
def interface_type(self) -> int:
return Coins.PART_ANON
@staticmethod
def balance_type():
return BalanceTypes.ANON

View file

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020-2024 tecnovert
# Copyright (c) 2024 The Basicswap developers
# Copyright (c) 2024-2025 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@ -15,9 +15,10 @@ from basicswap.chainparams import (
Coins,
)
from basicswap.basicswap_util import (
EventLogTypes,
KeyTypes,
SwapTypes,
EventLogTypes,
TxTypes,
)
from . import ProtocolInterface
from basicswap.contrib.test_framework.script import CScript, CScriptOp, OP_CHECKMULTISIG
@ -55,7 +56,7 @@ def recoverNoScriptTxnWithKey(self, bid_id: bytes, encoded_key, cursor=None):
ensure(xmr_offer, "Adaptor-sig offer not found: {}.".format(bid.offer_id.hex()))
# The no-script coin is always the follower
reverse_bid: bool = self.is_reverse_ads_bid(offer.coin_from)
reverse_bid: bool = self.is_reverse_ads_bid(offer.coin_from, offer.coin_to)
ci_from = self.ci(Coins(offer.coin_from))
ci_to = self.ci(Coins(offer.coin_to))
ci_follower = ci_from if reverse_bid else ci_to
@ -89,16 +90,20 @@ def recoverNoScriptTxnWithKey(self, bid_id: bytes, encoded_key, cursor=None):
summed_pkbs = ci_follower.getPubkey(vkbs)
if summed_pkbs != xmr_swap.pkbs:
err_msg: str = "Summed key does not match expected wallet spend pubkey"
have_pk = summed_pkbs.hex()
expect_pk = xmr_swap.pkbs.hex()
self.log.error(f"{err_msg}. Got: {have_pk}, Expect: {expect_pk}")
self.log.error(
f"{err_msg}. Got: {summed_pkbs.hex()}, Expect: {xmr_swap.pkbs.hex()}"
)
raise ValueError(err_msg)
if ci_follower.coin_type() in (Coins.XMR, Coins.WOW):
coin_to: int = ci_follower.interface_type()
base_coin_to: int = ci_follower.coin_type()
if coin_to in (Coins.XMR, Coins.WOW):
address_to = self.getCachedMainWalletAddress(ci_follower, use_cursor)
elif coin_to in (Coins.PART_BLIND, Coins.PART_ANON):
address_to = self.getCachedStealthAddressForCoin(base_coin_to, use_cursor)
else:
address_to = self.getCachedStealthAddressForCoin(
ci_follower.coin_type(), use_cursor
address_to = self.getReceiveAddressFromPool(
base_coin_to, bid_id, TxTypes.XMR_SWAP_B_LOCK_SPEND, use_cursor
)
amount = bid.amount_to
lock_tx_vout = bid.getLockTXBVout()
@ -145,10 +150,11 @@ def getChainBSplitKey(swap_client, bid, xmr_swap, offer):
was_sent: bool = bid.was_received if reverse_bid else bid.was_sent
key_type = KeyTypes.KBSF if was_sent else KeyTypes.KBSL
return ci_follower.encodeKey(
swap_client.getPathKey(
ci_leader.coin_type(),
ci_follower.coin_type(),
ci_leader.interface_type(),
ci_follower.interface_type(),
bid.created_at,
xmr_swap.contract_count,
key_type,

View file

@ -2,7 +2,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021-2024 tecnovert
# Copyright (c) 2024 The Basicswap developers
# Copyright (c) 2024-2025 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@ -170,7 +170,11 @@ class TestFunctions(BaseTest):
bid_id = swap_clients[id_bidder].postXmrBid(offer_id, offer.amount_from)
wait_for_bid(
test_delay_event, swap_clients[id_offerer], bid_id, BidStates.BID_RECEIVED
test_delay_event,
swap_clients[id_offerer],
bid_id,
BidStates.BID_RECEIVED,
wait_for=(self.extra_wait_time + 40),
)
bid0 = read_json_api(1800 + id_offerer, f"bids/{bid_id.hex()}")
@ -392,7 +396,7 @@ class TestFunctions(BaseTest):
)
swap_clients[id_follower].ci(
coin_from if reverse_bid else coin_to
coin_to if reverse_bid else coin_from
)._altruistic = with_mercy
amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1)
@ -415,17 +419,10 @@ class TestFunctions(BaseTest):
test_delay_event, swap_clients[id_offerer], bid_id, BidStates.BID_RECEIVED
)
debug_type = (
DebugTypes.BID_DONT_SPEND_COIN_A_LOCK_REFUND2
if with_mercy
else DebugTypes.BID_DONT_SPEND_COIN_A_LOCK_REFUND
)
swap_clients[id_leader].setBidDebugInd(bid_id, debug_type)
debug_type = (
DebugTypes.BID_DONT_SPEND_COIN_B_LOCK
if with_mercy
else DebugTypes.BID_STOP_AFTER_COIN_A_LOCK
swap_clients[id_leader].setBidDebugInd(
bid_id, DebugTypes.BID_DONT_SPEND_COIN_A_LOCK_REFUND2
)
debug_type = DebugTypes.BID_DONT_SPEND_COIN_B_LOCK
swap_clients[id_follower].setBidDebugInd(bid_id, debug_type)
swap_clients[id_leader].setBidDebugInd(
@ -442,7 +439,7 @@ class TestFunctions(BaseTest):
expect_state = (
(BidStates.XMR_SWAP_NOSCRIPT_TX_REDEEMED, BidStates.SWAP_COMPLETED)
if with_mercy
else BidStates.BID_STALLED_FOR_TEST
else (BidStates.BID_STALLED_FOR_TEST, BidStates.XMR_SWAP_FAILED_SWIPED)
)
wait_for_bid(
test_delay_event,
@ -473,6 +470,19 @@ class TestFunctions(BaseTest):
wait_for_none_active(test_delay_event, 1800 + id_offerer)
wait_for_none_active(test_delay_event, 1800 + id_bidder)
if with_mercy is False:
# Test manually redeeming the no-script lock tx
offerer_key = read_json_api(
1800 + id_offerer,
"bids/{}".format(bid_id.hex()),
{"chainbkeysplit": True},
)["splitkey"]
data = {"spendchainblocktx": True, "remote_key": offerer_key}
redeemed_txid = read_json_api(
1800 + id_bidder, "bids/{}".format(bid_id.hex()), data
)["txid"]
assert len(redeemed_txid) == 64
def do_test_04_follower_recover_b_lock_tx(
self, coin_from, coin_to, lock_value: int = 32
):
@ -1601,7 +1611,13 @@ class BasicSwapTest(TestFunctions):
offer = swap_clients[1].getOffer(offer_id)
bid_id = swap_clients[1].postBid(offer_id, offer.amount_from)
wait_for_bid(test_delay_event, swap_clients[2], bid_id, BidStates.BID_RECEIVED)
wait_for_bid(
test_delay_event,
swap_clients[2],
bid_id,
BidStates.BID_RECEIVED,
wait_for=(self.extra_wait_time + 40),
)
swap_clients[2].acceptBid(bid_id)
wait_for_bid(
@ -1662,7 +1678,13 @@ class BasicSwapTest(TestFunctions):
wait_for_offer(test_delay_event, swap_clients[1], offer_id)
bid_id = swap_clients[1].postXmrBid(offer_id, amt_swap)
swap_clients[1].abandonBid(bid_id)
wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_ACCEPTED)
wait_for_bid(
test_delay_event,
swap_clients[0],
bid_id,
BidStates.BID_ACCEPTED,
wait_for=(self.extra_wait_time + 40),
)
try:
swap_clients[0].setMockTimeOffset(7200)

View file

@ -2,16 +2,13 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021-2023 tecnovert
# Copyright (c) 2024 The Basicswap developers
# Copyright (c) 2024-2025 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
import json
import random
import logging
import unittest
from urllib import parse
from urllib.request import urlopen
from basicswap.basicswap import (
Coins,
@ -27,7 +24,6 @@ from basicswap.util import (
format_amount,
)
from tests.basicswap.util import (
post_json_req,
read_json_api,
)
from tests.basicswap.common import (
@ -61,9 +57,7 @@ class Test(BaseTest):
"subfee": False,
"type_to": "blind",
}
json_rv = json.loads(
post_json_req("http://127.0.0.1:1800/json/wallets/part/withdraw", post_json)
)
json_rv = read_json_api(1800, "wallets/part/withdraw", post_json)
assert len(json_rv["txid"]) == 64
logging.info("Waiting for blind balance")
@ -388,7 +382,7 @@ class Test(BaseTest):
swap_clients[1].setBidDebugInd(bid_id, DebugTypes.CREATE_INVALID_COIN_B_LOCK)
swap_clients[0].setBidDebugInd(
bid_id, DebugTypes.BID_DONT_SPEND_COIN_A_LOCK_REFUND
bid_id, DebugTypes.BID_DONT_SPEND_COIN_A_LOCK_REFUND2
)
swap_clients[0].acceptXmrBid(bid_id)
@ -397,7 +391,7 @@ class Test(BaseTest):
test_delay_event,
swap_clients[0],
bid_id,
BidStates.BID_STALLED_FOR_TEST,
(BidStates.BID_STALLED_FOR_TEST, BidStates.XMR_SWAP_FAILED_SWIPED),
wait_for=180,
)
wait_for_bid(
@ -422,21 +416,14 @@ class Test(BaseTest):
wait_for_none_active(test_delay_event, 1800)
wait_for_none_active(test_delay_event, 1801)
data = parse.urlencode({"chainbkeysplit": True}).encode()
offerer_key = json.loads(
urlopen(
"http://127.0.0.1:1800/json/bids/{}".format(bid_id.hex()), data=data
).read()
offerer_key = read_json_api(
1800, "bids/{}".format(bid_id.hex()), {"chainbkeysplit": True}
)["splitkey"]
data = parse.urlencode(
{"spendchainblocktx": True, "remote_key": offerer_key}
).encode()
redeemed_txid = json.loads(
urlopen(
"http://127.0.0.1:1801/json/bids/{}".format(bid_id.hex()), data=data
).read()
)["txid"]
data = {"spendchainblocktx": True, "remote_key": offerer_key}
redeemed_txid = read_json_api(1801, "bids/{}".format(bid_id.hex()), data)[
"txid"
]
assert len(redeemed_txid) == 64
def do_test_04_follower_recover_b_lock_tx(self, coin_from, coin_to):