channeld: Code to implement splicing

Update the lightningd <-> channeld interface with lots of new commands to needed to facilitate spicing.

Implement the channeld splicing protocol leveraging the interactivetx protocol.

Implement lightningd’s channel_control to support channeld in its splicing efforts.

Changelog-Added: Added the features to enable splicing & resizing of active channels.
This commit is contained in:
Dusty Daemon
2023-07-27 14:37:52 -07:00
committed by Rusty Russell
parent ebd0a3fd69
commit 4628e3ace8
88 changed files with 4560 additions and 644 deletions

View File

@@ -1016,8 +1016,10 @@ def test_reconnect_remote_sends_no_sigs(node_factory):
l2.daemon.wait_for_logs([r'peer_out WIRE_ANNOUNCEMENT_SIGNATURES',
r'peer_out WIRE_ANNOUNCEMENT_SIGNATURES'])
count = ''.join(l1.daemon.logs).count(r'peer_out WIRE_ANNOUNCEMENT_SIGNATURES')
# l1 only did send them the first time
assert(''.join(l1.daemon.logs).count(r'peer_out WIRE_ANNOUNCEMENT_SIGNATURES') == 1)
assert(count == 1 or count == 2)
@pytest.mark.openchannel('v1')

View File

@@ -2225,8 +2225,9 @@ def test_list_features_only(node_factory):
'option_shutdown_anysegwit/odd',
'option_channel_type/odd',
'option_scid_alias/odd',
'option_zeroconf/odd',
'supports_open_accept_channel_type']
'option_zeroconf/odd']
expected += ['supports_open_accept_channel_type']
assert features == expected

View File

@@ -3886,6 +3886,8 @@ def test_sql(node_factory, bitcoind):
'type': 'string'},
{'name': 'total_funding_msat',
'type': 'msat'},
{'name': 'splice_amount',
'type': 's64'},
{'name': 'our_funding_msat',
'type': 'msat'},
{'name': 'scratch_txid',
@@ -4023,6 +4025,7 @@ def test_sql(node_factory, bitcoind):
'u16': 'INTEGER',
'u32': 'INTEGER',
'u64': 'INTEGER',
's64': 'INTEGER',
'msat': 'INTEGER',
'hex': 'BLOB',
'hash': 'BLOB',
@@ -4093,7 +4096,7 @@ def test_sql(node_factory, bitcoind):
assert len(bytes.fromhex(val)) == 32
elif col['type'] == "pubkey":
assert len(bytes.fromhex(val)) == 33
elif col['type'] in ("msat", "integer", "u64", "u32", "u16", "u8", "boolean"):
elif col['type'] in ("msat", "integer", "s64", "u64", "u32", "u16", "u8", "boolean"):
int(val)
elif col['type'] == "number":
float(val)

35
tests/test_splicing.py Normal file
View File

@@ -0,0 +1,35 @@
from fixtures import * # noqa: F401,F403
import os
import pytest
import unittest
@unittest.skipIf(os.environ.get("EXPERIMENTAL_SPLICING", '0') != '1', "Need experimental splicing turned on")
@pytest.mark.openchannel('v2')
def test_splice(node_factory, bitcoind):
l1, l2 = node_factory.line_graph(2, fundamount=1000000, wait_for_announce=True)
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'])

View File

@@ -2,7 +2,7 @@ from pyln.testing.utils import TEST_NETWORK, TIMEOUT, VALGRIND, DEVELOPER, DEPRE
from pyln.testing.utils import env, only_one, wait_for, write_config, TailableProc, sync_blockheight, wait_channel_quiescent, get_tx_p2wsh_outnum, mine_funding_to_announce, scid_to_int # noqa: F401
import bitstring
from pyln.client import Millisatoshi
from pyln.testing.utils import EXPERIMENTAL_DUAL_FUND
from pyln.testing.utils import EXPERIMENTAL_DUAL_FUND, EXPERIMENTAL_SPLICING
import time
COMPAT = env("COMPAT", "1") == "1"
@@ -42,6 +42,10 @@ def expected_peer_features(wumbo_channels=False, extra=[]):
if EXPERIMENTAL_DUAL_FUND:
# option_dual_fund
features += [29]
if EXPERIMENTAL_SPLICING:
features += [29] # option_dual_fund
features += [35] # option_quiesce
features += [63] # option_splice
return hex_bits(features + extra)
@@ -55,6 +59,10 @@ def expected_node_features(wumbo_channels=False, extra=[]):
if EXPERIMENTAL_DUAL_FUND:
# option_dual_fund
features += [29]
if EXPERIMENTAL_SPLICING:
features += [29] # option_dual_fund
features += [35] # option_quiesce
features += [63] # option_splice
return hex_bits(features + extra)