2023-07-27 23:37:52 +02:00
|
|
|
from fixtures import * # noqa: F401,F403
|
|
|
|
import pytest
|
|
|
|
import unittest
|
2023-08-16 04:58:53 +02:00
|
|
|
import time
|
2023-09-19 23:35:57 +02:00
|
|
|
from utils import (
|
|
|
|
wait_for, TEST_NETWORK
|
|
|
|
)
|
2023-07-27 23:37:52 +02:00
|
|
|
|
|
|
|
|
2023-08-08 02:12:50 +02:00
|
|
|
@pytest.mark.openchannel('v1')
|
2023-07-27 23:37:52 +02:00
|
|
|
@pytest.mark.openchannel('v2')
|
2023-08-08 02:12:50 +02:00
|
|
|
@unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need')
|
2023-07-27 23:37:52 +02:00
|
|
|
def test_splice(node_factory, bitcoind):
|
2023-08-08 02:12:50 +02:00
|
|
|
l1, l2 = node_factory.line_graph(2, fundamount=1000000, wait_for_announce=True, opts={'experimental-splicing': None})
|
2023-07-27 23:37:52 +02:00
|
|
|
|
|
|
|
chan_id = l1.get_channel_id(l2)
|
|
|
|
|
|
|
|
# add extra sats to pay fee
|
|
|
|
funds_result = l1.rpc.fundpsbt("109000sat", "slow", 166, excess_as_change=True)
|
|
|
|
|
|
|
|
result = l1.rpc.splice_init(chan_id, 100000, funds_result['psbt'])
|
|
|
|
result = l1.rpc.splice_update(chan_id, result['psbt'])
|
|
|
|
result = l1.rpc.signpsbt(result['psbt'])
|
|
|
|
result = l1.rpc.splice_signed(chan_id, result['signed_psbt'])
|
|
|
|
|
|
|
|
l2.daemon.wait_for_log(r'CHANNELD_NORMAL to CHANNELD_AWAITING_SPLICE')
|
|
|
|
l1.daemon.wait_for_log(r'CHANNELD_NORMAL to CHANNELD_AWAITING_SPLICE')
|
|
|
|
|
|
|
|
mempool = bitcoind.rpc.getrawmempool(True)
|
|
|
|
assert len(list(mempool.keys())) == 1
|
|
|
|
assert result['txid'] in list(mempool.keys())
|
|
|
|
|
|
|
|
bitcoind.generate_block(6, wait_for_mempool=1)
|
|
|
|
|
|
|
|
l2.daemon.wait_for_log(r'CHANNELD_AWAITING_SPLICE to CHANNELD_NORMAL')
|
|
|
|
l1.daemon.wait_for_log(r'CHANNELD_AWAITING_SPLICE to CHANNELD_NORMAL')
|
|
|
|
|
|
|
|
inv = l2.rpc.invoice(10**2, '3', 'no_3')
|
|
|
|
l1.rpc.pay(inv['bolt11'])
|
2023-08-16 04:58:53 +02:00
|
|
|
|
|
|
|
# Check that the splice doesn't generate a unilateral close transaction
|
|
|
|
time.sleep(5)
|
|
|
|
assert l1.db_query("SELECT count(*) as c FROM channeltxs;")[0]['c'] == 0
|
2023-09-19 23:35:57 +02:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.openchannel('v1')
|
|
|
|
@pytest.mark.openchannel('v2')
|
|
|
|
@unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need')
|
|
|
|
def test_splice_gossip(node_factory, bitcoind):
|
|
|
|
l1, l2, l3 = node_factory.line_graph(3, fundamount=1000000, wait_for_announce=True, opts={'experimental-splicing': None})
|
|
|
|
|
|
|
|
chan_id = l1.get_channel_id(l2)
|
|
|
|
|
|
|
|
# add extra sats to pay fee
|
|
|
|
funds_result = l1.rpc.fundpsbt("109000sat", "slow", 166, excess_as_change=True)
|
|
|
|
|
|
|
|
result = l1.rpc.splice_init(chan_id, 100000, funds_result['psbt'])
|
|
|
|
result = l1.rpc.splice_update(chan_id, result['psbt'])
|
|
|
|
result = l1.rpc.signpsbt(result['psbt'])
|
|
|
|
result = l1.rpc.splice_signed(chan_id, result['signed_psbt'])
|
|
|
|
|
|
|
|
l2.daemon.wait_for_log(r'CHANNELD_NORMAL to CHANNELD_AWAITING_SPLICE')
|
|
|
|
l1.daemon.wait_for_log(r'CHANNELD_NORMAL to CHANNELD_AWAITING_SPLICE')
|
|
|
|
|
|
|
|
mempool = bitcoind.rpc.getrawmempool(True)
|
|
|
|
assert len(list(mempool.keys())) == 1
|
|
|
|
assert result['txid'] in list(mempool.keys())
|
|
|
|
|
|
|
|
bitcoind.generate_block(6, wait_for_mempool=1)
|
|
|
|
|
|
|
|
l2.daemon.wait_for_log(r'CHANNELD_AWAITING_SPLICE to CHANNELD_NORMAL')
|
|
|
|
l1.daemon.wait_for_log(r'CHANNELD_AWAITING_SPLICE to CHANNELD_NORMAL')
|
|
|
|
|
|
|
|
# l3 should see the old channel and new channel at the same time here
|
|
|
|
wait_for(lambda: len(l3.rpc.listchannels()['channels']) == 6)
|
|
|
|
|
|
|
|
bitcoind.generate_block(7)
|
|
|
|
|
|
|
|
# The old channel should fall off l3's perspective
|
|
|
|
wait_for(lambda: len(l3.rpc.listchannels()['channels']) == 4)
|
|
|
|
|
|
|
|
# Check that the splice doesn't generate a unilateral close transaction
|
|
|
|
time.sleep(5)
|
|
|
|
assert l1.db_query("SELECT count(*) as c FROM channeltxs;")[0]['c'] == 0
|
|
|
|
|
|
|
|
# Check for channel announcement failure
|
|
|
|
assert not l1.daemon.is_in_log("invalid local_channel_announcement")
|
|
|
|
assert not l2.daemon.is_in_log("invalid local_channel_announcement")
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.openchannel('v1')
|
|
|
|
@pytest.mark.openchannel('v2')
|
|
|
|
@unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need')
|
|
|
|
def test_splice_listnodes(node_factory, bitcoind):
|
|
|
|
# Here we do a splice but underfund it purposefully
|
|
|
|
l1, l2 = node_factory.line_graph(2, fundamount=1000000, wait_for_announce=True, opts={'experimental-splicing': None})
|
|
|
|
|
|
|
|
chan_id = l1.get_channel_id(l2)
|
|
|
|
|
|
|
|
# add extra sats to pay fee
|
|
|
|
funds_result = l1.rpc.fundpsbt("109000sat", "slow", 166, excess_as_change=True)
|
|
|
|
|
|
|
|
result = l1.rpc.splice_init(chan_id, 100000, funds_result['psbt'])
|
|
|
|
result = l1.rpc.splice_update(chan_id, result['psbt'])
|
|
|
|
result = l1.rpc.signpsbt(result['psbt'])
|
|
|
|
result = l1.rpc.splice_signed(chan_id, result['signed_psbt'])
|
|
|
|
|
|
|
|
l2.daemon.wait_for_log(r'CHANNELD_NORMAL to CHANNELD_AWAITING_SPLICE')
|
|
|
|
l1.daemon.wait_for_log(r'CHANNELD_NORMAL to CHANNELD_AWAITING_SPLICE')
|
|
|
|
|
|
|
|
assert len(l1.rpc.listnodes()['nodes']) == 2
|
|
|
|
assert len(l2.rpc.listnodes()['nodes']) == 2
|
|
|
|
|
|
|
|
bitcoind.generate_block(6, wait_for_mempool=1)
|
|
|
|
|
|
|
|
l2.daemon.wait_for_log(r'CHANNELD_AWAITING_SPLICE to CHANNELD_NORMAL')
|
|
|
|
l1.daemon.wait_for_log(r'CHANNELD_AWAITING_SPLICE to CHANNELD_NORMAL')
|
|
|
|
|
|
|
|
bitcoind.generate_block(7)
|
|
|
|
|
|
|
|
assert len(l1.rpc.listnodes()['nodes']) == 2
|
|
|
|
assert len(l2.rpc.listnodes()['nodes']) == 2
|