Compare commits

..

6 Commits

Author SHA1 Message Date
tecnovert 4930927339 Merge pull request #500 from tecnovert/fix4
fix: add more limits to split messages
2026-06-10 18:09:28 +00:00
tecnovert a2e6e730e3 Merge pull request #499 from tecnovert/fix3
fix: check if offer matches reverse state for incoming messages
2026-06-10 18:09:19 +00:00
tecnovert cbb6047ca7 Merge pull request #498 from tecnovert/refactor2
refactor: add haveSignedLockRefundTx
2026-06-10 18:09:06 +00:00
tecnovert a8e5723c7b fix: add more limits to split messages 2026-06-10 11:44:45 +02:00
tecnovert ac8216152c fix: check if offer matches reverse state for incoming messages 2026-06-09 21:16:20 +02:00
tecnovert 8cc5d808fa refactor: add haveSignedLockRefundTx 2026-06-09 19:20:25 +02:00
4 changed files with 93 additions and 54 deletions
+73 -51
View File
@@ -7938,8 +7938,7 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
return rv
else: # not XMR_SWAP_A_LOCK_REFUND in bid.txns
if (
len(xmr_swap.al_lock_refund_tx_sig) > 0
and len(xmr_swap.af_lock_refund_tx_sig) > 0
ci_from.haveSignedLockRefundTx(xmr_swap)
and bid.xmr_a_lock_tx is not None
and ci_from.isCsvLockMature(
offer.lock_type,
@@ -10094,6 +10093,14 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
kbsl_dleag_len: int = q[0]
kbsf_dleag_len: int = q[1]
q = cursor.execute(
"SELECT addr_from FROM offers WHERE offer_id = :offer_id",
{
"offer_id": bid.offer_id,
},
).fetchone()
offer_addr_from: str = q[0]
if bid.state == int(BidStates.BID_RECEIVING_ACC):
bid_type: str = "bid accept"
msg_type: int = int(XmrSplitMsgTypes.BID_ACCEPT)
@@ -10104,8 +10111,15 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
total_dleag_size: int = kbsf_dleag_len
q = cursor.execute(
"SELECT COUNT(*), SUM(LENGTH(dleag)) AS total_dleag_size FROM xmr_split_data WHERE bid_id = :bid_id AND msg_type = :msg_type",
{"bid_id": bid.bid_id, "msg_type": msg_type},
"SELECT COUNT(*), SUM(LENGTH(dleag)) AS total_dleag_size FROM xmr_split_data "
+ " WHERE bid_id = :bid_id AND msg_type = :msg_type "
+ " AND ((addr_from = :bid_addr AND addr_to = :offer_addr) OR (addr_from = :offer_addr AND addr_to = :bid_addr))",
{
"bid_id": bid.bid_id,
"msg_type": msg_type,
"bid_addr": bid.bid_addr,
"offer_addr": offer_addr_from,
},
).fetchone()
total_dleag_size += 0 if q[1] is None else q[1]
@@ -10941,43 +10955,36 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
ensure(xmr_offer, f"Adaptor-sig offer not found: {self.log.id(bid.offer_id)}.")
xmr_swap = self.queryOne(XmrSwap, cursor, {"bid_id": bid.bid_id})
ensure(xmr_swap, "Adaptor-sig swap not found: {}.".format(bid.bid_id.hex()))
ensure(xmr_swap, f"Adaptor-sig swap not found: {self.log.id(bid.bid_id)}")
reverse_bid: bool = self.is_reverse_ads_bid(offer.coin_from, offer.coin_to)
addr_expect_from: str = ""
if reverse_bid:
ci_from = self.ci(Coins(offer.coin_to))
ci_to = self.ci(Coins(offer.coin_from))
addr_expect_from = bid.bid_addr
addr_expect_to = offer.addr_from
else:
ensure(offer.was_sent, "Offer not sent: {}.".format(bid.offer_id.hex()))
ci_from = self.ci(Coins(offer.coin_from))
ci_to = self.ci(Coins(offer.coin_to))
addr_expect_from = offer.addr_from
addr_expect_to = bid.bid_addr
else:
ensure(offer.was_sent, f"Offer not sent: {self.log.id(bid.offer_id)}")
ci_from = self.ci(Coins(offer.coin_from))
ci_to = self.ci(Coins(offer.coin_to))
addr_expect_from = bid.bid_addr
addr_expect_to = offer.addr_from
if ci_to.curve_type() == Curves.ed25519:
if len(xmr_swap.kbsf_dleag) < ci_to.lengthDLEAG():
q = self.query(
XmrSplitData,
cursor,
{"bid_id": bid.bid_id, "msg_type": int(XmrSplitMsgTypes.BID)},
{
"bid_id": bid.bid_id,
"msg_type": int(XmrSplitMsgTypes.BID),
"addr_from": addr_expect_from,
"addr_to": addr_expect_to,
},
{"msg_sequence": "asc"},
)
for row in q:
ensure(
row.addr_to == addr_expect_from,
"Received on incorrect address, segment_id {}".format(
row.record_id
),
)
ensure(
row.addr_from == addr_expect_to,
"Sent from incorrect address, segment_id {}".format(
row.record_id
),
)
xmr_swap.kbsf_dleag += row.dleag
if not ci_to.verifyDLEAG(xmr_swap.kbsf_dleag):
@@ -11032,13 +11039,13 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
def receiveXmrBidAccept(self, bid, cursor) -> None:
# Follower receiving MSG1F and MSG2F
self.log.debug(f"Receiving adaptor-sig bid accept {self.log.id(bid.bid_id)}.")
self.log.debug(f"Receiving adaptor-sig bid accept {self.log.id(bid.bid_id)}")
offer, xmr_offer = self.getXmrOffer(bid.offer_id, cursor=cursor)
ensure(offer, f"Offer not found: {self.log.id(bid.offer_id)}.")
ensure(xmr_offer, f"Adaptor-sig offer not found: {self.log.id(bid.offer_id)}.")
ensure(xmr_offer, f"Adaptor-sig offer not found: {self.log.id(bid.offer_id)}")
xmr_swap = self.queryOne(XmrSwap, cursor, {"bid_id": bid.bid_id})
ensure(xmr_swap, "Adaptor-sig swap not found: {}.".format(bid.bid_id.hex()))
ensure(xmr_swap, f"Adaptor-sig swap not found: {self.log.id(bid.bid_id)}")
reverse_bid: bool = self.is_reverse_ads_bid(offer.coin_from, offer.coin_to)
ci_from = self.ci(offer.coin_to if reverse_bid else offer.coin_from)
@@ -11054,22 +11061,12 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
{
"bid_id": bid.bid_id,
"msg_type": int(XmrSplitMsgTypes.BID_ACCEPT),
"addr_from": addr_from,
"addr_to": addr_to,
},
order_by={"msg_sequence": "asc"},
)
for row in q:
ensure(
row.addr_to == addr_to,
"Received on incorrect address, segment_id {}".format(
row.record_id
),
)
ensure(
row.addr_from == addr_from,
"Sent from incorrect address, segment_id {}".format(
row.record_id
),
)
xmr_swap.kbsl_dleag += row.dleag
if not ci_to.verifyDLEAG(xmr_swap.kbsl_dleag):
raise ValueError("Invalid DLEAG proof.")
@@ -11136,9 +11133,11 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
offer_id = bid_data.offer_msg_id
offer, xmr_offer = self.getXmrOffer(offer_id)
ensure(offer and offer.was_sent, f"Offer not found: {self.log.id(offer_id)}.")
ensure(offer and offer.was_sent, f"Offer not found: {self.log.id(offer_id)}")
ensure(offer.swap_type == SwapTypes.XMR_SWAP, "Bid/offer swap type mismatch")
ensure(xmr_offer, f"Adaptor-sig offer not found: {self.log.id(offer_id)}.")
ensure(xmr_offer, f"Adaptor-sig offer not found: {self.log.id(offer_id)}")
reverse_bid: bool = self.is_reverse_ads_bid(offer.coin_from, offer.coin_to)
ensure(reverse_bid is False, f"Offer: {self.log.id(offer_id)} is reversed")
ci_from = self.ci(offer.coin_from)
ci_to = self.ci(offer.coin_to)
@@ -12641,7 +12640,25 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
# Validate data
ensure(len(msg_data.msg_id) == 28, "Bad msg_id length")
self.log.debug(f"for bid {self.log.id(msg_data.msg_id)}.")
self.log.debug(f"for bid {self.log.id(msg_data.msg_id)}")
max_dleag_proof_len: int = 48893 # coincurve.dleag.dleag_proof_len()
network_type: str = msg.get("msg_net", "smsg")
if network_type == "simplex":
max_data_size: int = 11000
min_data_size: int = 9000
else:
max_data_size: int = 17000
min_data_size: int = 16000
max_chunks: int = (max_dleag_proof_len + min_data_size - 1) // min_data_size
ensure(
len(msg_data.dleag) <= max_data_size,
f"Split message data too large: {len(msg_data.dleag)}",
)
ensure(
msg_data.sequence <= max_chunks,
f"Split message sequence too high: {msg_data.sequence}",
)
# TODO: Wait for bid msg to arrive first
@@ -12652,11 +12669,12 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
cursor = self.openDB()
try:
q = cursor.execute(
"SELECT COUNT(*) FROM xmr_split_data WHERE bid_id = :bid_id AND msg_type = :msg_type AND msg_sequence = :msg_sequence",
"SELECT COUNT(*) FROM xmr_split_data WHERE bid_id = :bid_id AND msg_type = :msg_type AND msg_sequence = :msg_sequence AND addr_from = :addr_from",
{
"bid_id": msg_data.msg_id,
"msg_type": msg_data.msg_type,
"msg_sequence": msg_data.sequence,
"addr_from": msg["from"],
},
).fetchone()
num_exists = q[0]
@@ -12772,9 +12790,11 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
offer_id = bid_data.offer_msg_id
offer, xmr_offer = self.getXmrOffer(offer_id)
ensure(offer and offer.was_sent, f"Offer not found: {self.log.id(offer_id)}.")
ensure(offer and offer.was_sent, f"Offer not found: {self.log.id(offer_id)}")
ensure(offer.swap_type == SwapTypes.XMR_SWAP, "Bid/offer swap type mismatch")
ensure(xmr_offer, f"Adaptor-sig offer not found: {self.log.id(offer_id)}.")
ensure(xmr_offer, f"Adaptor-sig offer not found: {self.log.id(offer_id)}")
reverse_bid: bool = self.is_reverse_ads_bid(offer.coin_from, offer.coin_to)
ensure(reverse_bid is True, f"Offer: {self.log.id(offer_id)} not reversed")
self.validateMessageNets(bid_data.message_nets)
@@ -12889,12 +12909,14 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
bid_id = msg_data.bid_msg_id
bid, xmr_swap = self.getXmrBid(bid_id)
ensure(bid, f"Bid not found: {self.log.id(bid_id)}.")
ensure(xmr_swap, f"Adaptor-sig swap not found: {self.log.id(bid_id)}.")
ensure(bid, f"Bid not found: {self.log.id(bid_id)}")
ensure(xmr_swap, f"Adaptor-sig swap not found: {self.log.id(bid_id)}")
offer, xmr_offer = self.getXmrOffer(bid.offer_id)
ensure(offer, f"Offer not found: {self.log.id(bid.offer_id)}.")
ensure(xmr_offer, f"Adaptor-sig offer not found: {self.log.id(bid.offer_id)}.")
ensure(offer, f"Offer not found: {self.log.id(bid.offer_id)}")
ensure(xmr_offer, f"Adaptor-sig offer not found: {self.log.id(bid.offer_id)}")
reverse_bid: bool = self.is_reverse_ads_bid(offer.coin_from, offer.coin_to)
ensure(reverse_bid is True, f"Offer: {self.log.id(bid.offer_id)} not reversed")
ensure(msg["to"] == bid.bid_addr, "Received on incorrect address")
ensure(msg["from"] == offer.addr_from, "Sent from incorrect address")
@@ -13119,14 +13141,14 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
raise ValueError("Invalid msg received {}.".format(msg["msgid"]))
return
network_type = msg.get("msg_net", "smsg")
network_type: str = msg.get("msg_net", "smsg")
if network_type == "smsg":
self.num_smsg_messages_received += 1
elif network_type == "simplex":
pass # Counted earlier, split between group and direct
else:
self.log.warning(f"processMsg unknown network: {network_type}")
msg_type = int(msg["hex"][:2], 16)
msg_type: int = int(msg["hex"][:2], 16)
if msg_type == MessageTypes.OFFER:
self.processOffer(msg)
-2
View File
@@ -492,8 +492,6 @@ class XmrSplitData(Table):
dleag = Column("blob")
created_at = Column("integer")
uc_1 = UniqueConstraint("bid_id", "msg_type", "msg_sequence")
class RevokedMessage(Table):
__tablename__ = "revoked_messages"
+15 -1
View File
@@ -192,9 +192,23 @@ class AdaptorSigInterface:
def getScriptLockRefundSwipeTxDummyWitness(self, script: bytes) -> List[bytes]:
return [bytes(72), b"", bytes(len(script))]
def getLockRefundVout(self, lock_refund_tx_data: bytes, vbkv: bytes):
def getLockRefundVout(self, lock_refund_tx_data: bytes, vbkv: bytes) -> int:
return 0
def haveSignedLockRefundTx(self, xmr_swap) -> bool:
if xmr_swap.a_lock_refund_tx is None:
return False
if (
xmr_swap.al_lock_refund_tx_sig is None
or xmr_swap.af_lock_refund_tx_sig is None
):
return False
return (
len(xmr_swap.al_lock_refund_tx_sig) > 0
and len(xmr_swap.af_lock_refund_tx_sig) > 0
)
class Secp256k1Interface(CoinInterface, AdaptorSigInterface):
def __init__(self, **kwargs):
+5
View File
@@ -1198,3 +1198,8 @@ class BCHInterface(BTCInterface):
txHex = tx.serialize_without_witness()
return self.signTxWithWallet(txHex)
def haveSignedLockRefundTx(self, xmr_swap) -> bool:
if xmr_swap.a_lock_refund_tx is None:
return False
return True