Browse Source

swapserver: add test for refund path

master
ThomasV 2 years ago
parent
commit
1411b75584
  1. 8
      electrum/commands.py
  2. 5
      electrum/lnworker.py
  3. 1
      electrum/simple_config.py
  4. 24
      electrum/submarine_swaps.py
  5. 7
      electrum/tests/regtest.py
  6. 43
      electrum/tests/regtest/regtest.sh

8
electrum/commands.py

@ -1318,22 +1318,22 @@ class Commands:
await sm.get_pairs()
lightning_amount_sat = satoshis(lightning_amount)
onchain_amount_sat = sm.get_recv_amount(lightning_amount_sat, is_reverse=True)
success = None
funding_txid = None
elif lightning_amount == 'dryrun':
await sm.get_pairs()
onchain_amount_sat = satoshis(onchain_amount)
lightning_amount_sat = sm.get_send_amount(onchain_amount_sat, is_reverse=True)
success = None
funding_txid = None
else:
lightning_amount_sat = satoshis(lightning_amount)
claim_fee = sm.get_claim_fee()
onchain_amount_sat = satoshis(onchain_amount) + claim_fee
success = await wallet.lnworker.swap_manager.reverse_swap(
funding_txid = await wallet.lnworker.swap_manager.reverse_swap(
lightning_amount_sat=lightning_amount_sat,
expected_onchain_amount_sat=onchain_amount_sat,
)
return {
'success': success,
'funding_txid': funding_txid,
'lightning_amount': format_satoshis(lightning_amount_sat),
'onchain_amount': format_satoshis(onchain_amount_sat),
}

5
electrum/lnworker.py

@ -2704,3 +2704,8 @@ class LNWallet(LNWorker):
self._channel_backups[bfh(channel_id)] = cb
util.trigger_callback('channels_updated', self.wallet)
self.lnwatcher.add_channel(cb.funding_outpoint.to_str(), cb.get_funding_address())
def fail_trampoline_forwarding(self, payment_key):
""" use this to fail htlcs received for hold invoices"""
e = OnionRoutingFailure(code=OnionFailureCode.UNKNOWN_NEXT_PEER, data=b'')
self.trampoline_forwarding_failures[payment_key] = e

1
electrum/simple_config.py

@ -967,6 +967,7 @@ class SimpleConfig(Logger):
SWAPSERVER_URL_MAINNET = ConfigVar('swapserver_url_mainnet', default='https://swaps.electrum.org/api', type_=str)
SWAPSERVER_URL_TESTNET = ConfigVar('swapserver_url_testnet', default='https://swaps.electrum.org/testnet', type_=str)
SWAPSERVER_URL_REGTEST = ConfigVar('swapserver_url_regtest', default='http://localhost:5455/api', type_=str)
TEST_SWAPSERVER_REFUND = ConfigVar('test_swapserver_refund', default=False, type_=bool)
# connect to remote WT
WATCHTOWER_CLIENT_ENABLED = ConfigVar('use_watchtower', default=False, type_=bool)
WATCHTOWER_CLIENT_URL = ConfigVar('watchtower_url', default=None, type_=str)

24
electrum/submarine_swaps.py

@ -232,11 +232,18 @@ class SwapManager(Logger):
#
tx = self.lnwatcher.adb.get_transaction(txin.spent_txid)
preimage = tx.inputs()[0].witness_elements()[1]
assert swap.payment_hash == sha256(preimage)
swap.preimage = preimage
self.logger.info(f'found preimage: {preimage.hex()}')
self.lnworker.preimages[swap.payment_hash.hex()] = preimage.hex()
# note: we must check the payment secret before we broadcast the funding tx
if sha256(preimage) == swap.payment_hash:
swap.preimage = preimage
self.logger.info(f'found preimage: {preimage.hex()}')
self.lnworker.preimages[swap.payment_hash.hex()] = preimage.hex()
# note: we must check the payment secret before we broadcast the funding tx
else:
# refund tx
if spent_height > 0:
self.logger.info(f'found confirmed refund')
payment_secret = self.lnworker.get_payment_secret(swap.payment_hash)
payment_key = swap.payment_hash + payment_secret
self.lnworker.fail_trampoline_forwarding(payment_key)
if spent_height > 0:
if current_height - spent_height > REDEEM_AFTER_DOUBLE_SPENT_DELAY:
@ -257,6 +264,8 @@ class SwapManager(Logger):
if swap.is_reverse and swap.preimage is None:
self.logger.info('preimage not available yet')
continue
if swap.is_reverse and self.network.config.TEST_SWAPSERVER_REFUND:
continue
try:
tx = self._create_and_sign_claim_tx(txin=txin, swap=swap, config=self.wallet.config)
except BelowDustLimit:
@ -586,13 +595,12 @@ class SwapManager(Logger):
asyncio.ensure_future(self.lnworker.pay_invoice(fee_invoice, attempts=10))
# we return if we detect funding
async def wait_for_funding(swap):
while swap.spending_txid is None:
while swap.funding_txid is None:
await asyncio.sleep(1)
# initiate main payment
tasks = [asyncio.create_task(self.lnworker.pay_invoice(invoice, attempts=10, channels=channels)), asyncio.create_task(wait_for_funding(swap))]
await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
success = swap.spending_txid is not None
return success
return swap.funding_txid
def _add_or_reindex_swap(self, swap: SwapData) -> None:
if swap.payment_hash.hex() not in self.swaps:

7
electrum/tests/regtest.py

@ -47,8 +47,11 @@ class TestLightningAB(TestLightning):
def test_collaborative_close(self):
self.run_shell(['collaborative_close'])
def test_submarine_swap(self):
self.run_shell(['reverse_swap'])
def test_swapserver_success(self):
self.run_shell(['swapserver_success'])
def test_swapserver_refund(self):
self.run_shell(['swapserver_refund'])
def test_backup(self):
self.run_shell(['backup'])

43
electrum/tests/regtest/regtest.sh

@ -15,6 +15,19 @@ function new_blocks()
$bitcoin_cli generatetoaddress $1 $($bitcoin_cli getnewaddress) > /dev/null
}
function wait_until_htlcs_settled()
{
msg="wait until $1's local_unsettled_sent is zero"
cmd="./run_electrum --regtest -D /tmp/$1"
while unsettled=$($alice list_channels | jq '.[] | .local_unsettled_sent') && [ $unsettled != "0" ]; do
sleep 1
msg="$msg."
printf "$msg\r"
done
printf "\n"
}
function wait_for_balance()
{
msg="wait until $1's balance reaches $2"
@ -171,7 +184,7 @@ if [[ $1 == "collaborative_close" ]]; then
fi
if [[ $1 == "reverse_swap" ]]; then
if [[ $1 == "swapserver_success" ]]; then
wait_for_balance alice 1
echo "alice opens channel"
bob_node=$($bob nodeid)
@ -180,12 +193,34 @@ if [[ $1 == "reverse_swap" ]]; then
wait_until_channel_open alice
echo "alice initiates swap"
dryrun=$($alice reverse_swap 0.02 dryrun)
echo $dryrun | jq
onchain_amount=$(echo $dryrun| jq -r ".onchain_amount")
$alice reverse_swap 0.02 $onchain_amount
swap=$($alice reverse_swap 0.02 $onchain_amount)
echo $swap | jq
funding_txid=$(echo $swap| jq -r ".funding_txid")
new_blocks 1
sleep 1
wait_until_spent $funding_txid 0
wait_until_htlcs_settled alice
fi
if [[ $1 == "swapserver_refund" ]]; then
$alice setconfig test_swapserver_refund true
wait_for_balance alice 1
echo "alice opens channel"
bob_node=$($bob nodeid)
channel=$($alice open_channel $bob_node 0.15)
new_blocks 3
wait_until_channel_open alice
echo "alice initiates swap"
dryrun=$($alice reverse_swap 0.02 dryrun)
onchain_amount=$(echo $dryrun| jq -r ".onchain_amount")
swap=$($alice reverse_swap 0.02 $onchain_amount)
echo $swap | jq
funding_txid=$(echo $swap| jq -r ".funding_txid")
new_blocks 140
wait_until_spent $funding_txid 0
new_blocks 1
wait_until_htlcs_settled alice
fi

Loading…
Cancel
Save