Final fix to refunds path, increase test coverage

This commit is contained in:
mainnet-pat 2024-10-30 05:37:01 +00:00 committed by nahuhh
parent 57513aeb06
commit ec1671911b
3 changed files with 69 additions and 56 deletions

View file

@ -3890,6 +3890,15 @@ class BasicSwap(BaseApp):
try: try:
txid = ci_from.publishTx(xmr_swap.a_lock_refund_tx) txid = ci_from.publishTx(xmr_swap.a_lock_refund_tx)
# bch txids change
if self.isBchXmrSwap(offer):
self.log.debug('Recomputing refund spend transaction and txid after submitting lock tx spend.')
tx = ci_from.loadTx(xmr_swap.a_lock_refund_spend_tx)
tx.vin[0].prevout.hash = b2i(xmr_swap.a_lock_refund_tx_id)
xmr_swap.a_lock_refund_spend_tx = tx.serialize_without_witness()
xmr_swap.a_lock_refund_spend_tx_id = ci_from.getTxid(xmr_swap.a_lock_refund_spend_tx)
self.log.info('Submitted coin a lock refund tx for bid {}'.format(bid_id.hex())) self.log.info('Submitted coin a lock refund tx for bid {}'.format(bid_id.hex()))
self.logBidEvent(bid.bid_id, EventLogTypes.LOCK_TX_A_REFUND_TX_PUBLISHED, '', session) self.logBidEvent(bid.bid_id, EventLogTypes.LOCK_TX_A_REFUND_TX_PUBLISHED, '', session)
bid.txns[TxTypes.XMR_SWAP_A_LOCK_REFUND] = SwapTx( bid.txns[TxTypes.XMR_SWAP_A_LOCK_REFUND] = SwapTx(
@ -4437,7 +4446,7 @@ class BasicSwap(BaseApp):
self.log.debug('Coin a lock tx spent by lock refund tx.') self.log.debug('Coin a lock tx spent by lock refund tx.')
# bch txids change # bch txids change
if self.isBchXmrSwap(offer): if self.isBchXmrSwap(offer):
self.log.debug('Recomputing refund spend transaction and txid after lock tx spend.') self.log.debug('Recomputing refund spend transaction and txid after lock tx spent.')
xmr_swap.a_lock_refund_tx_id = spending_txid xmr_swap.a_lock_refund_tx_id = spending_txid
xmr_swap.a_lock_refund_tx = bytes.fromhex(spend_txn_hex) xmr_swap.a_lock_refund_tx = bytes.fromhex(spend_txn_hex)
@ -5823,7 +5832,7 @@ class BasicSwap(BaseApp):
lock_tx_signed = ci_from.signTxWithWallet(xmr_swap.a_lock_tx) lock_tx_signed = ci_from.signTxWithWallet(xmr_swap.a_lock_tx)
txid_hex = ci_from.publishTx(lock_tx_signed) txid_hex = ci_from.publishTx(lock_tx_signed)
if txid_hex != b2h(xmr_swap.a_lock_tx_id): if txid_hex != b2h(xmr_swap.a_lock_tx_id):
self.log.info('Recomputing lock refund and lock spend transactions and txids after lock tx publish') self.log.info('Recomputing refund transactions and txids after lock tx publish')
xmr_swap.a_lock_tx = lock_tx_signed xmr_swap.a_lock_tx = lock_tx_signed
xmr_swap.a_lock_tx_id = bytes.fromhex(txid_hex) xmr_swap.a_lock_tx_id = bytes.fromhex(txid_hex)

View file

@ -57,17 +57,15 @@ from coincurve.ecdsaotves import (
ecdsaotves_rec_enc_key, ecdsaotves_rec_enc_key,
) )
def findOutput(tx, script_pk: bytes):
for i in range(len(tx.vout)):
if tx.vout[i].scriptPubKey == script_pk:
return i
return None
class BCHInterface(BTCInterface): class BCHInterface(BTCInterface):
@staticmethod @staticmethod
def coin_type(): def coin_type():
return Coins.BCH return Coins.BCH
@staticmethod
def xmr_swap_a_lock_spend_tx_vsize() -> int:
return 302
def __init__(self, coin_settings, network, swap_client=None): def __init__(self, coin_settings, network, swap_client=None):
super(BCHInterface, self).__init__(coin_settings, network, swap_client) super(BCHInterface, self).__init__(coin_settings, network, swap_client)
# No multiwallet support # No multiwallet support
@ -85,6 +83,17 @@ class BCHInterface(BTCInterface):
args = [label] args = [label]
return self.rpc_wallet('getnewaddress', args) return self.rpc_wallet('getnewaddress', args)
def getUnspentsByAddr(self):
unspent_addr = dict()
unspent = self.rpc_wallet('listunspent')
for u in unspent:
if u.get('spendable', False) is False:
continue
if 'address' not in u:
continue
unspent_addr[u['address']] = unspent_addr.get(u['address'], 0) + self.make_int(u['amount'], r=1)
return unspent_addr
# returns pkh # returns pkh
def decodeAddress(self, address: str) -> bytes: def decodeAddress(self, address: str) -> bytes:
return bytes(Address.from_string(address).payload) return bytes(Address.from_string(address).payload)

View file

@ -7,51 +7,28 @@
import random import random
import logging import logging
import unittest
from basicswap.chainparams import XMR_COIN from basicswap.chainparams import XMR_COIN
from basicswap.db import (
Concepts,
)
from basicswap.basicswap import ( from basicswap.basicswap import (
BidStates, BidStates,
Coins, Coins,
DebugTypes,
SwapTypes, SwapTypes,
) )
from basicswap.basicswap_util import (
TxLockTypes,
EventLogTypes,
)
from basicswap.util import ( from basicswap.util import (
COIN, COIN,
make_int,
format_amount,
) )
from basicswap.interface.base import Curves
from basicswap.util.crypto import sha256 from basicswap.util.crypto import sha256
from tests.basicswap.test_btc_xmr import BasicSwapTest from tests.basicswap.test_btc_xmr import BasicSwapTest
from tests.basicswap.util import (
read_json_api,
)
from tests.basicswap.common import ( from tests.basicswap.common import (
BCH_BASE_RPC_PORT, BCH_BASE_RPC_PORT,
abandon_all_swaps,
wait_for_bid, wait_for_bid,
wait_for_event,
wait_for_offer, wait_for_offer,
wait_for_balance,
wait_for_unspent,
wait_for_none_active,
BTC_BASE_RPC_PORT,
) )
from basicswap.contrib.test_framework.messages import ( from basicswap.contrib.test_framework.messages import (
ToHex, ToHex,
FromHex,
CTxIn, CTxIn,
COutPoint, COutPoint,
CTransaction, CTransaction,
CTxInWitness,
) )
from basicswap.contrib.test_framework.script import ( from basicswap.contrib.test_framework.script import (
CScript, CScript,
@ -64,8 +41,7 @@ from .test_xmr import BaseTest, test_delay_event, callnoderpc
from coincurve.ecdsaotves import ( from coincurve.ecdsaotves import (
ecdsaotves_enc_sign, ecdsaotves_enc_sign,
ecdsaotves_enc_verify, ecdsaotves_enc_verify,
ecdsaotves_dec_sig, ecdsaotves_dec_sig
ecdsaotves_rec_enc_key
) )
logger = logging.getLogger() logger = logging.getLogger()
@ -283,7 +259,7 @@ class TestBCH(BasicSwapTest):
def test_009_scantxoutset(self): def test_009_scantxoutset(self):
super().test_009_scantxoutset() super().test_009_scantxoutset()
def test_010_bch_txn_size(self): def test_010_txn_size(self):
logging.info('---------- Test {} txn_size'.format(Coins.BCH)) logging.info('---------- Test {} txn_size'.format(Coins.BCH))
swap_clients = self.swap_clients swap_clients = self.swap_clients
@ -335,7 +311,6 @@ class TestBCH(BasicSwapTest):
lock_tx = ci.fundSCLockTx(lock_tx, fee_rate) lock_tx = ci.fundSCLockTx(lock_tx, fee_rate)
lock_tx = ci.signTxWithWallet(lock_tx) lock_tx = ci.signTxWithWallet(lock_tx)
print(lock_tx.hex()) print(lock_tx.hex())
return
unspents_after = ci.rpc('listunspent') unspents_after = ci.rpc('listunspent')
assert (len(unspents) > len(unspents_after)) assert (len(unspents) > len(unspents_after))
@ -399,23 +374,6 @@ class TestBCH(BasicSwapTest):
assert (expect_size >= vsize_actual) assert (expect_size >= vsize_actual)
assert (expect_size - vsize_actual < 10) assert (expect_size - vsize_actual < 10)
# Test chain b (no-script) lock tx size
v = ci.getNewSecretKey()
s = ci.getNewSecretKey()
S = ci.getPubkey(s)
lock_tx_b_txid = ci.publishBLockTx(v, S, amount, fee_rate)
addr_out = ci.getNewAddress(True)
lock_tx_b_spend_txid = ci.spendBLockTx(lock_tx_b_txid, addr_out, v, s, amount, fee_rate, 0)
lock_tx_b_spend = ci.getTransaction(lock_tx_b_spend_txid)
if lock_tx_b_spend is None:
lock_tx_b_spend = ci.getWalletTransaction(lock_tx_b_spend_txid)
lock_tx_b_spend_decoded = ci.rpc('decoderawtransaction', [lock_tx_b_spend.hex()])
expect_size: int = ci.xmr_swap_b_lock_spend_tx_vsize()
assert (expect_size >= lock_tx_b_spend_decoded['size'])
assert (expect_size - lock_tx_b_spend_decoded['size'] < 10)
def test_011_p2sh(self): def test_011_p2sh(self):
# Not used in bsx for native-segwit coins # Not used in bsx for native-segwit coins
logging.info('---------- Test {} p2sh'.format(self.test_coin_from.name)) logging.info('---------- Test {} p2sh'.format(self.test_coin_from.name))
@ -548,7 +506,44 @@ class TestBCH(BasicSwapTest):
def test_04_a_follower_recover_b_lock_tx(self): def test_04_a_follower_recover_b_lock_tx(self):
super().test_04_a_follower_recover_b_lock_tx() super().test_04_a_follower_recover_b_lock_tx()
# does not work yet def test_04_b_follower_recover_b_lock_tx_reverse(self):
# def test_04_b_follower_recover_b_lock_tx_reverse(self): self.prepare_balance(Coins.BCH, 100.0, 1801, 1800)
# self.prepare_balance(Coins.BCH, 100.0, 1801, 1800) super().test_04_b_follower_recover_b_lock_tx_reverse()
# super().test_04_b_follower_recover_b_lock_tx_reverse()
def test_04_c_follower_recover_b_lock_tx_to_part(self):
super().test_04_c_follower_recover_b_lock_tx_to_part()
def test_04_d_follower_recover_b_lock_tx_from_part(self):
self.prepare_balance(Coins.BCH, 100.0, 1801, 1800)
super().test_04_d_follower_recover_b_lock_tx_from_part()
def test_05_self_bid(self):
self.prepare_balance(Coins.BCH, 100.0, 1801, 1800)
super().test_05_self_bid()
def test_05_self_bid_to_part(self):
self.prepare_balance(Coins.BCH, 100.0, 1801, 1800)
super().test_05_self_bid_to_part()
def test_05_self_bid_from_part(self):
self.prepare_balance(Coins.BCH, 100.0, 1801, 1800)
super().test_05_self_bid_from_part()
def test_05_self_bid_rev(self):
self.prepare_balance(Coins.BCH, 100.0, 1801, 1800)
super().test_05_self_bid_rev()
def test_06_preselect_inputs(self):
tla_from = self.test_coin_from.name
logging.info('---------- Test {} Preselected inputs'.format(tla_from))
logging.info('Skipped')
def test_07_expire_stuck_accepted(self):
super().test_07_expire_stuck_accepted()
def test_08_insufficient_funds(self):
super().test_08_insufficient_funds()
def test_08_insufficient_funds_rev(self):
self.prepare_balance(Coins.BCH, 100.0, 1801, 1800)
super().test_08_insufficient_funds_rev()