From a214866b08f7cc112d040f6e1a66e88ec8993246 Mon Sep 17 00:00:00 2001 From: mainnet-pat Date: Tue, 5 Nov 2024 18:41:07 +0000 Subject: [PATCH] Add support for mercy transactions for refund-refund path --- basicswap/basicswap.py | 8 ++++++++ basicswap/interface/bch.py | 40 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/basicswap/basicswap.py b/basicswap/basicswap.py index 30f506b..42a6e9d 100644 --- a/basicswap/basicswap.py +++ b/basicswap/basicswap.py @@ -3871,6 +3871,14 @@ class BasicSwap(BaseApp): ) self.saveBidInSession(bid_id, bid, session, xmr_swap) session.commit() + + if self.isBchXmrSwap(offer): + for_ed25519: bool = True if ci_to.curve_type() == Curves.ed25519 else False + kbsf = self.getPathKey(offer.coin_from, offer.coin_to, bid.created_at, xmr_swap.contract_count, KeyTypes.KBSF, for_ed25519) + + mercy_tx = ci_from.createMercyTx(xmr_swap.a_lock_refund_swipe_tx, h2b(txid), xmr_swap.a_lock_refund_tx_script, kbsf) + txid = ci_from.publishTx(mercy_tx) + self.log.info('Submitted mercy tx for bid %s, txid %s', bid_id.hex(), txid) except Exception as ex: self.log.debug('Trying to publish coin a lock refund swipe tx: %s', str(ex)) diff --git a/basicswap/interface/bch.py b/basicswap/interface/bch.py index df5eebc..fa5073a 100644 --- a/basicswap/interface/bch.py +++ b/basicswap/interface/bch.py @@ -45,7 +45,7 @@ from basicswap.interface.contrib.bch_test_framework.script import ( OP_CHECKSIG, OP_HASH256, ) -from basicswap.contrib.test_framework.script import CScript +from basicswap.contrib.test_framework.script import OP_RETURN, CScript from coincurve.keys import ( PrivateKey, PublicKey, @@ -469,7 +469,7 @@ class BCHInterface(BTCInterface): self._log.info('createSCLockRefundSpendToFTx %s:\n fee_rate, vsize, fee: %ld, %ld, %ld.', i2h(tx.sha256), tx_fee_rate, vsize, pay_fee) - return tx.serialize() + return tx.serialize_without_witness() def signTx(self, key_bytes: bytes, tx_bytes: bytes, input_n: int, prevout_script: bytes, prevout_value: int) -> bytes: # simply sign the entire tx data, as this is not a preimage signature @@ -798,3 +798,39 @@ class BCHInterface(BTCInterface): def isTxExistsError(self, err_str: str) -> bool: return 'transaction already in block chain' in err_str + + def createMercyTx(self, refund_swipe_tx_bytes: bytes, refund_swipe_tx_id: bytes, lock_refund_tx_script: bytes, keyshare: bytes) -> str: + refund_swipe_tx = self.loadTx(refund_swipe_tx_bytes) + refund_output_value = refund_swipe_tx.vout[0].nValue + refund_output_script = refund_swipe_tx.vout[0].scriptPubKey + + # mercy transaction size consisting of one input of freshly received funds, + # one op_return with mercy information, a dust output to the leader and change back to the follower + tx_size = 275 + dust_limit = 546 + + outValue = refund_output_value - tx_size - dust_limit + + _, out_1, _, _, _ = self.extractScriptLockScriptValues(lock_refund_tx_script) + + tx = CTransaction() + tx.nVersion = self.txVersion() + tx.vin.append(CTxIn(COutPoint(b2i(refund_swipe_tx_id), 0), + nSequence=0, + scriptSig=CScript(out_1))) + + tx.vout.append(self.txoType()(0, CScript([OP_RETURN, b'XBSW', keyshare]))) + tx.vout.append(self.txoType()(dust_limit, CScript(out_1))) + tx.vout.append(self.txoType()(outValue, refund_output_script)) + + size = tx_size + vsize = size + + pay_fee = size + + tx.rehash() + self._log.info('createMercyTx %s:\n fee_rate, vsize, fee: %ld, %ld, %ld.', + i2h(tx.sha256), 1, vsize, pay_fee) + + txHex = tx.serialize_without_witness() + return self.signTxWithWallet(txHex)