mirror of
https://github.com/basicswap/basicswap.git
synced 2025-11-05 10:28:10 +01:00
tests: Add more bid intent test cases.
Send bid intent amount and rate un-reversed.
This commit is contained in:
@@ -22,6 +22,7 @@ from basicswap.util import (
|
||||
make_int,
|
||||
format_amount,
|
||||
)
|
||||
from basicswap.interface import Curves
|
||||
from tests.basicswap.util import (
|
||||
read_json_api,
|
||||
)
|
||||
@@ -51,11 +52,24 @@ from .test_xmr import BaseTest, test_delay_event, callnoderpc
|
||||
logger = logging.getLogger()
|
||||
|
||||
|
||||
class BasicSwapTest(BaseTest):
|
||||
class TestFunctions(BaseTest):
|
||||
base_rpc_port = None
|
||||
|
||||
def getBalance(self, js_wallets, coin):
|
||||
return float(js_wallets[coin.name]['balance']) + float(js_wallets[coin.name]['unconfirmed'])
|
||||
def getBalance(self, js_wallets, coin) -> float:
|
||||
if coin == Coins.PART_BLIND:
|
||||
coin_ticker: str = 'PART'
|
||||
balance_type: str = 'blind_balance'
|
||||
unconfirmed_name: str = 'blind_unconfirmed'
|
||||
elif coin == Coins.PART_ANON:
|
||||
coin_ticker: str = 'PART'
|
||||
balance_type: str = 'anon_balance'
|
||||
unconfirmed_name: str = 'anon_pending'
|
||||
else:
|
||||
coin_ticker: str = coin.name
|
||||
balance_type: str = 'balance'
|
||||
unconfirmed_name: str = 'unconfirmed'
|
||||
|
||||
return float(js_wallets[coin_ticker][balance_type]) + float(js_wallets[coin_ticker][unconfirmed_name])
|
||||
|
||||
def callnoderpc(self, method, params=[], wallet=None, node_id=0):
|
||||
return callnoderpc(node_id, method, params, wallet, self.base_rpc_port)
|
||||
@@ -63,17 +77,276 @@ class BasicSwapTest(BaseTest):
|
||||
def mineBlock(self, num_blocks=1):
|
||||
self.callnoderpc('generatetoaddress', [num_blocks, self.btc_addr])
|
||||
|
||||
def prepare_balance(self, coin_ticker: str, amount: float, port_target_node: int, port_take_from_node: int) -> None:
|
||||
def prepare_balance(self, coin, amount: float, port_target_node: int, port_take_from_node: int) -> None:
|
||||
if coin == Coins.PART_BLIND:
|
||||
coin_ticker: str = 'PART'
|
||||
balance_type: str = 'blind_balance'
|
||||
address_type: str = 'stealth_address'
|
||||
type_to: str = 'blind'
|
||||
elif coin == Coins.PART_ANON:
|
||||
coin_ticker: str = 'PART'
|
||||
balance_type: str = 'anon_balance'
|
||||
address_type: str = 'stealth_address'
|
||||
type_to: str = 'anon'
|
||||
else:
|
||||
coin_ticker: str = coin.name
|
||||
balance_type: str = 'balance'
|
||||
address_type: str = 'deposit_address'
|
||||
js_w = read_json_api(port_target_node, 'wallets')
|
||||
if float(js_w[coin_ticker]['balance']) < amount:
|
||||
post_json = {
|
||||
'value': amount,
|
||||
'address': js_w[coin_ticker]['deposit_address'],
|
||||
'subfee': False,
|
||||
}
|
||||
json_rv = read_json_api(port_take_from_node, 'wallets/{}/withdraw'.format(coin_ticker.lower()), post_json)
|
||||
assert (len(json_rv['txid']) == 64)
|
||||
wait_for_balance(test_delay_event, 'http://127.0.0.1:{}/json/wallets/{}'.format(port_target_node, coin_ticker.lower()), 'balance', amount)
|
||||
if float(js_w[coin_ticker][balance_type]) >= amount:
|
||||
return
|
||||
post_json = {
|
||||
'value': amount,
|
||||
'address': js_w[coin_ticker][address_type],
|
||||
'subfee': False,
|
||||
}
|
||||
if coin in (Coins.PART_BLIND, Coins.PART_ANON):
|
||||
post_json['type_to'] = type_to
|
||||
json_rv = read_json_api(port_take_from_node, 'wallets/{}/withdraw'.format(coin_ticker.lower()), post_json)
|
||||
assert (len(json_rv['txid']) == 64)
|
||||
wait_for_balance(test_delay_event, 'http://127.0.0.1:{}/json/wallets/{}'.format(port_target_node, coin_ticker.lower()), balance_type, amount)
|
||||
|
||||
def do_test_01_full_swap(self, coin_from: Coins, coin_to: Coins) -> None:
|
||||
logging.info('---------- Test {} to {}'.format(coin_from.name, coin_to.name))
|
||||
|
||||
swap_clients = self.swap_clients
|
||||
reverse_bid: bool = coin_from in swap_clients[0].scriptless_coins
|
||||
ci_from = swap_clients[0].ci(coin_from)
|
||||
ci_to = swap_clients[1].ci(coin_to)
|
||||
ci_part0 = swap_clients[0].ci(Coins.PART)
|
||||
ci_part1 = swap_clients[1].ci(Coins.PART)
|
||||
|
||||
# Offerer sends the offer
|
||||
# Bidder sends the bid
|
||||
id_offerer: int = 0
|
||||
id_bidder: int = 1
|
||||
|
||||
# Leader sends the initial (chain a) lock tx.
|
||||
# Follower sends the participate (chain b) lock tx.
|
||||
id_leader: int = 1 if reverse_bid else 0
|
||||
id_follower: int = 0 if reverse_bid else 1
|
||||
logging.info(f'Offerer, bidder, leader, follower: {id_offerer}, {id_bidder}, {id_leader}, {id_follower}')
|
||||
|
||||
js_0 = read_json_api(1800, 'wallets')
|
||||
node0_from_before: float = self.getBalance(js_0, coin_from)
|
||||
|
||||
js_1 = read_json_api(1801, 'wallets')
|
||||
node1_from_before: float = self.getBalance(js_1, coin_from)
|
||||
|
||||
node0_sent_messages_before: int = ci_part0.rpc_callback('smsgoutbox', ['count',])['num_messages']
|
||||
node1_sent_messages_before: int = ci_part1.rpc_callback('smsgoutbox', ['count',])['num_messages']
|
||||
|
||||
amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1)
|
||||
rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1)
|
||||
offer_id = swap_clients[id_offerer].postOffer(coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP)
|
||||
wait_for_offer(test_delay_event, swap_clients[id_bidder], offer_id)
|
||||
offer = swap_clients[id_bidder].listOffers(filters={'offer_id': offer_id})[0]
|
||||
assert (offer.offer_id == offer_id)
|
||||
|
||||
bid_id = swap_clients[1].postXmrBid(offer_id, offer.amount_from)
|
||||
|
||||
wait_for_bid(test_delay_event, swap_clients[id_offerer], bid_id, BidStates.BID_RECEIVED)
|
||||
swap_clients[id_offerer].acceptBid(bid_id)
|
||||
|
||||
wait_for_bid(test_delay_event, swap_clients[id_offerer], bid_id, BidStates.SWAP_COMPLETED, wait_for=180)
|
||||
wait_for_bid(test_delay_event, swap_clients[id_bidder], bid_id, BidStates.SWAP_COMPLETED, sent=True)
|
||||
|
||||
amount_from = float(ci_from.format_amount(amt_swap))
|
||||
js_1_after = read_json_api(1801, 'wallets')
|
||||
node1_from_after = self.getBalance(js_1_after, coin_from)
|
||||
if coin_from is not Coins.PART: # TODO: staking
|
||||
assert (node1_from_after > node1_from_before + (amount_from - 0.05))
|
||||
|
||||
js_0_after = read_json_api(1800, 'wallets')
|
||||
node0_from_after: float = self.getBalance(js_0_after, coin_from)
|
||||
# TODO: Discard block rewards
|
||||
# assert (node0_from_after < node0_from_before - amount_from)
|
||||
|
||||
scale_from = 8
|
||||
amount_to = int((amt_swap * rate_swap) // (10 ** scale_from))
|
||||
amount_to_float = float(ci_to.format_amount(amount_to))
|
||||
node1_to_after: float = self.getBalance(js_1_after, coin_to)
|
||||
node1_to_before: float = self.getBalance(js_1, coin_to)
|
||||
if False: # TODO: set stakeaddress and xmr rewards to non wallet addresses
|
||||
assert (node1_to_after < node1_to_before - amount_to_float)
|
||||
|
||||
node0_sent_messages_after: int = ci_part0.rpc_callback('smsgoutbox', ['count',])['num_messages']
|
||||
node1_sent_messages_after: int = ci_part1.rpc_callback('smsgoutbox', ['count',])['num_messages']
|
||||
node0_sent_messages: int = node0_sent_messages_after - node0_sent_messages_before
|
||||
node1_sent_messages: int = node1_sent_messages_after - node1_sent_messages_before
|
||||
split_msgs: int = 2 if (ci_from.curve_type() != Curves.secp256k1 or ci_to.curve_type() != Curves.secp256k1) else 0
|
||||
assert (node0_sent_messages == (3 + split_msgs if reverse_bid else 4 + split_msgs))
|
||||
assert (node1_sent_messages == (4 + split_msgs if reverse_bid else 2 + split_msgs))
|
||||
|
||||
def do_test_02_leader_recover_a_lock_tx(self, coin_from: Coins, coin_to: Coins) -> None:
|
||||
logging.info('---------- Test {} to {} leader recovers coin a lock tx'.format(coin_from.name, coin_to.name))
|
||||
|
||||
swap_clients = self.swap_clients
|
||||
reverse_bid: bool = coin_from in swap_clients[0].scriptless_coins
|
||||
ci_from = swap_clients[0].ci(coin_from)
|
||||
ci_to = swap_clients[0].ci(coin_to)
|
||||
|
||||
id_offerer: int = 0
|
||||
id_bidder: int = 1
|
||||
id_leader: int = 1 if reverse_bid else 0
|
||||
id_follower: int = 0 if reverse_bid else 1
|
||||
logging.info(f'Offerer, bidder, leader, follower: {id_offerer}, {id_bidder}, {id_leader}, {id_follower}')
|
||||
|
||||
js_wl_before = read_json_api(1800 + id_leader, 'wallets')
|
||||
wl_from_before = self.getBalance(js_wl_before, coin_from)
|
||||
|
||||
amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1)
|
||||
rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1)
|
||||
offer_id = swap_clients[id_offerer].postOffer(
|
||||
coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP,
|
||||
lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, lock_value=32)
|
||||
wait_for_offer(test_delay_event, swap_clients[id_bidder], offer_id)
|
||||
offer = swap_clients[id_bidder].getOffer(offer_id)
|
||||
|
||||
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)
|
||||
|
||||
swap_clients[id_follower].setBidDebugInd(bid_id, DebugTypes.BID_STOP_AFTER_COIN_A_LOCK)
|
||||
swap_clients[id_offerer].acceptBid(bid_id)
|
||||
|
||||
leader_sent_bid: bool = True if reverse_bid else False
|
||||
wait_for_bid(test_delay_event, swap_clients[id_leader], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, sent=leader_sent_bid, wait_for=180)
|
||||
wait_for_bid(test_delay_event, swap_clients[id_follower], bid_id, [BidStates.BID_STALLED_FOR_TEST, BidStates.XMR_SWAP_FAILED], sent=(not leader_sent_bid))
|
||||
|
||||
js_wl_after = read_json_api(1800 + id_leader, 'wallets')
|
||||
wl_from_after = self.getBalance(js_wl_after, coin_from)
|
||||
|
||||
# TODO: Discard block rewards
|
||||
# assert (node0_from_before - node0_from_after < 0.02)
|
||||
|
||||
def do_test_03_follower_recover_a_lock_tx(self, coin_from, coin_to, lock_value=32):
|
||||
logging.info('---------- Test {} to {} follower recovers coin a lock tx'.format(coin_from.name, coin_to.name))
|
||||
|
||||
# Leader is too slow to recover the coin a lock tx and follower swipes it
|
||||
# coin b lock tx remains unspent
|
||||
|
||||
swap_clients = self.swap_clients
|
||||
reverse_bid: bool = coin_from in swap_clients[0].scriptless_coins
|
||||
ci_from = swap_clients[0].ci(coin_from)
|
||||
ci_to = swap_clients[0].ci(coin_to)
|
||||
|
||||
id_offerer: int = 0
|
||||
id_bidder: int = 1
|
||||
id_leader: int = 1 if reverse_bid else 0
|
||||
id_follower: int = 0 if reverse_bid else 1
|
||||
logging.info(f'Offerer, bidder, leader, follower: {id_offerer}, {id_bidder}, {id_leader}, {id_follower}')
|
||||
|
||||
js_w0_before = read_json_api(1800, 'wallets')
|
||||
js_w1_before = read_json_api(1801, 'wallets')
|
||||
|
||||
amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1)
|
||||
rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1)
|
||||
offer_id = swap_clients[id_offerer].postOffer(
|
||||
coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP,
|
||||
lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, lock_value=lock_value)
|
||||
wait_for_offer(test_delay_event, swap_clients[1], offer_id)
|
||||
offer = swap_clients[id_bidder].getOffer(offer_id)
|
||||
|
||||
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)
|
||||
|
||||
swap_clients[id_follower].setBidDebugInd(bid_id, DebugTypes.BID_STOP_AFTER_COIN_A_LOCK)
|
||||
swap_clients[id_leader].setBidDebugInd(bid_id, DebugTypes.BID_DONT_SPEND_COIN_A_LOCK_REFUND)
|
||||
|
||||
swap_clients[id_offerer].acceptBid(bid_id)
|
||||
|
||||
leader_sent_bid: bool = True if reverse_bid else False
|
||||
wait_for_bid(test_delay_event, swap_clients[id_leader], bid_id, BidStates.BID_STALLED_FOR_TEST, wait_for=180, sent=leader_sent_bid)
|
||||
wait_for_bid(test_delay_event, swap_clients[id_follower], bid_id, BidStates.XMR_SWAP_FAILED_SWIPED, wait_for=80, sent=(not leader_sent_bid))
|
||||
|
||||
js_w1_after = read_json_api(1801, 'wallets')
|
||||
|
||||
node1_from_before = self.getBalance(js_w1_before, coin_from)
|
||||
node1_from_after = self.getBalance(js_w1_after, coin_from)
|
||||
amount_from = float(format_amount(amt_swap, 8))
|
||||
# TODO: Discard block rewards
|
||||
# assert (node1_from_after - node1_from_before > (amount_from - 0.02))
|
||||
|
||||
swap_clients[0].abandonBid(bid_id)
|
||||
|
||||
wait_for_none_active(test_delay_event, 1800)
|
||||
wait_for_none_active(test_delay_event, 1801)
|
||||
|
||||
def do_test_04_follower_recover_b_lock_tx(self, coin_from, coin_to):
|
||||
logging.info('---------- Test {} to {} follower recovers coin b lock tx'.format(coin_from.name, coin_to.name))
|
||||
|
||||
swap_clients = self.swap_clients
|
||||
reverse_bid: bool = coin_from in swap_clients[0].scriptless_coins
|
||||
ci_from = swap_clients[0].ci(coin_from)
|
||||
ci_to = swap_clients[0].ci(coin_to)
|
||||
|
||||
id_offerer: int = 0
|
||||
id_bidder: int = 1
|
||||
id_leader: int = 1 if reverse_bid else 0
|
||||
id_follower: int = 0 if reverse_bid else 1
|
||||
logging.info(f'Offerer, bidder, leader, follower: {id_offerer}, {id_bidder}, {id_leader}, {id_follower}')
|
||||
|
||||
js_w0_before = read_json_api(1800, 'wallets')
|
||||
js_w1_before = read_json_api(1801, 'wallets')
|
||||
|
||||
amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1)
|
||||
rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1)
|
||||
offer_id = swap_clients[id_offerer].postOffer(
|
||||
coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP,
|
||||
lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, lock_value=32)
|
||||
wait_for_offer(test_delay_event, swap_clients[id_bidder], offer_id)
|
||||
offer = swap_clients[id_bidder].getOffer(offer_id)
|
||||
|
||||
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)
|
||||
|
||||
swap_clients[id_follower].setBidDebugInd(bid_id, DebugTypes.CREATE_INVALID_COIN_B_LOCK)
|
||||
swap_clients[id_offerer].acceptBid(bid_id)
|
||||
|
||||
leader_sent_bid: bool = True if reverse_bid else False
|
||||
wait_for_bid(test_delay_event, swap_clients[id_leader], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, wait_for=200, sent=leader_sent_bid)
|
||||
wait_for_bid(test_delay_event, swap_clients[id_follower], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, sent=(not leader_sent_bid))
|
||||
|
||||
js_w0_after = read_json_api(1800, 'wallets')
|
||||
js_w1_after = read_json_api(1801, 'wallets')
|
||||
|
||||
node0_from_before = self.getBalance(js_w0_before, coin_from)
|
||||
node0_from_after = self.getBalance(js_w0_after, coin_from)
|
||||
logging.info('node0 end coin_from balance {}, diff {}'.format(node0_from_after, node0_from_after - node0_from_before))
|
||||
node0_to_before = self.getBalance(js_w0_before, coin_to)
|
||||
node0_to_after = self.getBalance(js_w0_after, coin_to)
|
||||
logging.info('node0 end coin_to balance {}, diff {}'.format(node0_to_after, node0_to_after - node0_to_before))
|
||||
max_fee_from: float = 0.1 if coin_from == Coins.PART_ANON else 0.02
|
||||
if coin_from != Coins.PART: # TODO: Discard block rewards
|
||||
assert (node0_from_before - node0_from_after < max_fee_from)
|
||||
|
||||
node1_from_before = self.getBalance(js_w1_before, coin_from)
|
||||
node1_from_after = self.getBalance(js_w1_after, coin_from)
|
||||
logging.info('node1 end coin_from balance {}, diff {}'.format(node1_from_after, node1_from_after - node1_from_before))
|
||||
node1_to_before = self.getBalance(js_w1_before, coin_to)
|
||||
node1_to_after = self.getBalance(js_w1_after, coin_to)
|
||||
logging.info('node1 end coin_to balance {}, diff {}'.format(node1_to_after, node1_to_after - node1_to_before))
|
||||
|
||||
max_fee_to: float = 0.1 if coin_to == Coins.PART_ANON else 0.02
|
||||
assert (node1_to_before - node1_to_after < max_fee_to)
|
||||
|
||||
def do_test_05_self_bid(self, coin_from, coin_to):
|
||||
logging.info('---------- Test {} to {} same client'.format(coin_from.name, coin_to.name))
|
||||
|
||||
swap_clients = self.swap_clients
|
||||
ci_from = swap_clients[0].ci(coin_from)
|
||||
ci_to = swap_clients[0].ci(coin_to)
|
||||
|
||||
amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1)
|
||||
rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1)
|
||||
|
||||
offer_id = swap_clients[1].postOffer(coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP, auto_accept_bids=True)
|
||||
bid_id = swap_clients[1].postXmrBid(offer_id, amt_swap)
|
||||
|
||||
wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, wait_for=180)
|
||||
|
||||
|
||||
class BasicSwapTest(TestFunctions):
|
||||
|
||||
def test_001_nested_segwit(self):
|
||||
logging.info('---------- Test {} p2sh nested segwit'.format(self.test_coin_from.name))
|
||||
@@ -275,83 +548,6 @@ class BasicSwapTest(BaseTest):
|
||||
rv = read_json_api(1800, 'getcoinseed', {'coin': 'XMR'})
|
||||
assert (rv['address'] == '47H7UDLzYEsR28BWttxp59SP1UVSxs4VKDJYSfmz7Wd4Fue5VWuoV9x9eejunwzVSmHWN37gBkaAPNf9VD4bTvwQKsBVWyK')
|
||||
|
||||
def do_test_01_full_swap(self, coin_from: Coins, coin_to: Coins) -> None:
|
||||
logging.info('---------- Test {} to {}'.format(coin_from.name, coin_to.name))
|
||||
|
||||
swap_clients = self.swap_clients
|
||||
reverse_bid: bool = coin_from in swap_clients[0].scriptless_coins
|
||||
ci_from = swap_clients[0].ci(coin_from)
|
||||
ci_to = swap_clients[1].ci(coin_to)
|
||||
ci_part0 = swap_clients[0].ci(Coins.PART)
|
||||
ci_part1 = swap_clients[1].ci(Coins.PART)
|
||||
|
||||
# Offerer sends the offer
|
||||
# Bidder sends the bid
|
||||
id_offerer: int = 0
|
||||
id_bidder: int = 1
|
||||
|
||||
# Leader sends the initial (chain a) lock tx.
|
||||
# Follower sends the participate (chain b) lock tx.
|
||||
id_leader: int = 1 if reverse_bid else 0
|
||||
id_follower: int = 0 if reverse_bid else 1
|
||||
logging.info(f'Offerer, bidder, leader, follower: {id_offerer}, {id_bidder}, {id_leader}, {id_follower}')
|
||||
|
||||
js_0 = read_json_api(1800, 'wallets')
|
||||
node0_from_before = self.getBalance(js_0, coin_from)
|
||||
|
||||
js_1 = read_json_api(1801, 'wallets')
|
||||
node1_from_before = self.getBalance(js_1, coin_from)
|
||||
|
||||
js_0_to = read_json_api(1800, 'wallets/{}'.format(coin_to.name.lower()))
|
||||
js_1_to = read_json_api(1801, 'wallets/{}'.format(coin_to.name.lower()))
|
||||
|
||||
node0_sent_messages_before: int = ci_part0.rpc_callback('smsgoutbox', ['count',])['num_messages']
|
||||
node1_sent_messages_before: int = ci_part1.rpc_callback('smsgoutbox', ['count',])['num_messages']
|
||||
|
||||
amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1)
|
||||
rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1)
|
||||
offer_id = swap_clients[id_offerer].postOffer(coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP)
|
||||
wait_for_offer(test_delay_event, swap_clients[id_bidder], offer_id)
|
||||
offer = swap_clients[id_bidder].listOffers(filters={'offer_id': offer_id})[0]
|
||||
assert (offer.offer_id == offer_id)
|
||||
|
||||
bid_id = swap_clients[1].postXmrBid(offer_id, offer.amount_from)
|
||||
|
||||
wait_for_bid(test_delay_event, swap_clients[id_offerer], bid_id, BidStates.BID_RECEIVED)
|
||||
swap_clients[id_offerer].acceptBid(bid_id)
|
||||
|
||||
wait_for_bid(test_delay_event, swap_clients[id_offerer], bid_id, BidStates.SWAP_COMPLETED, wait_for=180)
|
||||
wait_for_bid(test_delay_event, swap_clients[id_bidder], bid_id, BidStates.SWAP_COMPLETED, sent=True)
|
||||
|
||||
amount_from = float(ci_from.format_amount(amt_swap))
|
||||
js_1 = read_json_api(1801, 'wallets')
|
||||
node1_from_after = self.getBalance(js_1, coin_from)
|
||||
if coin_from is not Coins.PART: # TODO: staking
|
||||
assert (node1_from_after > node1_from_before + (amount_from - 0.05))
|
||||
|
||||
js_0 = read_json_api(1800, 'wallets')
|
||||
node0_from_after = self.getBalance(js_0, coin_from)
|
||||
# TODO: Discard block rewards
|
||||
# assert (node0_from_after < node0_from_before - amount_from)
|
||||
|
||||
js_0_to_after = read_json_api(1800, 'wallets/{}'.format(coin_to.name.lower()))
|
||||
js_1_to_after = read_json_api(1801, 'wallets/{}'.format(coin_to.name.lower()))
|
||||
|
||||
scale_from = 8
|
||||
amount_to = int((amt_swap * rate_swap) // (10 ** scale_from))
|
||||
amount_to_float = float(ci_to.format_amount(amount_to))
|
||||
node1_to_after = float(js_1_to_after['unconfirmed']) + float(js_1_to_after['balance'])
|
||||
node1_to_before = float(js_1_to['unconfirmed']) + float(js_1_to['balance'])
|
||||
if False: # TODO: set stakeaddress and xmr rewards to non wallet addresses
|
||||
assert (node1_to_after < node1_to_before - amount_to_float)
|
||||
|
||||
node0_sent_messages_after: int = ci_part0.rpc_callback('smsgoutbox', ['count',])['num_messages']
|
||||
node1_sent_messages_after: int = ci_part1.rpc_callback('smsgoutbox', ['count',])['num_messages']
|
||||
node0_sent_messages: int = node0_sent_messages_after - node0_sent_messages_before
|
||||
node1_sent_messages: int = node1_sent_messages_after - node1_sent_messages_before
|
||||
assert (node0_sent_messages == (5 if reverse_bid else 6))
|
||||
assert (node1_sent_messages == (6 if reverse_bid else 4))
|
||||
|
||||
def test_01_a_full_swap(self):
|
||||
if not self.has_segwit:
|
||||
return
|
||||
@@ -360,7 +556,7 @@ class BasicSwapTest(BaseTest):
|
||||
def test_01_b_full_swap_reverse(self):
|
||||
if not self.has_segwit:
|
||||
return
|
||||
self.prepare_balance(Coins.XMR.name, 100.0, 1800, 1801)
|
||||
self.prepare_balance(Coins.XMR, 100.0, 1800, 1801)
|
||||
self.do_test_01_full_swap(Coins.XMR, self.test_coin_from)
|
||||
|
||||
def test_01_c_full_swap_to_part(self):
|
||||
@@ -371,47 +567,6 @@ class BasicSwapTest(BaseTest):
|
||||
def test_01_d_full_swap_from_part(self):
|
||||
self.do_test_01_full_swap(Coins.PART, self.test_coin_from)
|
||||
|
||||
def do_test_02_leader_recover_a_lock_tx(self, coin_from: Coins, coin_to: Coins) -> None:
|
||||
logging.info('---------- Test {} to {} leader recovers coin a lock tx'.format(coin_from.name, coin_to.name))
|
||||
|
||||
swap_clients = self.swap_clients
|
||||
reverse_bid: bool = coin_from in swap_clients[0].scriptless_coins
|
||||
ci_from = swap_clients[0].ci(coin_from)
|
||||
ci_to = swap_clients[0].ci(coin_to)
|
||||
|
||||
id_offerer: int = 0
|
||||
id_bidder: int = 1
|
||||
id_leader: int = 1 if reverse_bid else 0
|
||||
id_follower: int = 0 if reverse_bid else 1
|
||||
logging.info(f'Offerer, bidder, leader, follower: {id_offerer}, {id_bidder}, {id_leader}, {id_follower}')
|
||||
|
||||
js_wl_before = read_json_api(1800 + id_leader, 'wallets')
|
||||
wl_from_before = self.getBalance(js_wl_before, coin_from)
|
||||
|
||||
amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1)
|
||||
rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1)
|
||||
offer_id = swap_clients[id_offerer].postOffer(
|
||||
coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP,
|
||||
lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, lock_value=32)
|
||||
wait_for_offer(test_delay_event, swap_clients[id_bidder], offer_id)
|
||||
offer = swap_clients[id_bidder].getOffer(offer_id)
|
||||
|
||||
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)
|
||||
|
||||
swap_clients[id_follower].setBidDebugInd(bid_id, DebugTypes.BID_STOP_AFTER_COIN_A_LOCK)
|
||||
swap_clients[id_offerer].acceptBid(bid_id)
|
||||
|
||||
leader_sent_bid: bool = True if reverse_bid else False
|
||||
wait_for_bid(test_delay_event, swap_clients[id_leader], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, sent=leader_sent_bid, wait_for=180)
|
||||
wait_for_bid(test_delay_event, swap_clients[id_follower], bid_id, [BidStates.BID_STALLED_FOR_TEST, BidStates.XMR_SWAP_FAILED], sent=(not leader_sent_bid))
|
||||
|
||||
js_wl_after = read_json_api(1800 + id_leader, 'wallets')
|
||||
wl_from_after = self.getBalance(js_wl_after, coin_from)
|
||||
|
||||
# TODO: Discard block rewards
|
||||
# assert (node0_from_before - node0_from_after < 0.02)
|
||||
|
||||
def test_02_a_leader_recover_a_lock_tx(self):
|
||||
if not self.has_segwit:
|
||||
return
|
||||
@@ -420,7 +575,7 @@ class BasicSwapTest(BaseTest):
|
||||
def test_02_b_leader_recover_a_lock_tx_reverse(self):
|
||||
if not self.has_segwit:
|
||||
return
|
||||
self.prepare_balance(Coins.XMR.name, 100.0, 1800, 1801)
|
||||
self.prepare_balance(Coins.XMR, 100.0, 1800, 1801)
|
||||
self.do_test_02_leader_recover_a_lock_tx(Coins.XMR, self.test_coin_from)
|
||||
|
||||
def test_02_c_leader_recover_a_lock_tx_to_part(self):
|
||||
@@ -431,59 +586,6 @@ class BasicSwapTest(BaseTest):
|
||||
def test_02_leader_recover_a_lock_tx_from_part(self):
|
||||
self.do_test_02_leader_recover_a_lock_tx(Coins.PART, self.test_coin_from)
|
||||
|
||||
def do_test_03_follower_recover_a_lock_tx(self, coin_from, coin_to):
|
||||
logging.info('---------- Test {} to {} follower recovers coin a lock tx'.format(coin_from.name, coin_to.name))
|
||||
|
||||
# Leader is too slow to recover the coin a lock tx and follower swipes it
|
||||
# coin b lock tx remains unspent
|
||||
|
||||
swap_clients = self.swap_clients
|
||||
reverse_bid: bool = coin_from in swap_clients[0].scriptless_coins
|
||||
ci_from = swap_clients[0].ci(coin_from)
|
||||
ci_to = swap_clients[0].ci(coin_to)
|
||||
|
||||
id_offerer: int = 0
|
||||
id_bidder: int = 1
|
||||
id_leader: int = 1 if reverse_bid else 0
|
||||
id_follower: int = 0 if reverse_bid else 1
|
||||
logging.info(f'Offerer, bidder, leader, follower: {id_offerer}, {id_bidder}, {id_leader}, {id_follower}')
|
||||
|
||||
js_w0_before = read_json_api(1800, 'wallets')
|
||||
js_w1_before = read_json_api(1801, 'wallets')
|
||||
|
||||
amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1)
|
||||
rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1)
|
||||
offer_id = swap_clients[id_offerer].postOffer(
|
||||
coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP,
|
||||
lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, lock_value=32)
|
||||
wait_for_offer(test_delay_event, swap_clients[1], offer_id)
|
||||
offer = swap_clients[id_bidder].getOffer(offer_id)
|
||||
|
||||
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)
|
||||
|
||||
swap_clients[id_follower].setBidDebugInd(bid_id, DebugTypes.BID_STOP_AFTER_COIN_A_LOCK)
|
||||
swap_clients[id_leader].setBidDebugInd(bid_id, DebugTypes.BID_DONT_SPEND_COIN_A_LOCK_REFUND)
|
||||
|
||||
swap_clients[id_offerer].acceptBid(bid_id)
|
||||
|
||||
leader_sent_bid: bool = True if reverse_bid else False
|
||||
wait_for_bid(test_delay_event, swap_clients[id_leader], bid_id, BidStates.BID_STALLED_FOR_TEST, wait_for=180, sent=leader_sent_bid)
|
||||
wait_for_bid(test_delay_event, swap_clients[id_follower], bid_id, BidStates.XMR_SWAP_FAILED_SWIPED, wait_for=80, sent=(not leader_sent_bid))
|
||||
|
||||
js_w1_after = read_json_api(1801, 'wallets')
|
||||
|
||||
node1_from_before = self.getBalance(js_w1_before, coin_from)
|
||||
node1_from_after = self.getBalance(js_w1_after, coin_from)
|
||||
amount_from = float(format_amount(amt_swap, 8))
|
||||
# TODO: Discard block rewards
|
||||
# assert (node1_from_after - node1_from_before > (amount_from - 0.02))
|
||||
|
||||
swap_clients[0].abandonBid(bid_id)
|
||||
|
||||
wait_for_none_active(test_delay_event, 1800)
|
||||
wait_for_none_active(test_delay_event, 1801)
|
||||
|
||||
def test_03_a_follower_recover_a_lock_tx(self):
|
||||
if not self.has_segwit:
|
||||
return
|
||||
@@ -492,7 +594,7 @@ class BasicSwapTest(BaseTest):
|
||||
def test_03_b_follower_recover_a_lock_tx_reverse(self):
|
||||
if not self.has_segwit:
|
||||
return
|
||||
self.prepare_balance(Coins.XMR.name, 100.0, 1800, 1801)
|
||||
self.prepare_balance(Coins.XMR, 100.0, 1800, 1801)
|
||||
self.do_test_03_follower_recover_a_lock_tx(Coins.XMR, self.test_coin_from)
|
||||
|
||||
def test_03_c_follower_recover_a_lock_tx_to_part(self):
|
||||
@@ -503,61 +605,6 @@ class BasicSwapTest(BaseTest):
|
||||
def test_03_d_follower_recover_a_lock_tx_from_part(self):
|
||||
self.do_test_03_follower_recover_a_lock_tx(Coins.PART, self.test_coin_from)
|
||||
|
||||
def do_test_04_follower_recover_b_lock_tx(self, coin_from, coin_to):
|
||||
logging.info('---------- Test {} to {} follower recovers coin b lock tx'.format(coin_from.name, coin_to.name))
|
||||
|
||||
swap_clients = self.swap_clients
|
||||
reverse_bid: bool = coin_from in swap_clients[0].scriptless_coins
|
||||
ci_from = swap_clients[0].ci(coin_from)
|
||||
ci_to = swap_clients[0].ci(coin_to)
|
||||
|
||||
id_offerer: int = 0
|
||||
id_bidder: int = 1
|
||||
id_leader: int = 1 if reverse_bid else 0
|
||||
id_follower: int = 0 if reverse_bid else 1
|
||||
logging.info(f'Offerer, bidder, leader, follower: {id_offerer}, {id_bidder}, {id_leader}, {id_follower}')
|
||||
|
||||
js_w0_before = read_json_api(1800, 'wallets')
|
||||
js_w1_before = read_json_api(1801, 'wallets')
|
||||
|
||||
amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1)
|
||||
rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1)
|
||||
offer_id = swap_clients[id_offerer].postOffer(
|
||||
coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP,
|
||||
lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, lock_value=32)
|
||||
wait_for_offer(test_delay_event, swap_clients[id_bidder], offer_id)
|
||||
offer = swap_clients[id_bidder].getOffer(offer_id)
|
||||
|
||||
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)
|
||||
|
||||
swap_clients[id_follower].setBidDebugInd(bid_id, DebugTypes.CREATE_INVALID_COIN_B_LOCK)
|
||||
swap_clients[id_offerer].acceptBid(bid_id)
|
||||
|
||||
leader_sent_bid: bool = True if reverse_bid else False
|
||||
wait_for_bid(test_delay_event, swap_clients[id_leader], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, wait_for=200, sent=leader_sent_bid)
|
||||
wait_for_bid(test_delay_event, swap_clients[id_follower], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, sent=(not leader_sent_bid))
|
||||
|
||||
js_w0_after = read_json_api(1800, 'wallets')
|
||||
js_w1_after = read_json_api(1801, 'wallets')
|
||||
|
||||
node0_from_before = self.getBalance(js_w0_before, coin_from)
|
||||
node0_from_after = self.getBalance(js_w0_after, coin_from)
|
||||
logging.info('node0 end coin_from balance {}, diff {}'.format(node0_from_after, node0_from_after - node0_from_before))
|
||||
node0_to_before = self.getBalance(js_w0_before, coin_to)
|
||||
node0_to_after = self.getBalance(js_w0_after, coin_to)
|
||||
logging.info('node0 end coin_to balance {}, diff {}'.format(node0_to_after, node0_to_after - node0_to_before))
|
||||
if coin_from != Coins.PART: # TODO: Discard block rewards
|
||||
assert (node0_from_before - node0_from_after < 0.02)
|
||||
|
||||
node1_from_before = self.getBalance(js_w1_before, coin_from)
|
||||
node1_from_after = self.getBalance(js_w1_after, coin_from)
|
||||
logging.info('node1 end coin_from balance {}, diff {}'.format(node1_from_after, node1_from_after - node1_from_before))
|
||||
node1_to_before = self.getBalance(js_w1_before, coin_to)
|
||||
node1_to_after = self.getBalance(js_w1_after, coin_to)
|
||||
logging.info('node1 end coin_to balance {}, diff {}'.format(node1_to_after, node1_to_after - node1_to_before))
|
||||
assert (node1_to_before - node1_to_after < 0.02)
|
||||
|
||||
def test_04_a_follower_recover_b_lock_tx(self):
|
||||
if not self.has_segwit:
|
||||
return
|
||||
@@ -566,7 +613,7 @@ class BasicSwapTest(BaseTest):
|
||||
def test_04_b_follower_recover_b_lock_tx_reverse(self):
|
||||
if not self.has_segwit:
|
||||
return
|
||||
self.prepare_balance(Coins.XMR.name, 100.0, 1800, 1801)
|
||||
self.prepare_balance(Coins.XMR, 100.0, 1800, 1801)
|
||||
self.do_test_04_follower_recover_b_lock_tx(Coins.XMR, self.test_coin_from)
|
||||
|
||||
def test_04_c_follower_recover_b_lock_tx_to_part(self):
|
||||
@@ -577,20 +624,6 @@ class BasicSwapTest(BaseTest):
|
||||
def test_04_d_follower_recover_b_lock_tx_from_part(self):
|
||||
self.do_test_04_follower_recover_b_lock_tx(Coins.PART, self.test_coin_from)
|
||||
|
||||
def do_test_05_self_bid(self, coin_from, coin_to):
|
||||
logging.info('---------- Test {} to {} same client'.format(coin_from.name, coin_to.name))
|
||||
|
||||
swap_clients = self.swap_clients
|
||||
ci_to = swap_clients[0].ci(coin_to)
|
||||
|
||||
amt_swap = make_int(random.uniform(0.1, 2.0), scale=8, r=1)
|
||||
rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1)
|
||||
|
||||
offer_id = swap_clients[1].postOffer(coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP, auto_accept_bids=True)
|
||||
bid_id = swap_clients[1].postXmrBid(offer_id, amt_swap)
|
||||
|
||||
wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, wait_for=180)
|
||||
|
||||
def test_05_self_bid(self):
|
||||
if not self.has_segwit:
|
||||
return
|
||||
@@ -604,12 +637,17 @@ class BasicSwapTest(BaseTest):
|
||||
def test_05_self_bid_from_part(self):
|
||||
self.do_test_05_self_bid(Coins.PART, self.test_coin_from)
|
||||
|
||||
def test_05_self_bid_rev(self):
|
||||
if not self.has_segwit:
|
||||
return
|
||||
self.do_test_05_self_bid(Coins.XMR, self.test_coin_from)
|
||||
|
||||
def test_06_preselect_inputs(self):
|
||||
tla_from = self.test_coin_from.name
|
||||
logging.info('---------- Test {} Preselected inputs'.format(tla_from))
|
||||
swap_clients = self.swap_clients
|
||||
|
||||
self.prepare_balance(tla_from, 100.0, 1802, 1800)
|
||||
self.prepare_balance(self.test_coin_from, 100.0, 1802, 1800)
|
||||
|
||||
js_w2 = read_json_api(1802, 'wallets')
|
||||
assert (float(js_w2[tla_from]['balance']) >= 100.0)
|
||||
@@ -739,7 +777,52 @@ class TestBTC(BasicSwapTest):
|
||||
assert (js_0['PART']['encrypted'] is True)
|
||||
assert (js_0['PART']['locked'] is False)
|
||||
|
||||
super().test_01_full_swap()
|
||||
super().test_01_a_full_swap()
|
||||
|
||||
|
||||
class TestBTC_PARTB(TestFunctions):
|
||||
__test__ = True
|
||||
test_coin_from = Coins.BTC
|
||||
test_coin_to = Coins.PART_BLIND
|
||||
start_ltc_nodes = False
|
||||
base_rpc_port = BTC_BASE_RPC_PORT
|
||||
|
||||
def test_01_a_full_swap(self):
|
||||
self.prepare_balance(self.test_coin_to, 100.0, 1801, 1800)
|
||||
self.do_test_01_full_swap(self.test_coin_from, self.test_coin_to)
|
||||
|
||||
def test_01_b_full_swap_reverse(self):
|
||||
self.prepare_balance(self.test_coin_to, 100.0, 1800, 1800)
|
||||
self.do_test_01_full_swap(self.test_coin_to, self.test_coin_from)
|
||||
|
||||
def test_02_a_leader_recover_a_lock_tx(self):
|
||||
self.prepare_balance(self.test_coin_to, 100.0, 1801, 1800)
|
||||
self.do_test_02_leader_recover_a_lock_tx(self.test_coin_from, self.test_coin_to)
|
||||
|
||||
def test_02_b_leader_recover_a_lock_tx_reverse(self):
|
||||
self.prepare_balance(self.test_coin_to, 100.0, 1800, 1800)
|
||||
self.do_test_02_leader_recover_a_lock_tx(self.test_coin_to, self.test_coin_from)
|
||||
|
||||
def test_03_a_follower_recover_a_lock_tx(self):
|
||||
self.prepare_balance(self.test_coin_to, 100.0, 1801, 1800)
|
||||
self.do_test_03_follower_recover_a_lock_tx(self.test_coin_from, self.test_coin_to)
|
||||
|
||||
def test_03_b_follower_recover_a_lock_tx_reverse(self):
|
||||
self.prepare_balance(self.test_coin_to, 100.0, 1800, 1800)
|
||||
self.do_test_03_follower_recover_a_lock_tx(self.test_coin_to, self.test_coin_from, lock_value=12)
|
||||
|
||||
def test_04_a_follower_recover_b_lock_tx(self):
|
||||
self.prepare_balance(self.test_coin_to, 100.0, 1801, 1800)
|
||||
self.do_test_04_follower_recover_b_lock_tx(self.test_coin_from, self.test_coin_to)
|
||||
|
||||
def test_04_b_follower_recover_b_lock_tx_reverse(self):
|
||||
self.prepare_balance(self.test_coin_to, 100.0, 1800, 1800)
|
||||
self.do_test_04_follower_recover_b_lock_tx(self.test_coin_to, self.test_coin_from)
|
||||
|
||||
|
||||
class TestBTC_PARTA(TestBTC_PARTB):
|
||||
__test__ = True
|
||||
test_coin_to = Coins.PART_ANON
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -565,7 +565,7 @@ class BaseTest(unittest.TestCase):
|
||||
for i in range(8):
|
||||
sx_addr = callnoderpc(1, 'getnewstealthaddress')
|
||||
outputs.append({'address': sx_addr, 'amount': 0.5})
|
||||
for i in range(6):
|
||||
for i in range(7):
|
||||
callnoderpc(0, 'sendtypeto', ['part', 'anon', outputs])
|
||||
|
||||
part_addr1 = callnoderpc(1, 'getnewaddress', ['initial addr'])
|
||||
|
||||
Reference in New Issue
Block a user