mirror of
https://github.com/basicswap/basicswap.git
synced 2026-04-11 03:47:22 +02:00
refactor: backports
This commit is contained in:
@@ -3964,6 +3964,13 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
|
||||
except Exception as e:
|
||||
raise ValueError(f"Invalid message networks: {e}")
|
||||
|
||||
def isValidSwapDest(self, ci, dest: bytes):
|
||||
ensure(isinstance(dest, bytes), "Swap destination must be bytes")
|
||||
if ci.coin_type() in (Coins.PART_BLIND,):
|
||||
return ci.isValidPubkey(dest)
|
||||
# TODO: allow p2wsh
|
||||
return ci.isValidAddressHash(dest)
|
||||
|
||||
def ensureWalletCanSend(
|
||||
self, ci, swap_type, ensure_balance: int, estimated_fee: int, for_offer=True
|
||||
) -> None:
|
||||
@@ -5365,12 +5372,13 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
|
||||
self.loadBidTxns(bid, cursor)
|
||||
return bid, xmr_swap
|
||||
|
||||
def getXmrBid(self, bid_id: bytes):
|
||||
def getXmrBid(self, bid_id: bytes, cursor=None):
|
||||
try:
|
||||
cursor = self.openDB()
|
||||
return self.getXmrBidFromSession(cursor, bid_id)
|
||||
use_cursor = self.openDB(cursor)
|
||||
return self.getXmrBidFromSession(use_cursor, bid_id)
|
||||
finally:
|
||||
self.closeDB(cursor, commit=False)
|
||||
if cursor is None:
|
||||
self.closeDB(use_cursor, commit=False)
|
||||
|
||||
def getXmrOfferFromSession(self, cursor, offer_id: bytes):
|
||||
offer = self.queryOne(Offer, cursor, {"offer_id": offer_id})
|
||||
@@ -5875,7 +5883,7 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
|
||||
)
|
||||
if bid.bid_id and bid_msg_id != bid.bid_id:
|
||||
self.log.warning(
|
||||
f"sendBidMessage: Mismatched bid ids: {bid.bid_id.hex()}, {bid_msg_id.hex()}."
|
||||
f"sendBidMessage: Mismatched bid ids: {self.log.id(bid.bid_id)}, {self.log.id(bid_msg_id)}."
|
||||
)
|
||||
return bid_msg_id
|
||||
|
||||
@@ -7771,7 +7779,12 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
|
||||
len(xmr_swap.al_lock_refund_tx_sig) > 0
|
||||
and len(xmr_swap.af_lock_refund_tx_sig) > 0
|
||||
):
|
||||
|
||||
try:
|
||||
if bid.xmr_b_lock_tx is None and self.haveDebugInd(
|
||||
bid.bid_id, DebugTypes.WAIT_FOR_COIN_B_LOCK_BEFORE_PREREFUND
|
||||
):
|
||||
raise TemporaryError("Debug: Waiting for Coin B Lock Tx")
|
||||
txid = ci_from.publishTx(xmr_swap.a_lock_refund_tx)
|
||||
|
||||
# BCH txids change
|
||||
@@ -7821,6 +7834,10 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
|
||||
self.saveBidInSession(bid_id, bid, cursor, xmr_swap)
|
||||
self.commitDB()
|
||||
return rv
|
||||
else:
|
||||
self.log.warning(
|
||||
f"Trying to publish coin a lock refund tx: {ex}"
|
||||
)
|
||||
|
||||
state = BidStates(bid.state)
|
||||
if state == BidStates.SWAP_COMPLETED:
|
||||
@@ -8067,6 +8084,15 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
|
||||
self.log.warning(
|
||||
f"Not releasing ads script coin lock tx for bid {self.log.id(bid_id)}: Chain A lock refund tx already exists."
|
||||
)
|
||||
elif (
|
||||
bid.debug_ind == DebugTypes.DONT_RELEASE_COIN_A_LOCK
|
||||
):
|
||||
self.logBidEvent(
|
||||
bid_id,
|
||||
EventLogTypes.DEBUG_TWEAK_APPLIED,
|
||||
f"ind {DebugTypes.DONT_RELEASE_COIN_A_LOCK}",
|
||||
None,
|
||||
)
|
||||
else:
|
||||
delay = self.get_delay_event_seconds()
|
||||
self.log.info(
|
||||
@@ -8513,9 +8539,8 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
|
||||
)
|
||||
|
||||
watched = self.coin_clients[coin_type]["watched_transactions"]
|
||||
|
||||
for wo in watched:
|
||||
if wo.bid_id == bid_id and wo.txid_hex == txid_hex:
|
||||
for wt in watched:
|
||||
if wt.bid_id == bid_id and wt.txid_hex == txid_hex:
|
||||
self.log.debug("Transaction already being watched.")
|
||||
return
|
||||
|
||||
@@ -8953,7 +8978,7 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
|
||||
|
||||
else:
|
||||
self.log.info(
|
||||
f"Coin a lock refund spent by unknown tx, bid {self.log.id(bid_id)}."
|
||||
f"Coin a lock refund spent by unknown tx, bid {self.log.id(bid_id)}, txid {self.logIDT(spending_txid)}."
|
||||
)
|
||||
|
||||
mercy_keyshare = None
|
||||
@@ -8980,6 +9005,7 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
|
||||
bid.setState(BidStates.XMR_SWAP_FAILED_SWIPED)
|
||||
else:
|
||||
delay = self.get_delay_event_seconds()
|
||||
self.log.info("Found mercy output.")
|
||||
self.log.info(
|
||||
f"Redeeming coin b lock tx for bid {self.log.id(bid_id)} in {delay} seconds."
|
||||
)
|
||||
@@ -9298,6 +9324,7 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
|
||||
self.processFoundTransaction(
|
||||
t, block_hash, block["height"], chain_blocks
|
||||
)
|
||||
|
||||
for s in c["watched_scripts"]:
|
||||
for i, txo in enumerate(tx["vout"]):
|
||||
if "scriptPubKey" in txo and "hex" in txo["scriptPubKey"]:
|
||||
@@ -12174,7 +12201,9 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
|
||||
xmr_swap.af_lock_refund_spend_tx_sig = ci_from.decryptOtVES(
|
||||
kbsl, xmr_swap.af_lock_refund_spend_tx_esig
|
||||
)
|
||||
prevout_amount = ci_from.getLockRefundTxSwapOutputValue(bid, xmr_swap)
|
||||
prevout_amount: int = ci_from.getLockRefundTxSwapOutputValue(
|
||||
bid, xmr_swap
|
||||
)
|
||||
al_lock_refund_spend_tx_sig = ci_from.signTx(
|
||||
kal,
|
||||
xmr_swap.a_lock_refund_spend_tx,
|
||||
@@ -12601,8 +12630,7 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
|
||||
ci_from.verifyPubkey(msg_data.pkaf), "Invalid chain A follower public key"
|
||||
)
|
||||
ensure(
|
||||
ci_from.isValidAddressHash(msg_data.dest_af)
|
||||
or ci_from.isValidPubkey(msg_data.dest_af),
|
||||
self.isValidSwapDest(ci_from, msg_data.dest_af),
|
||||
"Invalid destination address",
|
||||
)
|
||||
if ci_to.curve_type() == Curves.ed25519:
|
||||
|
||||
@@ -240,8 +240,11 @@ class DebugTypes(IntEnum):
|
||||
OFFER_LOCK_2_VALUE_INC = auto()
|
||||
BID_STOP_AFTER_COIN_B_LOCK = auto()
|
||||
BID_DONT_SPEND_COIN_B_LOCK = auto()
|
||||
WAIT_FOR_COIN_B_LOCK_BEFORE_PREREFUND = auto()
|
||||
WAIT_FOR_COIN_B_LOCK_BEFORE_REFUND = auto()
|
||||
BID_DONT_SPEND_COIN_A_LOCK = auto()
|
||||
DONT_SEND_COIN_B_LOCK = auto()
|
||||
DONT_RELEASE_COIN_A_LOCK = auto()
|
||||
|
||||
|
||||
class NotificationTypes(IntEnum):
|
||||
|
||||
@@ -566,7 +566,7 @@ def getCoinIdFromTicker(ticker: str) -> str:
|
||||
raise ValueError(f"Unknown coin {ticker}")
|
||||
|
||||
|
||||
def getCoinIdFromName(name: str) -> str:
|
||||
def getCoinIdFromName(name: str) -> Coins:
|
||||
try:
|
||||
return name_map[name.lower()]
|
||||
except Exception:
|
||||
|
||||
@@ -1229,7 +1229,6 @@ class DBMethods:
|
||||
values = {}
|
||||
constraint_values = {}
|
||||
set_columns = []
|
||||
|
||||
for mc in inspect.getmembers(obj.__class__):
|
||||
mc_name, mc_obj = mc
|
||||
if not hasattr(mc_obj, "__sqlite3_column__"):
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
import base64
|
||||
import copy
|
||||
import hashlib
|
||||
import json
|
||||
import logging
|
||||
@@ -530,6 +531,16 @@ class BTCInterface(Secp256k1Interface):
|
||||
)
|
||||
return self.rpc("getblockheader", [block_hash])
|
||||
|
||||
def getPrevBlockInChain(self, block_header_in):
|
||||
block_header = copy.deeocopy(block_header_in)
|
||||
while True:
|
||||
previousblockhash = block_header.get("previousblockhash", None)
|
||||
if previousblockhash is None:
|
||||
raise RuntimeError("previousblockhash not in block_header")
|
||||
if block_header["confirmations"] > 0:
|
||||
return block_header
|
||||
block_header = self.rpc("getblockheader", [previousblockhash])
|
||||
|
||||
def getBlockHeaderAt(self, time_target: int, block_after=False):
|
||||
blockchaininfo = self.rpc("getblockchaininfo")
|
||||
last_block_header = self.rpc(
|
||||
@@ -1310,7 +1321,7 @@ class BTCInterface(Secp256k1Interface):
|
||||
vkbv=None,
|
||||
kbsf=None,
|
||||
):
|
||||
# lock refund swipe tx
|
||||
# Lock refund swipe tx
|
||||
# Sends the coinA locked coin to the follower
|
||||
|
||||
tx_lock_refund = self.loadTx(tx_lock_refund_bytes)
|
||||
@@ -1584,7 +1595,7 @@ class BTCInterface(Secp256k1Interface):
|
||||
)
|
||||
|
||||
if not self.compareFeeRates(fee_rate_paid, feerate):
|
||||
raise ValueError("Bad fee rate, expected: {}".format(feerate))
|
||||
raise ValueError(f"Bad fee rate, expected: {feerate}")
|
||||
|
||||
return txid, locked_coin, locked_n
|
||||
|
||||
@@ -1647,7 +1658,7 @@ class BTCInterface(Secp256k1Interface):
|
||||
)
|
||||
|
||||
if not self.compareFeeRates(fee_rate_paid, feerate):
|
||||
raise ValueError("Bad fee rate, expected: {}".format(feerate))
|
||||
raise ValueError(f"Bad fee rate, expected: {feerate}")
|
||||
|
||||
return True
|
||||
|
||||
@@ -1706,7 +1717,7 @@ class BTCInterface(Secp256k1Interface):
|
||||
)
|
||||
|
||||
if not self.compareFeeRates(fee_rate_paid, feerate):
|
||||
raise ValueError("Bad fee rate, expected: {}".format(feerate))
|
||||
raise ValueError(f"Bad fee rate, expected: {feerate}")
|
||||
|
||||
return True
|
||||
|
||||
|
||||
@@ -1403,7 +1403,7 @@ class DCRInterface(Secp256k1Interface):
|
||||
)
|
||||
|
||||
if not self.compareFeeRates(fee_rate_paid, feerate):
|
||||
raise ValueError("Bad fee rate, expected: {}".format(feerate))
|
||||
raise ValueError(f"Bad fee rate, expected: {feerate}")
|
||||
|
||||
return True
|
||||
|
||||
@@ -1472,7 +1472,7 @@ class DCRInterface(Secp256k1Interface):
|
||||
)
|
||||
|
||||
if not self.compareFeeRates(fee_rate_paid, feerate):
|
||||
raise ValueError("Bad fee rate, expected: {}".format(feerate))
|
||||
raise ValueError(f"Bad fee rate, expected: {feerate}")
|
||||
|
||||
return txid, locked_coin, locked_n
|
||||
|
||||
@@ -1533,7 +1533,7 @@ class DCRInterface(Secp256k1Interface):
|
||||
)
|
||||
|
||||
if not self.compareFeeRates(fee_rate_paid, feerate):
|
||||
raise ValueError("Bad fee rate, expected: {}".format(feerate))
|
||||
raise ValueError(f"Bad fee rate, expected: {feerate}")
|
||||
|
||||
return True
|
||||
|
||||
|
||||
@@ -658,7 +658,7 @@ class PARTInterfaceBlind(PARTInterface):
|
||||
|
||||
ensure(
|
||||
self.compareFeeRates(fee_rate_paid, feerate),
|
||||
"Bad fee rate, expected: {}".format(feerate),
|
||||
f"Bad fee rate, expected: {feerate}",
|
||||
)
|
||||
|
||||
return (
|
||||
@@ -734,7 +734,7 @@ class PARTInterfaceBlind(PARTInterface):
|
||||
fee_rate_paid = fee_paid * 1000 // vsize
|
||||
ensure(
|
||||
self.compareFeeRates(fee_rate_paid, feerate),
|
||||
"Bad fee rate, expected: {}".format(feerate),
|
||||
f"Bad fee rate, expected: {feerate}",
|
||||
)
|
||||
|
||||
return True
|
||||
@@ -958,7 +958,7 @@ class PARTInterfaceBlind(PARTInterface):
|
||||
fee_rate_paid = fee_paid * 1000 // vsize
|
||||
self._log.info("vsize, feerate: %ld, %ld", vsize, fee_rate_paid)
|
||||
if not self.compareFeeRates(fee_rate_paid, feerate):
|
||||
raise ValueError("Bad fee rate, expected: {}".format(feerate))
|
||||
raise ValueError(f"Bad fee rate, expected: {feerate}")
|
||||
|
||||
return True
|
||||
|
||||
|
||||
@@ -45,3 +45,21 @@ class BSXLogger(logging.Logger):
|
||||
def info_s(self, msg, *args, **kwargs):
|
||||
if self.safe_logs is False:
|
||||
self.info(msg, *args, **kwargs)
|
||||
|
||||
|
||||
class BSXLogAdapter(logging.LoggerAdapter):
|
||||
def __init__(self, logger, prefix):
|
||||
super().__init__(logger, {})
|
||||
self.prefix = prefix
|
||||
|
||||
def process(self, msg, kwargs):
|
||||
return f"{self.prefix} {msg}", kwargs
|
||||
|
||||
def addr(self, addr: str) -> str:
|
||||
return self.logger.addr(addr)
|
||||
|
||||
def id(self, concept_id: bytes, prefix: str = "") -> str:
|
||||
return self.logger.id(concept_id, prefix)
|
||||
|
||||
def info_s(self, msg, *args, **kwargs):
|
||||
return self.logger.info_s(msg, *args, **kwargs)
|
||||
|
||||
@@ -290,7 +290,7 @@ def wait_for_event(
|
||||
|
||||
|
||||
def wait_for_offer(delay_event, swap_client, offer_id, wait_for=20):
|
||||
logging.info("wait_for_offer %s", offer_id.hex())
|
||||
logging.info(f"wait_for_offer {offer_id.hex()}")
|
||||
for i in range(wait_for):
|
||||
if delay_event.is_set():
|
||||
raise ValueError("Test stopped.")
|
||||
|
||||
@@ -229,22 +229,24 @@ class Test(unittest.TestCase):
|
||||
== "0dde9df8660d3e0f28fe00d648b70e0323e9c192fe9b94f1cf7138515e877725"
|
||||
)
|
||||
|
||||
sum_secp256k1 = ci_btc.sumPubkeys(
|
||||
pk_secp256k1 = ci_btc.sumPubkeys(
|
||||
ci_btc.getPubkey(keys[0]), ci_btc.getPubkey(keys[1])
|
||||
)
|
||||
assert (
|
||||
sum_secp256k1.hex()
|
||||
pk_secp256k1.hex()
|
||||
== "028c30392e35620af0787b363a03cf9a695336759664436e1f609481c869541a5c"
|
||||
)
|
||||
|
||||
sum_ed25519 = ci_xmr.sumPubkeys(
|
||||
pk_ed25519 = ci_xmr.sumPubkeys(
|
||||
ci_xmr.getPubkey(keys[0]), ci_xmr.getPubkey(keys[1])
|
||||
)
|
||||
assert (
|
||||
sum_ed25519.hex()
|
||||
pk_ed25519.hex()
|
||||
== "4b2dd2dc9acc9be7efed4fdbfb96f0002aeb9e4c8638c5b24562a7158b283626"
|
||||
)
|
||||
|
||||
assert pk_secp256k1 == ci_btc.getPubkey(sum_secp256k1)
|
||||
|
||||
def test_ecdsa_otves(self):
|
||||
ci = self.ci_btc()
|
||||
vk_sign = ci.getNewRandomKey()
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2020-2024 tecnovert
|
||||
# Copyright (c) 2024-2025 The Basicswap developers
|
||||
# Copyright (c) 2024-2026 The Basicswap developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
@@ -263,9 +263,7 @@ def waitForXMRNode(rpc_offset, max_tries=7):
|
||||
except Exception as ex:
|
||||
if i < max_tries:
|
||||
logging.warning(
|
||||
"Can't connect to XMR RPC: %s. Retrying in %d second/s.",
|
||||
str(ex),
|
||||
(i + 1),
|
||||
f"Can't connect to XMR RPC: {ex}. Retrying in {i + 1} second/s."
|
||||
)
|
||||
time.sleep(i + 1)
|
||||
raise ValueError("waitForXMRNode failed")
|
||||
@@ -281,9 +279,7 @@ def waitForXMRWallet(rpc_offset, auth, max_tries=7):
|
||||
except Exception as ex:
|
||||
if i < max_tries:
|
||||
logging.warning(
|
||||
"Can't connect to XMR wallet RPC: %s. Retrying in %d second/s.",
|
||||
str(ex),
|
||||
(i + 1),
|
||||
f"Can't connect to XMR wallet RPC: {ex}. Retrying in {i + 1} second/s."
|
||||
)
|
||||
time.sleep(i + 1)
|
||||
raise ValueError("waitForXMRWallet failed")
|
||||
@@ -304,7 +300,7 @@ def run_coins_loop(cls):
|
||||
cls.coins_loop()
|
||||
except Exception as e:
|
||||
logging.warning("run_coins_loop " + str(e))
|
||||
test_delay_event.wait(1.0)
|
||||
test_delay_event.wait(cls.coins_loop_delay)
|
||||
|
||||
|
||||
def run_loop(cls):
|
||||
@@ -336,6 +332,7 @@ class BaseTest(unittest.TestCase):
|
||||
xmr_addr = None
|
||||
btc_addr = None
|
||||
ltc_addr = None
|
||||
coins_loop_delay = 1.0
|
||||
|
||||
@classmethod
|
||||
def getRandomPubkey(cls):
|
||||
@@ -345,7 +342,7 @@ class BaseTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
if signal_event.is_set():
|
||||
raise ValueError("Test has been cancelled.")
|
||||
raise ValueError("Test has been cancelled")
|
||||
test_delay_event.clear()
|
||||
random.seed(time.time())
|
||||
|
||||
@@ -400,7 +397,7 @@ class BaseTest(unittest.TestCase):
|
||||
cls.prepareTestDir()
|
||||
|
||||
try:
|
||||
logging.info("Preparing coin nodes.")
|
||||
logging.info("Preparing coin nodes")
|
||||
part_wallet_bin = "particl-wallet" + (".exe" if os.name == "nt" else "")
|
||||
for i in range(NUM_NODES):
|
||||
if not cls.restore_instance:
|
||||
@@ -411,7 +408,7 @@ class BaseTest(unittest.TestCase):
|
||||
part_wallet_bin,
|
||||
)
|
||||
):
|
||||
logging.warning(f"{part_wallet_bin} not found.")
|
||||
logging.warning(f"{part_wallet_bin} not found")
|
||||
else:
|
||||
try:
|
||||
callrpc_cli(
|
||||
@@ -623,10 +620,8 @@ class BaseTest(unittest.TestCase):
|
||||
)
|
||||
|
||||
for i in range(NUM_XMR_NODES):
|
||||
cls.xmr_wallet_auth.append(
|
||||
("test{0}".format(i), "test_pass{0}".format(i))
|
||||
)
|
||||
logging.info("Creating XMR wallet %i", i)
|
||||
cls.xmr_wallet_auth.append((f"test{i}", f"test_pass{i}"))
|
||||
logging.info(f"Creating XMR wallet {i}")
|
||||
|
||||
waitForXMRWallet(i, cls.xmr_wallet_auth[i])
|
||||
|
||||
@@ -732,7 +727,7 @@ class BaseTest(unittest.TestCase):
|
||||
wallet="wallet.dat",
|
||||
)
|
||||
num_blocks = 400 # Mine enough to activate segwit
|
||||
logging.info("Mining %d Bitcoin blocks to %s", num_blocks, cls.btc_addr)
|
||||
logging.info(f"Mining {num_blocks} Bitcoin blocks to {cls.btc_addr}")
|
||||
callnoderpc(
|
||||
0,
|
||||
"generatetoaddress",
|
||||
@@ -763,7 +758,7 @@ class BaseTest(unittest.TestCase):
|
||||
.ci(Coins.BTC)
|
||||
.pubkey_to_segwit_address(void_block_rewards_pubkey)
|
||||
)
|
||||
logging.info("Mining %d Bitcoin blocks to %s", num_blocks, cls.btc_addr)
|
||||
logging.info(f"Mining {num_blocks} Bitcoin blocks to {cls.btc_addr}")
|
||||
callnoderpc(
|
||||
0,
|
||||
"generatetoaddress",
|
||||
@@ -801,7 +796,7 @@ class BaseTest(unittest.TestCase):
|
||||
wallet="wallet.dat",
|
||||
)
|
||||
logging.info(
|
||||
"Mining %d Litecoin blocks to %s", num_blocks, cls.ltc_addr
|
||||
f"Mining {num_blocks} Litecoin blocks to {cls.ltc_addr}"
|
||||
)
|
||||
callnoderpc(
|
||||
0,
|
||||
|
||||
Reference in New Issue
Block a user