2019-03-11 21:00:29 +01:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
export HOME=~
|
|
|
|
|
set -eu
|
|
|
|
|
|
2021-09-15 09:47:58 +02:00
|
|
|
TEST_ANCHOR_CHANNELS=True
|
|
|
|
|
|
2019-03-11 21:00:29 +01:00
|
|
|
# alice -> bob -> carol
|
|
|
|
|
|
2019-10-13 20:34:38 +02:00
|
|
|
alice="./run_electrum --regtest -D /tmp/alice"
|
|
|
|
|
bob="./run_electrum --regtest -D /tmp/bob"
|
|
|
|
|
carol="./run_electrum --regtest -D /tmp/carol"
|
2019-03-11 21:00:29 +01:00
|
|
|
|
2019-05-23 21:05:27 +02:00
|
|
|
bitcoin_cli="bitcoin-cli -rpcuser=doggman -rpcpassword=donkey -rpcport=18554 -regtest"
|
|
|
|
|
|
2019-05-28 12:17:37 +02:00
|
|
|
function new_blocks()
|
|
|
|
|
{
|
2025-03-11 18:13:32 +01:00
|
|
|
printf "mining $1 blocks\n"
|
2019-05-28 12:17:37 +02:00
|
|
|
$bitcoin_cli generatetoaddress $1 $($bitcoin_cli getnewaddress) > /dev/null
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-28 14:23:32 +02:00
|
|
|
function wait_until_htlcs_settled()
|
|
|
|
|
{
|
|
|
|
|
msg="wait until $1's local_unsettled_sent is zero"
|
|
|
|
|
cmd="./run_electrum --regtest -D /tmp/$1"
|
2025-10-31 14:32:40 +01:00
|
|
|
declare -i timeout_sec=30
|
|
|
|
|
declare -i elapsed_sec=0
|
|
|
|
|
|
2024-02-22 09:40:59 +01:00
|
|
|
while unsettled=$($cmd list_channels | jq '.[] | .local_unsettled_sent') && [ $unsettled != "0" ]; do
|
2025-10-31 14:32:40 +01:00
|
|
|
if ((elapsed_sec > timeout_sec)); then
|
|
|
|
|
printf "Timeout of %i s exceeded\n" "$elapsed_sec"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
2023-06-28 14:23:32 +02:00
|
|
|
sleep 1
|
2025-10-31 14:32:40 +01:00
|
|
|
elapsed_sec=$((elapsed_sec + 1))
|
2023-06-28 14:23:32 +02:00
|
|
|
msg="$msg."
|
|
|
|
|
printf "$msg\r"
|
|
|
|
|
done
|
|
|
|
|
printf "\n"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2019-08-30 15:18:04 +02:00
|
|
|
function wait_for_balance()
|
2019-07-03 08:40:18 +02:00
|
|
|
{
|
2019-08-30 15:18:04 +02:00
|
|
|
msg="wait until $1's balance reaches $2"
|
2019-10-13 20:34:38 +02:00
|
|
|
cmd="./run_electrum --regtest -D /tmp/$1"
|
2025-10-31 14:32:40 +01:00
|
|
|
declare -i timeout_sec=30
|
|
|
|
|
declare -i elapsed_sec=0
|
|
|
|
|
|
2019-08-30 15:18:04 +02:00
|
|
|
while balance=$($cmd getbalance | jq '[.confirmed, .unconfirmed] | to_entries | map(select(.value != null).value) | map(tonumber) | add ') && (( $(echo "$balance < $2" | bc -l) )); do
|
2025-10-31 14:32:40 +01:00
|
|
|
if ((elapsed_sec > timeout_sec)); then
|
|
|
|
|
printf "Timeout of %i s exceeded\n" "$elapsed_sec"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
2019-08-15 19:34:46 +02:00
|
|
|
sleep 1
|
2025-10-31 14:32:40 +01:00
|
|
|
elapsed_sec=$((elapsed_sec + 1))
|
2025-03-07 17:06:55 +00:00
|
|
|
msg="$msg."
|
|
|
|
|
printf "$msg\r"
|
2019-07-03 08:40:18 +02:00
|
|
|
done
|
2019-08-30 15:18:04 +02:00
|
|
|
printf "\n"
|
2019-07-03 08:40:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function wait_until_channel_open()
|
|
|
|
|
{
|
2019-08-30 15:18:04 +02:00
|
|
|
msg="wait until $1 sees channel open"
|
2019-10-13 20:34:38 +02:00
|
|
|
cmd="./run_electrum --regtest -D /tmp/$1"
|
2025-10-31 14:32:40 +01:00
|
|
|
declare -i timeout_sec=30
|
|
|
|
|
declare -i elapsed_sec=0
|
|
|
|
|
|
2019-08-30 15:18:04 +02:00
|
|
|
while channel_state=$($cmd list_channels | jq '.[0] | .state' | tr -d '"') && [ $channel_state != "OPEN" ]; do
|
2025-10-31 14:32:40 +01:00
|
|
|
if ((elapsed_sec > timeout_sec)); then
|
|
|
|
|
printf "Timeout of %i s exceeded\n" "$elapsed_sec"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
2019-08-15 19:34:46 +02:00
|
|
|
sleep 1
|
2025-10-31 14:32:40 +01:00
|
|
|
elapsed_sec=$((elapsed_sec + 1))
|
2025-03-07 17:06:55 +00:00
|
|
|
msg="$msg."
|
|
|
|
|
printf "$msg\r"
|
2019-07-03 08:40:18 +02:00
|
|
|
done
|
2019-08-30 15:18:04 +02:00
|
|
|
printf "\n"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function wait_until_channel_closed()
|
|
|
|
|
{
|
|
|
|
|
msg="wait until $1 sees channel closed"
|
2019-10-13 20:34:38 +02:00
|
|
|
cmd="./run_electrum --regtest -D /tmp/$1"
|
2025-10-31 14:32:40 +01:00
|
|
|
declare -i timeout_sec=30
|
|
|
|
|
declare -i elapsed_sec=0
|
|
|
|
|
|
2019-08-30 15:18:04 +02:00
|
|
|
while [[ $($cmd list_channels | jq '.[0].state' | tr -d '"') != "CLOSED" ]]; do
|
2025-10-31 14:32:40 +01:00
|
|
|
if ((elapsed_sec > timeout_sec)); then
|
|
|
|
|
printf "Timeout of %i s exceeded\n" "$elapsed_sec"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
2019-08-30 15:18:04 +02:00
|
|
|
sleep 1
|
2025-10-31 14:32:40 +01:00
|
|
|
elapsed_sec=$((elapsed_sec + 1))
|
2025-03-07 17:06:55 +00:00
|
|
|
msg="$msg."
|
|
|
|
|
printf "$msg\r"
|
2019-08-30 15:18:04 +02:00
|
|
|
done
|
|
|
|
|
printf "\n"
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-18 14:31:49 +02:00
|
|
|
function wait_until_preimage()
|
|
|
|
|
{
|
|
|
|
|
msg="wait until $1 has preimage for $2"
|
|
|
|
|
cmd="./run_electrum --regtest -D /tmp/$1"
|
2025-10-31 14:32:40 +01:00
|
|
|
declare -i timeout_sec=30
|
|
|
|
|
declare -i elapsed_sec=0
|
|
|
|
|
|
2025-05-18 14:31:49 +02:00
|
|
|
while [[ $($cmd get_invoice $2 | jq '.preimage' | tr -d '"') == "null" ]]; do
|
2025-10-31 14:32:40 +01:00
|
|
|
if ((elapsed_sec > timeout_sec)); then
|
|
|
|
|
printf "Timeout of %i s exceeded\n" "$elapsed_sec"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
2025-05-18 14:31:49 +02:00
|
|
|
sleep 1
|
2025-10-31 14:32:40 +01:00
|
|
|
elapsed_sec=$((elapsed_sec + 1))
|
2025-05-18 14:31:49 +02:00
|
|
|
msg="$msg."
|
|
|
|
|
printf "$msg\r"
|
|
|
|
|
done
|
|
|
|
|
printf "\n"
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-30 15:18:04 +02:00
|
|
|
function wait_until_spent()
|
|
|
|
|
{
|
|
|
|
|
msg="wait until $1:$2 is spent"
|
2025-10-31 14:32:40 +01:00
|
|
|
declare -i timeout_sec=30
|
|
|
|
|
declare -i elapsed_sec=0
|
|
|
|
|
|
2019-08-30 15:18:04 +02:00
|
|
|
while [[ $($bitcoin_cli gettxout $1 $2) ]]; do
|
2025-10-31 14:32:40 +01:00
|
|
|
if ((elapsed_sec > timeout_sec)); then
|
|
|
|
|
printf "Timeout of %i s exceeded\n" "$elapsed_sec"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
2019-08-30 15:18:04 +02:00
|
|
|
sleep 1
|
2025-10-31 14:32:40 +01:00
|
|
|
elapsed_sec=$((elapsed_sec + 1))
|
2025-03-07 17:06:55 +00:00
|
|
|
msg="$msg."
|
|
|
|
|
printf "$msg\r"
|
2019-08-30 15:18:04 +02:00
|
|
|
done
|
|
|
|
|
printf "\n"
|
2019-07-03 08:40:18 +02:00
|
|
|
}
|
|
|
|
|
|
2025-06-28 08:03:32 +00:00
|
|
|
function assert_utxo_exists()
|
|
|
|
|
{
|
|
|
|
|
utxo=$($bitcoin_cli gettxout $1 $2)
|
|
|
|
|
if [[ -z "$utxo" ]]; then
|
|
|
|
|
echo "utxo $1:$2 does not exist"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-11 21:00:29 +01:00
|
|
|
if [[ $# -eq 0 ]]; then
|
|
|
|
|
echo "syntax: init|start|open|status|pay|close|stop"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
2020-02-02 14:50:08 +01:00
|
|
|
if [[ $1 == "new_block" ]]; then
|
2019-05-28 12:17:37 +02:00
|
|
|
new_blocks 1
|
2019-03-11 21:00:29 +01:00
|
|
|
fi
|
|
|
|
|
|
2020-02-02 14:50:08 +01:00
|
|
|
if [[ $1 == "init" ]]; then
|
|
|
|
|
echo "initializing $2"
|
|
|
|
|
rm -rf /tmp/$2/
|
|
|
|
|
agent="./run_electrum --regtest -D /tmp/$2"
|
|
|
|
|
$agent create --offline > /dev/null
|
2021-09-15 09:47:58 +02:00
|
|
|
$agent setconfig --offline enable_anchor_channels $TEST_ANCHOR_CHANNELS
|
2020-02-02 14:50:08 +01:00
|
|
|
$agent setconfig --offline log_to_file True
|
2020-11-11 11:03:31 +01:00
|
|
|
$agent setconfig --offline use_gossip True
|
2020-02-02 14:50:08 +01:00
|
|
|
$agent setconfig --offline server 127.0.0.1:51001:t
|
2020-06-09 18:36:34 +02:00
|
|
|
$agent setconfig --offline lightning_to_self_delay 144
|
2023-08-11 15:08:18 +00:00
|
|
|
$agent setconfig --offline test_force_disable_mpp True
|
2022-10-20 13:40:01 +02:00
|
|
|
echo "funding $2"
|
2023-08-03 11:40:01 +00:00
|
|
|
# note: changing the funding amount affects all tests, as they rely on "wait_for_balance"
|
2025-05-31 11:45:57 +02:00
|
|
|
$bitcoin_cli sendtoaddress $($agent getunusedaddress -o -w "/tmp/$2/regtest/wallets/default_wallet") 1
|
2019-10-29 08:02:14 +01:00
|
|
|
fi
|
|
|
|
|
|
2023-09-21 12:47:11 +02:00
|
|
|
if [[ $1 == "setconfig" ]]; then
|
|
|
|
|
# use this to set config vars that need to be set before the daemon is started
|
|
|
|
|
agent="./run_electrum --regtest -D /tmp/$2"
|
|
|
|
|
$agent setconfig --offline $3 $4
|
|
|
|
|
fi
|
2020-02-02 14:50:08 +01:00
|
|
|
|
2019-03-11 21:00:29 +01:00
|
|
|
# start daemons. Bob is started first because he is listening
|
|
|
|
|
if [[ $1 == "start" ]]; then
|
2020-02-02 14:50:08 +01:00
|
|
|
agent="./run_electrum --regtest -D /tmp/$2"
|
|
|
|
|
$agent daemon -d
|
|
|
|
|
$agent load_wallet
|
2025-05-13 16:34:06 +00:00
|
|
|
$agent wait_for_sync
|
2019-03-11 21:00:29 +01:00
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if [[ $1 == "stop" ]]; then
|
2020-02-02 14:50:08 +01:00
|
|
|
agent="./run_electrum --regtest -D /tmp/$2"
|
|
|
|
|
$agent stop || true
|
|
|
|
|
fi
|
|
|
|
|
|
2021-02-09 15:09:27 +01:00
|
|
|
|
2019-05-28 13:11:21 +02:00
|
|
|
# alice sends two payments, then broadcast ctx after first payment.
|
|
|
|
|
# thus, bob needs to redeem both to_local and to_remote
|
|
|
|
|
|
2020-02-02 14:50:08 +01:00
|
|
|
|
2019-03-11 21:00:29 +01:00
|
|
|
if [[ $1 == "breach" ]]; then
|
2020-02-05 08:56:58 +01:00
|
|
|
wait_for_balance alice 1
|
|
|
|
|
echo "alice opens channel"
|
2019-03-11 21:00:29 +01:00
|
|
|
bob_node=$($bob nodeid)
|
2023-08-18 08:49:11 +02:00
|
|
|
channel=$($alice open_channel $bob_node 0.15 --password='')
|
2019-07-03 08:40:18 +02:00
|
|
|
new_blocks 3
|
2019-08-30 15:18:04 +02:00
|
|
|
wait_until_channel_open alice
|
2025-03-18 11:15:16 +01:00
|
|
|
request=$($bob add_request 0.01 --lightning | jq -r ".lightning_invoice")
|
2019-05-28 12:17:37 +02:00
|
|
|
echo "alice pays"
|
2019-03-11 21:00:29 +01:00
|
|
|
$alice lnpay $request
|
2019-05-28 13:11:21 +02:00
|
|
|
sleep 2
|
2020-03-05 17:27:43 +01:00
|
|
|
ctx=$($alice get_channel_ctx $channel --iknowwhatimdoing)
|
2025-03-18 11:15:16 +01:00
|
|
|
request=$($bob add_request 0.01 --lightning | jq -r ".lightning_invoice")
|
2019-08-30 15:18:04 +02:00
|
|
|
echo "alice pays again"
|
2019-05-28 13:11:21 +02:00
|
|
|
$alice lnpay $request
|
2019-05-28 12:17:37 +02:00
|
|
|
echo "alice broadcasts old ctx"
|
2019-05-23 21:05:27 +02:00
|
|
|
$bitcoin_cli sendrawtransaction $ctx
|
2020-03-09 19:00:59 +01:00
|
|
|
new_blocks 1
|
2019-08-30 15:18:04 +02:00
|
|
|
wait_until_channel_closed bob
|
|
|
|
|
new_blocks 1
|
2023-08-03 11:40:01 +00:00
|
|
|
wait_for_balance bob 1.14
|
2019-08-30 15:18:04 +02:00
|
|
|
$bob getbalance
|
2019-03-11 21:00:29 +01:00
|
|
|
fi
|
|
|
|
|
|
2020-05-02 11:39:21 +02:00
|
|
|
|
2021-03-12 16:10:02 +01:00
|
|
|
if [[ $1 == "backup" ]]; then
|
|
|
|
|
wait_for_balance alice 1
|
|
|
|
|
echo "alice opens channel"
|
|
|
|
|
bob_node=$($bob nodeid)
|
2023-08-18 08:49:11 +02:00
|
|
|
channel1=$($alice open_channel $bob_node 0.15 --password='')
|
lightning: change derivation of funding_pubkey
Ideally, given an on-chain backup, after the remote force-closes, we should be able to spend our anchor output,
to CPFP the remote commitment tx (assuming the channel used OPTION_ANCHORS).
To spend the anchor output, we need to be able to sign with the local funding_privkey.
Previously we derived the funding_key from the channel_seed (which comes from os.urandom).
Prior to anchors, there was no use case for signing with the funding_key given a channel backup.
Now with anchors, we should make its derivation deterministic somehow, in a way so that it can
be derived given just an on-chain backup.
- one way would be to put some more data into the existing OP_RETURN
- uses block space
- the OP_RETURNs can be disabled via "use_recoverable_channels"
- only the initiator can use OP_RETURNs (so what if channel is in incoming dir?)
- instead, new scheme for our funding_key:
- we derive the funding_privkey from the lnworker root secret (derived from our bip32 seed)
- for outgoing channels:
- lnworker_root_secret + remote_node_id + funding_tx_nlocktime
- for incoming channels:
- lnworker_root_secret + remote_node_id + remote_funding_pubkey
- a check is added to avoid reusing the same key between channels:
not letting to user open more than one channel with the same peer in a single block
- only the first 16 bytes of the remote_node_id are used, as the onchain backup OP_RETURNs only contain that
- as the funding_privkey cannot be derived from the channel_seed anymore, it is included in the
imported channel backups, which in turn need a new version defined
- a wallet db upgrade is used to update already stored imported cbs
- alternatively we could keep the imported cbs as-is, so no new version, no new funding_privkey field, as it is clearly somewhat redundant given on-chain backups can reconstruct it
- however adding the field seems easier
- otherwise the existing code would try to derive the funding_privkey from the channel_seed
- also note: atm there is no field in the imported backups to distinguish anchor channels vs static-remotekey channels
2025-01-14 16:14:01 +00:00
|
|
|
new_blocks 1 # cannot open multiple chans with same node in same block
|
2021-03-29 17:35:04 +02:00
|
|
|
$alice setconfig use_recoverable_channels False
|
2023-08-18 08:49:11 +02:00
|
|
|
channel2=$($alice open_channel $bob_node 0.15 --password='')
|
2021-03-12 16:10:02 +01:00
|
|
|
new_blocks 3
|
|
|
|
|
wait_until_channel_open alice
|
2021-03-29 19:08:22 +02:00
|
|
|
backup=$($alice export_channel_backup $channel2)
|
2023-08-18 08:49:11 +02:00
|
|
|
seed=$($alice getseed --password='')
|
2021-03-12 16:10:02 +01:00
|
|
|
$alice stop
|
|
|
|
|
mv /tmp/alice/regtest/wallets/default_wallet /tmp/alice/regtest/wallets/default_wallet.old
|
|
|
|
|
$alice -o restore "$seed"
|
|
|
|
|
$alice daemon -d
|
|
|
|
|
$alice load_wallet
|
2021-03-29 17:35:04 +02:00
|
|
|
$alice import_channel_backup $backup
|
2025-05-13 16:34:06 +00:00
|
|
|
$alice wait_for_sync
|
2021-09-26 12:18:25 +02:00
|
|
|
echo "request force close $channel1"
|
2021-03-29 19:08:22 +02:00
|
|
|
$alice request_force_close $channel1
|
2021-09-26 12:18:25 +02:00
|
|
|
echo "request force close $channel2"
|
2021-03-29 19:08:22 +02:00
|
|
|
$alice request_force_close $channel2
|
2021-09-15 09:47:58 +02:00
|
|
|
new_blocks 1
|
|
|
|
|
wait_for_balance alice 0.997
|
2021-03-12 16:10:02 +01:00
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
2023-07-14 13:44:56 +00:00
|
|
|
if [[ $1 == "backup_local_forceclose" ]]; then
|
|
|
|
|
# Alice does a local-force-close, and then restores from seed before sweeping CSV-locked coins
|
|
|
|
|
wait_for_balance alice 1
|
|
|
|
|
echo "alice opens channel"
|
|
|
|
|
bob_node=$($bob nodeid)
|
|
|
|
|
$alice setconfig use_recoverable_channels False
|
2023-08-18 08:49:11 +02:00
|
|
|
channel=$($alice open_channel $bob_node 0.15 --password='')
|
2023-07-14 13:44:56 +00:00
|
|
|
new_blocks 3
|
|
|
|
|
wait_until_channel_open alice
|
|
|
|
|
backup=$($alice export_channel_backup $channel)
|
|
|
|
|
echo "local force close $channel"
|
|
|
|
|
$alice close_channel $channel --force
|
|
|
|
|
sleep 0.5
|
2023-08-18 08:49:11 +02:00
|
|
|
seed=$($alice getseed --password='')
|
2023-07-14 13:44:56 +00:00
|
|
|
$alice stop
|
|
|
|
|
mv /tmp/alice/regtest/wallets/default_wallet /tmp/alice/regtest/wallets/default_wallet.old
|
|
|
|
|
new_blocks 150
|
|
|
|
|
$alice -o restore "$seed"
|
|
|
|
|
$alice daemon -d
|
|
|
|
|
$alice load_wallet
|
|
|
|
|
$alice import_channel_backup $backup
|
|
|
|
|
wait_for_balance alice 0.998
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
2021-11-26 09:45:06 +01:00
|
|
|
if [[ $1 == "collaborative_close" ]]; then
|
|
|
|
|
wait_for_balance alice 1
|
|
|
|
|
echo "alice opens channel"
|
|
|
|
|
bob_node=$($bob nodeid)
|
2023-08-18 08:49:11 +02:00
|
|
|
channel=$($alice open_channel $bob_node 0.15 --password='')
|
2021-11-26 09:45:06 +01:00
|
|
|
new_blocks 3
|
|
|
|
|
wait_until_channel_open alice
|
|
|
|
|
echo "alice closes channel"
|
|
|
|
|
request=$($bob close_channel $channel)
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
2023-06-28 14:23:32 +02:00
|
|
|
if [[ $1 == "swapserver_success" ]]; then
|
2022-10-20 13:40:01 +02:00
|
|
|
wait_for_balance alice 1
|
|
|
|
|
echo "alice opens channel"
|
|
|
|
|
bob_node=$($bob nodeid)
|
2023-08-18 08:49:11 +02:00
|
|
|
channel=$($alice open_channel $bob_node 0.15 --password='')
|
2022-10-20 13:40:01 +02:00
|
|
|
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")
|
2025-08-21 17:38:31 +02:00
|
|
|
prepayment=$(echo $dryrun| jq -r ".prepayment")
|
|
|
|
|
swap=$($alice reverse_swap 0.02 $onchain_amount --prepayment $prepayment)
|
2023-06-28 14:23:32 +02:00
|
|
|
echo $swap | jq
|
|
|
|
|
funding_txid=$(echo $swap| jq -r ".funding_txid")
|
2022-10-20 13:40:01 +02:00
|
|
|
new_blocks 1
|
2023-06-28 14:23:32 +02:00
|
|
|
wait_until_spent $funding_txid 0
|
|
|
|
|
wait_until_htlcs_settled alice
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
2024-10-23 15:28:01 +02:00
|
|
|
if [[ $1 == "swapserver_forceclose" ]]; then
|
2025-06-25 16:52:32 +00:00
|
|
|
# Alice starts reverse-swap with Bob.
|
|
|
|
|
# Alice sends hold-HTLCs via LN, Bob funds locking script onchain.
|
|
|
|
|
# Bob force-closes the channel, before swap-funding-tx gets mined.
|
|
|
|
|
# After swap-funding-tx gets mined, Alice broadcasts onchain claim tx, revealing preimage.
|
|
|
|
|
# Bob finds preimage onchain, and creates HTLC-success tx to spend own ctx htlc output onchain.
|
2024-10-23 15:28:01 +02:00
|
|
|
wait_for_balance alice 1
|
|
|
|
|
echo "alice opens channel"
|
|
|
|
|
bob_node=$($bob nodeid)
|
|
|
|
|
channel=$($alice open_channel $bob_node 0.15 --password='')
|
|
|
|
|
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")
|
2025-08-21 17:38:31 +02:00
|
|
|
prepayment=$(echo $dryrun| jq -r ".prepayment")
|
|
|
|
|
swap=$($alice reverse_swap 0.02 $onchain_amount --prepayment $prepayment)
|
2024-10-23 15:28:01 +02:00
|
|
|
echo $swap | jq
|
|
|
|
|
funding_txid=$(echo $swap| jq -r ".funding_txid")
|
2025-05-15 14:19:49 +00:00
|
|
|
ctx_id=$($bob close_channel --force $channel)
|
2024-10-23 15:28:01 +02:00
|
|
|
new_blocks 1
|
|
|
|
|
wait_until_spent $funding_txid 0 # alice reveals preimage
|
|
|
|
|
new_blocks 1
|
2025-05-15 14:19:49 +00:00
|
|
|
if [ $TEST_ANCHOR_CHANNELS = True ] ; then
|
|
|
|
|
output_index=3 # received_htlc_output in bob's ctx. FIXME index depends on Alice not using MPP
|
|
|
|
|
else
|
|
|
|
|
output_index=1
|
|
|
|
|
fi
|
|
|
|
|
# wait until Bob finds preimage onchain and uses it to create an htlc_success tx
|
2025-05-26 16:53:17 +00:00
|
|
|
wait_until_spent $ctx_id $output_index
|
2025-02-14 14:12:12 +01:00
|
|
|
new_blocks 144
|
2024-10-23 15:28:01 +02:00
|
|
|
wait_for_balance bob 0.999
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
2023-06-28 14:23:32 +02:00
|
|
|
if [[ $1 == "swapserver_refund" ]]; then
|
2025-06-25 16:52:32 +00:00
|
|
|
# Alice starts reverse-swap with Bob.
|
|
|
|
|
# Alice sends hold-HTLCs via LN, Bob funds locking script onchain.
|
|
|
|
|
# Alice never broadcasts onchain claim tx. Bob will use timeout path onchain.
|
|
|
|
|
# Then Bob fails hold-HTLCs via LN.
|
|
|
|
|
# Channel stays open.
|
2023-06-28 14:23:32 +02:00
|
|
|
$alice setconfig test_swapserver_refund true
|
|
|
|
|
wait_for_balance alice 1
|
|
|
|
|
echo "alice opens channel"
|
|
|
|
|
bob_node=$($bob nodeid)
|
2023-08-18 08:49:11 +02:00
|
|
|
channel=$($alice open_channel $bob_node 0.15 --password='')
|
2023-06-28 14:23:32 +02:00
|
|
|
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")
|
2025-08-21 17:38:31 +02:00
|
|
|
prepayment=$(echo $dryrun| jq -r ".prepayment")
|
|
|
|
|
swap=$($alice reverse_swap 0.02 $onchain_amount --prepayment $prepayment)
|
2023-06-28 14:23:32 +02:00
|
|
|
echo $swap | jq
|
|
|
|
|
funding_txid=$(echo $swap| jq -r ".funding_txid")
|
|
|
|
|
new_blocks 140
|
|
|
|
|
wait_until_spent $funding_txid 0
|
2022-10-20 13:40:01 +02:00
|
|
|
new_blocks 1
|
2023-06-28 14:23:32 +02:00
|
|
|
wait_until_htlcs_settled alice
|
2022-10-20 13:40:01 +02:00
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
2025-06-28 08:03:32 +00:00
|
|
|
if [[ $1 == "lnwatcher_waits_until_fees_go_down" ]]; then
|
|
|
|
|
# Alice sends two HTLCs to Bob (one for small invoice, one for large invoice), which Bob will hold.
|
|
|
|
|
# Alice requests Bob to force-close the channel, while the HTLCs are pending. Bob force-closes.
|
|
|
|
|
# Fee levels rise, to the point where the small HTLC is not economical to claim.
|
|
|
|
|
# Alice sweeps the large HTLC (via onchain timeout), but not the small one.
|
|
|
|
|
# Then, fee levels go back down, and Alice sweeps the small HTLC.
|
|
|
|
|
# This test checks Alice does not abandon channel outputs that are temporarily ~dust due to
|
|
|
|
|
# mempool spikes, and keeps watching the channel in hope of fees going down.
|
|
|
|
|
$alice setconfig test_force_disable_mpp true
|
|
|
|
|
$alice setconfig test_force_mpp false
|
|
|
|
|
wait_for_balance alice 1
|
2025-10-31 13:31:10 +01:00
|
|
|
$alice setconfig test_disable_automatic_fee_eta_update true
|
2025-06-28 08:03:32 +00:00
|
|
|
$alice test_inject_fee_etas "{2:1000}"
|
|
|
|
|
$bob test_inject_fee_etas "{2:1000}"
|
|
|
|
|
echo "alice opens channel"
|
|
|
|
|
bob_node=$($bob nodeid)
|
|
|
|
|
channel=$($alice open_channel $bob_node 0.15 --password='')
|
|
|
|
|
chan_funding_txid=$(echo "$channel" | cut -d ":" -f 1)
|
|
|
|
|
chan_funding_outidx=$(echo "$channel" | cut -d ":" -f 2)
|
|
|
|
|
new_blocks 3
|
|
|
|
|
wait_until_channel_open alice
|
|
|
|
|
# Alice sends an HTLC to Bob, which Bob will hold indefinitely. Alice's lnpay will time out.
|
|
|
|
|
invoice1=$($bob add_hold_invoice deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbee1 \
|
|
|
|
|
--amount 0.0004 --min_final_cltv_expiry_delta 300 | jq -r ".invoice")
|
|
|
|
|
invoice2=$($bob add_hold_invoice deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbee2 \
|
|
|
|
|
--amount 0.04 --min_final_cltv_expiry_delta 300 | jq -r ".invoice")
|
|
|
|
|
set +e
|
|
|
|
|
$alice lnpay $invoice1 --timeout 3
|
|
|
|
|
$alice lnpay $invoice2 --timeout 3
|
|
|
|
|
set -e
|
|
|
|
|
# After a while, Alice gets impatient and gets Bob to close the channel.
|
|
|
|
|
new_blocks 20
|
|
|
|
|
$alice request_force_close $channel
|
|
|
|
|
wait_until_spent $chan_funding_txid $chan_funding_outidx
|
|
|
|
|
$bob stop # bob closes and then disappears. FIXME this is a hack to prevent Bob claiming the fake-hold-invoice-htlc onchain
|
|
|
|
|
new_blocks 1
|
|
|
|
|
wait_until_channel_closed alice
|
|
|
|
|
ctx_id=$($alice list_channels | jq -r ".[0].closing_txid")
|
|
|
|
|
if [ $TEST_ANCHOR_CHANNELS = True ] ; then
|
|
|
|
|
htlc_output_index1=2
|
|
|
|
|
htlc_output_index2=3
|
|
|
|
|
to_alice_index=4 # Bob's to_remote
|
|
|
|
|
wait_until_spent $ctx_id $to_alice_index
|
|
|
|
|
else
|
|
|
|
|
htlc_output_index1=0
|
|
|
|
|
htlc_output_index2=1
|
|
|
|
|
to_alice_index=2
|
|
|
|
|
fi
|
|
|
|
|
new_blocks 1
|
|
|
|
|
assert_utxo_exists $ctx_id $htlc_output_index1
|
|
|
|
|
assert_utxo_exists $ctx_id $htlc_output_index2
|
|
|
|
|
# fee levels rise. now small htlc is ~dust
|
|
|
|
|
$alice test_inject_fee_etas "{2:300000}"
|
|
|
|
|
new_blocks 300 # this goes past the CLTV of the HTLC-output in ctx
|
|
|
|
|
wait_until_spent $ctx_id $htlc_output_index2
|
|
|
|
|
assert_utxo_exists $ctx_id $htlc_output_index1
|
|
|
|
|
new_blocks 24 # note: >20 blocks depth is considered "DEEP" by lnwatcher
|
|
|
|
|
sleep 1 # give time for Alice to make mistakes, such as abandoning the channel. which it should NOT do.
|
|
|
|
|
new_blocks 1
|
|
|
|
|
# Alice goes offline and comes back later, 1
|
|
|
|
|
$alice stop
|
|
|
|
|
$alice daemon -d
|
|
|
|
|
$alice test_inject_fee_etas "{2:300000}"
|
|
|
|
|
$alice load_wallet
|
|
|
|
|
$alice wait_for_sync
|
|
|
|
|
new_blocks 1
|
|
|
|
|
sleep 1 # give time for Alice to make mistakes
|
|
|
|
|
# Alice goes offline and comes back later, 2
|
|
|
|
|
$alice stop
|
|
|
|
|
$alice daemon -d
|
|
|
|
|
$alice test_inject_fee_etas "{2:300000}"
|
|
|
|
|
$alice load_wallet
|
|
|
|
|
$alice wait_for_sync
|
|
|
|
|
new_blocks 1
|
|
|
|
|
sleep 1 # give time for Alice to make mistakes
|
|
|
|
|
# fee levels go down. time to claim the small htlc
|
|
|
|
|
$alice test_inject_fee_etas "{2:1000}"
|
|
|
|
|
new_blocks 1
|
|
|
|
|
wait_until_spent $ctx_id $htlc_output_index1
|
|
|
|
|
new_blocks 1
|
|
|
|
|
wait_for_balance alice 0.9995
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
2020-05-02 11:39:21 +02:00
|
|
|
if [[ $1 == "extract_preimage" ]]; then
|
2025-03-07 17:06:55 +00:00
|
|
|
# Alice sends htlc1 to Bob. Bob sends htlc2 to Alice.
|
|
|
|
|
# Neither one of them settles, they hold the htlcs, and Bob force-closes.
|
|
|
|
|
# Bob's ctx contains two htlc outputs: "received" htlc1, and "offered" htlc2.
|
|
|
|
|
# Bob also broadcasts an HTLC-success tx for received htlc1, revealing the preimage.
|
|
|
|
|
# Alice broadcasts a direct-spend of the offered htlc2, revealing the preimage.
|
|
|
|
|
# This test checks that
|
|
|
|
|
# - Alice successfully extracts the preimage for htlc1 from Bob's HTLC-success tx, and
|
|
|
|
|
# - Bob successfully extracts the preimage for htlc2 from Alice's direct spend tx
|
|
|
|
|
# note: actually, due to MPP, there will be more htlcs in the ctx:
|
|
|
|
|
# we force alice to use MPP, but force bob NOT to use MPP
|
2024-12-14 08:24:26 +01:00
|
|
|
$alice setconfig test_force_disable_mpp false
|
|
|
|
|
$alice setconfig test_force_mpp true
|
2025-03-07 17:06:55 +00:00
|
|
|
$bob setconfig test_force_disable_mpp true
|
|
|
|
|
$bob setconfig test_force_mpp false
|
|
|
|
|
$alice enable_htlc_settle false
|
2020-05-02 11:39:21 +02:00
|
|
|
$bob enable_htlc_settle false
|
|
|
|
|
wait_for_balance alice 1
|
|
|
|
|
echo "alice opens channel"
|
|
|
|
|
bob_node=$($bob nodeid)
|
2025-03-07 17:06:55 +00:00
|
|
|
$alice open_channel $bob_node 0.15 --password='' --push_amount=0.075
|
2020-05-02 11:39:21 +02:00
|
|
|
new_blocks 3
|
|
|
|
|
wait_until_channel_open alice
|
|
|
|
|
chan_id=$($alice list_channels | jq -r ".[0].channel_point")
|
|
|
|
|
# alice pays bob
|
2025-05-18 14:31:49 +02:00
|
|
|
request1=$($bob add_request 0.04 --lightning --memo "test1")
|
|
|
|
|
invoice1=$(echo $request1 | jq -r ".lightning_invoice")
|
|
|
|
|
rhash1=$(echo $request1 | jq -r ".rhash")
|
2025-03-07 17:06:55 +00:00
|
|
|
screen -S alice_payment -dm -L -Logfile /tmp/alice/screen1.log $alice lnpay $invoice1 --timeout=600
|
2020-05-02 11:39:21 +02:00
|
|
|
sleep 1
|
|
|
|
|
unsettled=$($alice list_channels | jq '.[] | .local_unsettled_sent')
|
|
|
|
|
if [[ "$unsettled" == "0" ]]; then
|
2025-03-07 17:06:55 +00:00
|
|
|
echo 'enable_htlc_settle did not work (bob settled)'
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
# bob pays alice
|
2025-05-18 14:31:49 +02:00
|
|
|
request2=$($alice add_request 0.04 --lightning --memo "test2")
|
|
|
|
|
invoice2=$(echo $request2 | jq -r ".lightning_invoice")
|
|
|
|
|
rhash2=$(echo $request2 | jq -r ".rhash")
|
2025-03-07 17:06:55 +00:00
|
|
|
screen -S bob_payment -dm -L -Logfile /tmp/bob/screen2.log $bob lnpay $invoice2 --timeout=600
|
|
|
|
|
sleep 1
|
|
|
|
|
unsettled=$($bob list_channels | jq '.[] | .local_unsettled_sent')
|
|
|
|
|
if [[ "$unsettled" == "0" ]]; then
|
|
|
|
|
echo 'enable_htlc_settle did not work (alice settled)'
|
2020-05-02 11:39:21 +02:00
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
# bob force closes
|
|
|
|
|
$bob close_channel $chan_id --force
|
|
|
|
|
new_blocks 1
|
2025-05-18 14:31:49 +02:00
|
|
|
wait_until_preimage alice $rhash1
|
|
|
|
|
wait_until_preimage bob $rhash2
|
2025-03-07 17:06:55 +00:00
|
|
|
# check both "lnpay" commands succeeded
|
|
|
|
|
success=$(cat /tmp/alice/screen1.log | jq -r ".success")
|
2025-05-26 16:53:17 +00:00
|
|
|
if [[ "$success" != "true" ]]; then echo "alice payment failed"; exit 1; fi
|
2025-03-07 17:06:55 +00:00
|
|
|
success=$(cat /tmp/bob/screen2.log | jq -r ".success")
|
2025-05-26 16:53:17 +00:00
|
|
|
if [[ "$success" != "true" ]]; then echo "bob payment failed"; exit 1; fi
|
2025-03-07 17:06:55 +00:00
|
|
|
cat /tmp/alice/screen1.log
|
|
|
|
|
cat /tmp/bob/screen2.log
|
2020-05-02 11:39:21 +02:00
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
2025-05-08 19:28:05 +02:00
|
|
|
if [[ $1 == "redeem_offered_htlcs" ]]; then
|
|
|
|
|
# alice force closes and redeems using htlc timeout
|
2020-02-27 20:53:50 +01:00
|
|
|
$bob enable_htlc_settle false
|
2020-02-05 08:56:58 +01:00
|
|
|
wait_for_balance alice 1
|
|
|
|
|
echo "alice opens channel"
|
2019-03-11 21:00:29 +01:00
|
|
|
bob_node=$($bob nodeid)
|
2023-08-18 08:49:11 +02:00
|
|
|
$alice open_channel $bob_node 0.15 --password=''
|
2020-02-05 08:56:58 +01:00
|
|
|
new_blocks 3
|
|
|
|
|
wait_until_channel_open alice
|
2019-03-11 21:00:29 +01:00
|
|
|
# alice pays bob
|
2025-03-18 11:15:16 +01:00
|
|
|
invoice=$($bob add_request 0.04 --lightning --memo "test" | jq -r ".lightning_invoice")
|
2019-05-29 17:34:12 +02:00
|
|
|
$alice lnpay $invoice --timeout=1 || true
|
2020-03-06 10:26:11 +01:00
|
|
|
unsettled=$($alice list_channels | jq '.[] | .local_unsettled_sent')
|
|
|
|
|
if [[ "$unsettled" == "0" ]]; then
|
2020-02-27 20:53:50 +01:00
|
|
|
echo 'enable_htlc_settle did not work'
|
2019-03-11 21:00:29 +01:00
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
# bob goes away
|
2019-08-19 12:46:31 +02:00
|
|
|
$bob stop
|
2019-03-11 21:00:29 +01:00
|
|
|
echo "alice balance before closing channel:" $($alice getbalance)
|
|
|
|
|
balance_before=$($alice getbalance | jq '[.confirmed, .unconfirmed, .lightning] | to_entries | map(select(.value != null).value) | map(tonumber) | add ')
|
|
|
|
|
# alice force closes the channel
|
|
|
|
|
chan_id=$($alice list_channels | jq -r ".[0].channel_point")
|
|
|
|
|
$alice close_channel $chan_id --force
|
2019-05-28 12:17:37 +02:00
|
|
|
new_blocks 1
|
2019-05-30 13:17:17 +02:00
|
|
|
sleep 3
|
2019-03-11 21:00:29 +01:00
|
|
|
echo "alice balance after closing channel:" $($alice getbalance)
|
2019-08-15 19:59:24 +02:00
|
|
|
new_blocks 150
|
2019-03-11 21:00:29 +01:00
|
|
|
sleep 10
|
2019-05-28 12:17:37 +02:00
|
|
|
new_blocks 1
|
2019-05-30 13:17:17 +02:00
|
|
|
sleep 3
|
|
|
|
|
echo "alice balance after CLTV" $($alice getbalance)
|
2019-08-15 19:59:24 +02:00
|
|
|
new_blocks 150
|
2019-03-11 21:00:29 +01:00
|
|
|
sleep 10
|
2019-05-30 13:17:17 +02:00
|
|
|
new_blocks 1
|
|
|
|
|
sleep 3
|
|
|
|
|
echo "alice balance after CSV" $($alice getbalance)
|
2019-08-30 15:18:04 +02:00
|
|
|
# fixme: add local to getbalance
|
|
|
|
|
wait_for_balance alice $(echo "$balance_before - 0.02" | bc -l)
|
|
|
|
|
$alice getbalance
|
2019-03-11 21:00:29 +01:00
|
|
|
fi
|
2019-05-29 17:34:12 +02:00
|
|
|
|
|
|
|
|
|
2025-05-08 19:28:05 +02:00
|
|
|
if [[ $1 == "redeem_received_htlcs" ]]; then
|
|
|
|
|
# bob force closes and redeems with the preimage
|
|
|
|
|
$bob enable_htlc_settle false
|
|
|
|
|
wait_for_balance alice 1
|
|
|
|
|
echo "alice opens channel"
|
|
|
|
|
bob_node=$($bob nodeid)
|
|
|
|
|
$alice open_channel $bob_node 0.15 --password=''
|
|
|
|
|
new_blocks 3
|
|
|
|
|
wait_until_channel_open alice
|
|
|
|
|
# alice pays bob
|
|
|
|
|
invoice=$($bob add_request 0.04 --lightning --memo "test" | jq -r ".lightning_invoice")
|
|
|
|
|
$alice lnpay $invoice --timeout=1 || true
|
|
|
|
|
unsettled=$($alice list_channels | jq '.[] | .local_unsettled_sent')
|
|
|
|
|
if [[ "$unsettled" == "0" ]]; then
|
|
|
|
|
echo 'enable_htlc_settle did not work'
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
$alice stop
|
|
|
|
|
chan_id=$($bob list_channels | jq -r ".[0].channel_point")
|
|
|
|
|
$bob close_channel $chan_id --force
|
|
|
|
|
# if we exit here, bob GUI will show a warning
|
|
|
|
|
new_blocks 1
|
2025-05-29 19:26:42 +02:00
|
|
|
wait_for_balance bob 1.038
|
2025-05-08 19:28:05 +02:00
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
2019-06-24 11:13:18 +02:00
|
|
|
if [[ $1 == "breach_with_unspent_htlc" ]]; then
|
2020-02-27 20:53:50 +01:00
|
|
|
$bob enable_htlc_settle false
|
2019-08-30 15:18:04 +02:00
|
|
|
wait_for_balance alice 1
|
2019-06-04 15:55:38 +02:00
|
|
|
echo "alice opens channel"
|
2019-05-29 17:34:12 +02:00
|
|
|
bob_node=$($bob nodeid)
|
2023-08-18 08:49:11 +02:00
|
|
|
channel=$($alice open_channel $bob_node 0.15 --password='')
|
2019-06-04 15:55:38 +02:00
|
|
|
new_blocks 3
|
2019-08-30 15:18:04 +02:00
|
|
|
wait_until_channel_open alice
|
2019-05-29 17:34:12 +02:00
|
|
|
echo "alice pays bob"
|
2025-03-18 11:15:16 +01:00
|
|
|
invoice=$($bob add_request 0.04 --lightning --memo "test" | jq -r ".lightning_invoice")
|
2019-05-29 17:34:12 +02:00
|
|
|
$alice lnpay $invoice --timeout=1 || true
|
2020-03-06 10:26:11 +01:00
|
|
|
unsettled=$($alice list_channels | jq '.[] | .local_unsettled_sent')
|
|
|
|
|
if [[ "$unsettled" == "0" ]]; then
|
|
|
|
|
echo "enable_htlc_settle did not work, $unsettled"
|
2019-05-29 17:34:12 +02:00
|
|
|
exit 1
|
|
|
|
|
fi
|
2020-03-05 17:27:43 +01:00
|
|
|
ctx=$($alice get_channel_ctx $channel --iknowwhatimdoing)
|
2020-02-27 20:53:50 +01:00
|
|
|
$bob enable_htlc_settle true
|
2020-03-06 10:26:11 +01:00
|
|
|
unsettled=$($alice list_channels | jq '.[] | .local_unsettled_sent')
|
|
|
|
|
if [[ "$unsettled" != "0" ]]; then
|
|
|
|
|
echo "enable_htlc_settle did not work, $unsettled"
|
2019-05-29 17:34:12 +02:00
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
echo "alice breaches with old ctx"
|
|
|
|
|
$bitcoin_cli sendrawtransaction $ctx
|
2025-02-14 14:12:12 +01:00
|
|
|
new_blocks 1
|
2023-08-03 11:40:01 +00:00
|
|
|
wait_for_balance bob 1.14
|
2019-05-29 17:34:12 +02:00
|
|
|
fi
|
2019-06-24 11:13:18 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
if [[ $1 == "breach_with_spent_htlc" ]]; then
|
2020-02-27 20:53:50 +01:00
|
|
|
$bob enable_htlc_settle false
|
2019-08-30 15:18:04 +02:00
|
|
|
wait_for_balance alice 1
|
2019-06-24 11:13:18 +02:00
|
|
|
echo "alice opens channel"
|
|
|
|
|
bob_node=$($bob nodeid)
|
2023-08-18 08:49:11 +02:00
|
|
|
channel=$($alice open_channel $bob_node 0.15 --password='')
|
2019-06-24 11:13:18 +02:00
|
|
|
new_blocks 3
|
2019-08-30 15:18:04 +02:00
|
|
|
wait_until_channel_open alice
|
2019-06-24 11:13:18 +02:00
|
|
|
echo "alice pays bob"
|
2025-03-18 11:15:16 +01:00
|
|
|
invoice=$($bob add_request 0.04 --lightning --memo "test" | jq -r ".lightning_invoice")
|
2019-06-24 11:13:18 +02:00
|
|
|
$alice lnpay $invoice --timeout=1 || true
|
2020-03-05 17:27:43 +01:00
|
|
|
ctx=$($alice get_channel_ctx $channel --iknowwhatimdoing)
|
2020-03-06 10:26:11 +01:00
|
|
|
unsettled=$($alice list_channels | jq '.[] | .local_unsettled_sent')
|
|
|
|
|
if [[ "$unsettled" == "0" ]]; then
|
|
|
|
|
echo "enable_htlc_settle did not work, $unsettled"
|
2019-06-24 11:13:18 +02:00
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
cp /tmp/alice/regtest/wallets/default_wallet /tmp/alice/regtest/wallets/toxic_wallet
|
2020-02-27 20:53:50 +01:00
|
|
|
$bob enable_htlc_settle true
|
2020-03-06 10:26:11 +01:00
|
|
|
unsettled=$($alice list_channels | jq '.[] | .local_unsettled_sent')
|
|
|
|
|
if [[ "$unsettled" != "0" ]]; then
|
|
|
|
|
echo "enable_htlc_settle did not work, $unsettled"
|
2019-06-24 11:13:18 +02:00
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
echo $($bob getbalance)
|
|
|
|
|
echo "bob goes offline"
|
2019-08-19 12:46:31 +02:00
|
|
|
$bob stop
|
2019-06-24 11:13:18 +02:00
|
|
|
ctx_id=$($bitcoin_cli sendrawtransaction $ctx)
|
|
|
|
|
echo "alice breaches with old ctx:" $ctx_id
|
|
|
|
|
new_blocks 1
|
|
|
|
|
if [[ $($bitcoin_cli gettxout $ctx_id 0 | jq '.confirmations') != "1" ]]; then
|
2019-08-15 19:34:46 +02:00
|
|
|
echo "breach tx not confirmed"
|
|
|
|
|
exit 1
|
2019-06-24 11:13:18 +02:00
|
|
|
fi
|
|
|
|
|
echo "wait for cltv_expiry blocks"
|
2019-08-15 19:59:24 +02:00
|
|
|
# note: this will let alice redeem both to_local and the htlc.
|
|
|
|
|
# (to_local needs to_self_delay blocks; htlc needs whatever we put in invoice)
|
|
|
|
|
new_blocks 150
|
2019-08-19 12:46:31 +02:00
|
|
|
$alice stop
|
2019-09-02 19:04:08 +02:00
|
|
|
$alice daemon -d
|
2019-08-30 15:57:01 +02:00
|
|
|
sleep 1
|
2019-08-30 17:40:09 +02:00
|
|
|
$alice load_wallet -w /tmp/alice/regtest/wallets/toxic_wallet
|
2019-06-24 11:13:18 +02:00
|
|
|
# wait until alice has spent both ctx outputs
|
2019-08-30 15:18:04 +02:00
|
|
|
echo "alice spends to_local and htlc outputs"
|
2021-09-15 09:47:58 +02:00
|
|
|
if [ $TEST_ANCHOR_CHANNELS = True ] ; then
|
|
|
|
|
# to_local_anchor/to_remote_anchor: 0 and 1 (both are present due to untrimmed htlcs)
|
|
|
|
|
# htlc: 2, to_local: 3
|
|
|
|
|
wait_until_spent $ctx_id 2
|
|
|
|
|
wait_until_spent $ctx_id 3
|
|
|
|
|
else
|
|
|
|
|
# htlc: 0, to_local: 1
|
|
|
|
|
wait_until_spent $ctx_id 0
|
|
|
|
|
wait_until_spent $ctx_id 1
|
|
|
|
|
fi
|
2019-06-24 11:13:18 +02:00
|
|
|
new_blocks 1
|
|
|
|
|
echo "bob comes back"
|
2019-09-02 19:04:08 +02:00
|
|
|
$bob daemon -d
|
2019-08-30 15:57:01 +02:00
|
|
|
sleep 1
|
2019-08-19 12:46:31 +02:00
|
|
|
$bob load_wallet
|
2023-08-03 11:40:01 +00:00
|
|
|
wait_for_balance bob 1.039
|
2019-08-30 15:18:04 +02:00
|
|
|
$bob getbalance
|
2019-06-24 11:13:18 +02:00
|
|
|
fi
|
2019-07-05 14:42:09 +02:00
|
|
|
|
2020-02-02 14:50:08 +01:00
|
|
|
if [[ $1 == "watchtower" ]]; then
|
2019-08-30 15:18:04 +02:00
|
|
|
wait_for_balance alice 1
|
2019-07-05 14:42:09 +02:00
|
|
|
echo "alice opens channel"
|
|
|
|
|
bob_node=$($bob nodeid)
|
2023-08-18 08:49:11 +02:00
|
|
|
channel=$($alice open_channel $bob_node 0.15 --password='')
|
2020-02-02 14:50:08 +01:00
|
|
|
echo "channel outpoint: $channel"
|
2019-07-05 14:42:09 +02:00
|
|
|
new_blocks 3
|
2019-08-30 15:18:04 +02:00
|
|
|
wait_until_channel_open alice
|
2019-07-05 14:42:09 +02:00
|
|
|
echo "alice pays bob"
|
2025-03-18 11:15:16 +01:00
|
|
|
invoice1=$($bob add_request 0.01 --lightning --memo "invoice1" | jq -r ".lightning_invoice")
|
2019-07-05 14:42:09 +02:00
|
|
|
$alice lnpay $invoice1
|
2020-03-05 17:27:43 +01:00
|
|
|
ctx=$($alice get_channel_ctx $channel --iknowwhatimdoing)
|
2020-02-02 14:50:08 +01:00
|
|
|
echo "alice pays bob again"
|
2025-03-18 11:15:16 +01:00
|
|
|
invoice2=$($bob add_request 0.01 --lightning --memo "invoice2" | jq -r ".lightning_invoice")
|
2019-07-05 14:42:09 +02:00
|
|
|
$alice lnpay $invoice2
|
2024-12-20 14:02:54 +01:00
|
|
|
bob_ctn=$($bob list_channels | jq '.[0].local_ctn')
|
2020-02-02 14:50:08 +01:00
|
|
|
msg="waiting until watchtower is synchronized"
|
2022-09-01 09:56:46 +02:00
|
|
|
# watchtower needs to be at latest revoked ctn
|
2024-12-20 14:02:54 +01:00
|
|
|
while watchtower_ctn=$($bob get_watchtower_ctn $channel) && [[ $watchtower_ctn != $((bob_ctn-1)) ]]; do
|
2022-09-01 09:56:46 +02:00
|
|
|
sleep 0.1
|
2024-12-20 14:02:54 +01:00
|
|
|
printf "$msg $bob_ctn $watchtower_ctn\r"
|
2020-02-02 14:50:08 +01:00
|
|
|
done
|
|
|
|
|
printf "\n"
|
2022-09-01 09:56:46 +02:00
|
|
|
echo "stopping alice and bob"
|
2021-09-27 10:31:44 +02:00
|
|
|
$bob stop
|
|
|
|
|
$alice stop
|
|
|
|
|
ctx_id=$($bitcoin_cli sendrawtransaction $ctx)
|
|
|
|
|
echo "alice breaches with old ctx:" $ctx_id
|
|
|
|
|
echo "watchtower publishes justice transaction"
|
2021-09-15 09:47:58 +02:00
|
|
|
if [ $TEST_ANCHOR_CHANNELS = True ] ; then
|
|
|
|
|
output_index=3
|
|
|
|
|
else
|
|
|
|
|
output_index=1
|
|
|
|
|
fi
|
|
|
|
|
wait_until_spent $ctx_id $output_index # alice's to_local gets punished
|
2019-07-05 14:42:09 +02:00
|
|
|
fi
|
2021-10-25 12:00:00 +00:00
|
|
|
|
2025-03-11 18:13:32 +01:00
|
|
|
if [[ $1 == "fw_fail_htlc" ]]; then
|
|
|
|
|
$carol enable_htlc_settle false
|
|
|
|
|
bob_node=$($bob nodeid)
|
|
|
|
|
wait_for_balance carol 1
|
|
|
|
|
echo "alice and carol open channels with bob"
|
|
|
|
|
chan_id1=$($alice open_channel $bob_node 0.15 --password='' --push_amount=0.075)
|
|
|
|
|
chan_id2=$($carol open_channel $bob_node 0.15 --password='' --push_amount=0.075)
|
|
|
|
|
new_blocks 3
|
|
|
|
|
wait_until_channel_open alice
|
|
|
|
|
wait_until_channel_open carol
|
|
|
|
|
echo "alice pays carol"
|
2025-03-18 11:15:16 +01:00
|
|
|
invoice=$($carol add_request 0.01 --lightning --memo "invoice" | jq -r ".lightning_invoice")
|
2025-03-11 18:13:32 +01:00
|
|
|
screen -S alice_payment -dm -L -Logfile /tmp/alice/screen1.log $alice lnpay $invoice --timeout=600
|
|
|
|
|
sleep 1
|
|
|
|
|
unsettled=$($alice list_channels | jq '.[] | .local_unsettled_sent')
|
|
|
|
|
if [[ "$unsettled" == "0" ]]; then
|
|
|
|
|
echo 'enable_htlc_settle did not work (carol settled)'
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
$carol stop
|
2025-06-01 13:42:26 +02:00
|
|
|
ctx_id=$($bob close_channel $chan_id2 --force)
|
2025-03-11 18:13:32 +01:00
|
|
|
new_blocks 1
|
|
|
|
|
sleep 1
|
|
|
|
|
new_blocks 150 # cltv before bob can broadcast
|
2025-06-01 13:42:26 +02:00
|
|
|
# index of htlc
|
|
|
|
|
if [ $TEST_ANCHOR_CHANNELS = True ] ; then
|
|
|
|
|
output_index=2
|
|
|
|
|
else
|
|
|
|
|
output_index=0
|
|
|
|
|
fi
|
|
|
|
|
wait_until_spent $ctx_id $output_index
|
2025-03-11 18:13:32 +01:00
|
|
|
new_blocks 1 # confirm 2nd stage.
|
|
|
|
|
sleep 1
|
|
|
|
|
new_blocks 100 # deep
|
|
|
|
|
sleep 5 # give bob time to fail incoming htlc
|
|
|
|
|
unsettled=$($alice list_channels | jq '.[] | .local_unsettled_sent')
|
|
|
|
|
if [[ "$unsettled" != "0" ]]; then
|
|
|
|
|
echo 'alice htlc was not failed'
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
|
2023-08-08 05:09:58 +02:00
|
|
|
if [[ $1 == "just_in_time" ]]; then
|
|
|
|
|
bob_node=$($bob nodeid)
|
|
|
|
|
$alice setconfig zeroconf_trusted_node $bob_node
|
|
|
|
|
$alice setconfig use_recoverable_channels false
|
|
|
|
|
wait_for_balance carol 1
|
|
|
|
|
echo "carol opens channel with bob"
|
|
|
|
|
$carol open_channel $bob_node 0.15 --password=''
|
|
|
|
|
new_blocks 3
|
|
|
|
|
wait_until_channel_open carol
|
|
|
|
|
echo "carol pays alice"
|
|
|
|
|
# note: set amount to 0.001 to test failure: 'payment too low'
|
2025-03-18 11:15:16 +01:00
|
|
|
invoice=$($alice add_request 0.01 --lightning --memo "invoice" | jq -r ".lightning_invoice")
|
2023-08-08 05:09:58 +02:00
|
|
|
$carol lnpay $invoice
|
|
|
|
|
fi
|
|
|
|
|
|
2021-10-25 12:00:00 +00:00
|
|
|
if [[ $1 == "unixsockets" ]]; then
|
|
|
|
|
# This looks different because it has to run the entire daemon
|
|
|
|
|
# Test domain socket behavior
|
|
|
|
|
./run_electrum --regtest daemon -d --rpcsock=unix # Start daemon with unix domain socket
|
|
|
|
|
./run_electrum --regtest stop # Errors if it can't connect
|
|
|
|
|
# Test custom socket path
|
|
|
|
|
f=$(mktemp --dry-run)
|
|
|
|
|
./run_electrum --regtest daemon -d --rpcsock=unix --rpcsockpath=$f
|
|
|
|
|
[ -S $f ] # filename exists and is socket
|
|
|
|
|
./run_electrum --regtest stop
|
|
|
|
|
rm $f # clean up
|
|
|
|
|
# Test for regressions in the ordinary TCP functionality.
|
|
|
|
|
./run_electrum --regtest daemon -d --rpcsock=tcp
|
|
|
|
|
./run_electrum --regtest stop
|
|
|
|
|
fi
|