From b0af2a2c30d4a6946b5a54f82927034b30127c8a Mon Sep 17 00:00:00 2001 From: Dusty Daemon Date: Tue, 19 Sep 2023 15:22:40 -0400 Subject: [PATCH] splice: Gossip new scid on splice_lock Reset scid announced flag so the gossip system can re-announce it, and add test the confirm the new channel is seen after 6 blcoks and the old one drops after 12+ blocks. ChageLog-Fixed: Scid gossip fix for splices. --- channeld/channeld.c | 3 +++ tests/test_splicing.py | 49 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/channeld/channeld.c b/channeld/channeld.c index a2ee13dec561..2fd19fe6482f 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -756,6 +756,9 @@ static void check_mutual_splice_locked(struct peer *peer) &inflight->outpoint.txid); wire_sync_write(MASTER_FD, take(msg)); + /* We must regossip the scid since it has changed */ + peer->gossip_scid_announced = false; + channel_announcement_negotiate(peer); billboard_update(peer); send_channel_update(peer, 0); diff --git a/tests/test_splicing.py b/tests/test_splicing.py index 959e4d4dc614..c31670744a71 100644 --- a/tests/test_splicing.py +++ b/tests/test_splicing.py @@ -1,8 +1,10 @@ from fixtures import * # noqa: F401,F403 -from utils import TEST_NETWORK import pytest import unittest import time +from utils import ( + wait_for, TEST_NETWORK +) @pytest.mark.openchannel('v1') @@ -39,3 +41,48 @@ def test_splice(node_factory, bitcoind): # 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 + + +@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")