Skip to content

Commit 0a20fa5

Browse files
authored
Merge pull request #4290 from jkczyz/2025-12-new-splice-api
Split splice initiation into two phases
2 parents 28e3335 + 20916b7 commit 0a20fa5

File tree

17 files changed

+1934
-1277
lines changed

17 files changed

+1934
-1277
lines changed

fuzz/src/chanmon_consistency.rs

Lines changed: 230 additions & 211 deletions
Large diffs are not rendered by default.

fuzz/src/full_stack.rs

Lines changed: 67 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use bitcoin::opcodes;
2222
use bitcoin::script::{Builder, ScriptBuf};
2323
use bitcoin::transaction::Version;
2424
use bitcoin::transaction::{Transaction, TxIn, TxOut};
25+
use bitcoin::FeeRate;
2526

2627
use bitcoin::hash_types::{BlockHash, Txid};
2728
use bitcoin::hashes::sha256::Hash as Sha256;
@@ -30,18 +31,16 @@ use bitcoin::hashes::Hash as _;
3031
use bitcoin::hex::FromHex;
3132
use bitcoin::WPubkeyHash;
3233

33-
use lightning::ln::funding::{FundingTxInput, SpliceContribution};
34-
3534
use lightning::blinded_path::message::{BlindedMessagePath, MessageContext, MessageForwardNode};
3635
use lightning::blinded_path::payment::{BlindedPaymentPath, ReceiveTlvs};
3736
use lightning::chain;
3837
use lightning::chain::chaininterface::{
39-
TransactionType, BroadcasterInterface, ConfirmationTarget, FeeEstimator,
38+
BroadcasterInterface, ConfirmationTarget, FeeEstimator, TransactionType,
4039
};
4140
use lightning::chain::chainmonitor;
4241
use lightning::chain::transaction::OutPoint;
4342
use lightning::chain::{BestBlock, ChannelMonitorUpdateStatus, Confirm, Listen};
44-
use lightning::events::bump_transaction::sync::WalletSourceSync;
43+
use lightning::events::bump_transaction::sync::{WalletSourceSync, WalletSync};
4544
use lightning::events::Event;
4645
use lightning::ln::channel_state::ChannelDetails;
4746
use lightning::ln::channelmanager::{ChainParameters, ChannelManager, InterceptId, PaymentId};
@@ -65,6 +64,7 @@ use lightning::sign::{
6564
SignerProvider,
6665
};
6766
use lightning::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret};
67+
use lightning::util::async_poll::{MaybeSend, MaybeSync};
6868
use lightning::util::config::{ChannelConfig, UserConfig};
6969
use lightning::util::hash_tables::*;
7070
use lightning::util::logger::Logger;
@@ -227,7 +227,7 @@ type ChannelMan<'a> = ChannelManager<
227227
Arc<dyn chain::Filter>,
228228
Arc<TestBroadcaster>,
229229
Arc<FuzzEstimator>,
230-
Arc<dyn Logger>,
230+
Arc<dyn Logger + MaybeSend + MaybeSync>,
231231
Arc<TestPersister>,
232232
Arc<KeyProvider>,
233233
>,
@@ -239,14 +239,20 @@ type ChannelMan<'a> = ChannelManager<
239239
Arc<FuzzEstimator>,
240240
&'a FuzzRouter,
241241
&'a FuzzRouter,
242-
Arc<dyn Logger>,
242+
Arc<dyn Logger + MaybeSend + MaybeSync>,
243243
>;
244244
type PeerMan<'a> = PeerManager<
245245
Peer<'a>,
246246
Arc<ChannelMan<'a>>,
247-
Arc<P2PGossipSync<Arc<NetworkGraph<Arc<dyn Logger>>>, Arc<dyn UtxoLookup>, Arc<dyn Logger>>>,
247+
Arc<
248+
P2PGossipSync<
249+
Arc<NetworkGraph<Arc<dyn Logger + MaybeSend + MaybeSync>>>,
250+
Arc<dyn UtxoLookup>,
251+
Arc<dyn Logger + MaybeSend + MaybeSync>,
252+
>,
253+
>,
248254
IgnoringMessageHandler,
249-
Arc<dyn Logger>,
255+
Arc<dyn Logger + MaybeSend + MaybeSync>,
250256
IgnoringMessageHandler,
251257
Arc<KeyProvider>,
252258
IgnoringMessageHandler,
@@ -260,7 +266,7 @@ struct MoneyLossDetector<'a> {
260266
Arc<dyn chain::Filter>,
261267
Arc<TestBroadcaster>,
262268
Arc<FuzzEstimator>,
263-
Arc<dyn Logger>,
269+
Arc<dyn Logger + MaybeSend + MaybeSync>,
264270
Arc<TestPersister>,
265271
Arc<KeyProvider>,
266272
>,
@@ -285,7 +291,7 @@ impl<'a> MoneyLossDetector<'a> {
285291
Arc<dyn chain::Filter>,
286292
Arc<TestBroadcaster>,
287293
Arc<FuzzEstimator>,
288-
Arc<dyn Logger>,
294+
Arc<dyn Logger + MaybeSend + MaybeSync>,
289295
Arc<TestPersister>,
290296
Arc<KeyProvider>,
291297
>,
@@ -520,7 +526,7 @@ impl SignerProvider for KeyProvider {
520526
}
521527

522528
#[inline]
523-
pub fn do_test(mut data: &[u8], logger: &Arc<dyn Logger>) {
529+
pub fn do_test(mut data: &[u8], logger: &Arc<dyn Logger + MaybeSend + MaybeSync>) {
524530
if data.len() < 32 {
525531
return;
526532
}
@@ -668,9 +674,7 @@ pub fn do_test(mut data: &[u8], logger: &Arc<dyn Logger>) {
668674
script_pubkey: wallet.get_change_script().unwrap(),
669675
}],
670676
};
671-
let coinbase_txid = coinbase_tx.compute_txid();
672-
wallet
673-
.add_utxo(bitcoin::OutPoint { txid: coinbase_txid, vout: 0 }, Amount::from_sat(1_000_000));
677+
wallet.add_utxo(coinbase_tx.clone(), 0);
674678

675679
loop {
676680
match get_slice!(1)[0] {
@@ -1026,20 +1030,24 @@ pub fn do_test(mut data: &[u8], logger: &Arc<dyn Logger>) {
10261030
if splice_in_sats == 0 {
10271031
continue;
10281032
}
1029-
// Create a funding input from the coinbase transaction
1030-
if let Ok(input) = FundingTxInput::new_p2wpkh(coinbase_tx.clone(), 0) {
1031-
let contribution = SpliceContribution::splice_in(
1032-
Amount::from_sat(splice_in_sats.min(900_000)), // Cap at available funds minus fees
1033-
vec![input],
1034-
Some(wallet.get_change_script().unwrap()),
1035-
);
1036-
let _ = channelmanager.splice_channel(
1037-
&chan.channel_id,
1038-
&chan.counterparty.node_id,
1039-
contribution,
1040-
253, // funding_feerate_per_kw
1041-
None,
1042-
);
1033+
let chan_id = chan.channel_id;
1034+
let counterparty = chan.counterparty.node_id;
1035+
if let Ok(funding_template) = channelmanager.splice_channel(
1036+
&chan_id,
1037+
&counterparty,
1038+
FeeRate::from_sat_per_kwu(253),
1039+
) {
1040+
let wallet_sync = WalletSync::new(&wallet, Arc::clone(&logger));
1041+
if let Ok(contribution) = funding_template
1042+
.splice_in_sync(Amount::from_sat(splice_in_sats.min(900_000)), &wallet_sync)
1043+
{
1044+
let _ = channelmanager.funding_contributed(
1045+
&chan_id,
1046+
&counterparty,
1047+
contribution,
1048+
None,
1049+
);
1050+
}
10431051
}
10441052
},
10451053
// Splice-out: remove funds from a channel
@@ -1062,17 +1070,29 @@ pub fn do_test(mut data: &[u8], logger: &Arc<dyn Logger>) {
10621070
// Cap splice-out at a reasonable portion of channel capacity
10631071
let max_splice_out = chan.channel_value_satoshis / 4;
10641072
let splice_out_sats = splice_out_sats.min(max_splice_out).max(546); // At least dust limit
1065-
let contribution = SpliceContribution::splice_out(vec![TxOut {
1066-
value: Amount::from_sat(splice_out_sats),
1067-
script_pubkey: wallet.get_change_script().unwrap(),
1068-
}]);
1069-
let _ = channelmanager.splice_channel(
1070-
&chan.channel_id,
1071-
&chan.counterparty.node_id,
1072-
contribution,
1073-
253, // funding_feerate_per_kw
1074-
None,
1075-
);
1073+
let chan_id = chan.channel_id;
1074+
let counterparty = chan.counterparty.node_id;
1075+
if let Ok(funding_template) = channelmanager.splice_channel(
1076+
&chan_id,
1077+
&counterparty,
1078+
FeeRate::from_sat_per_kwu(253),
1079+
) {
1080+
let outputs = vec![TxOut {
1081+
value: Amount::from_sat(splice_out_sats),
1082+
script_pubkey: wallet.get_change_script().unwrap(),
1083+
}];
1084+
let wallet_sync = WalletSync::new(&wallet, Arc::clone(&logger));
1085+
if let Ok(contribution) =
1086+
funding_template.splice_out_sync(outputs, &wallet_sync)
1087+
{
1088+
let _ = channelmanager.funding_contributed(
1089+
&chan_id,
1090+
&counterparty,
1091+
contribution,
1092+
None,
1093+
);
1094+
}
1095+
}
10761096
},
10771097
_ => return,
10781098
}
@@ -1139,14 +1159,15 @@ pub fn do_test(mut data: &[u8], logger: &Arc<dyn Logger>) {
11391159
}
11401160
}
11411161

1142-
pub fn full_stack_test<Out: test_logger::Output>(data: &[u8], out: Out) {
1143-
let logger: Arc<dyn Logger> = Arc::new(test_logger::TestLogger::new("".to_owned(), out));
1162+
pub fn full_stack_test<Out: test_logger::Output + MaybeSend + MaybeSync>(data: &[u8], out: Out) {
1163+
let logger: Arc<dyn Logger + MaybeSend + MaybeSync> =
1164+
Arc::new(test_logger::TestLogger::new("".to_owned(), out));
11441165
do_test(data, &logger);
11451166
}
11461167

11471168
#[no_mangle]
11481169
pub extern "C" fn full_stack_run(data: *const u8, datalen: usize) {
1149-
let logger: Arc<dyn Logger> =
1170+
let logger: Arc<dyn Logger + MaybeSend + MaybeSync> =
11501171
Arc::new(test_logger::TestLogger::new("".to_owned(), test_logger::DevNull {}));
11511172
do_test(unsafe { std::slice::from_raw_parts(data, datalen) }, &logger);
11521173
}
@@ -1932,6 +1953,7 @@ pub fn write_fst_seeds(path: &str) {
19321953

19331954
#[cfg(test)]
19341955
mod tests {
1956+
use lightning::util::async_poll::{MaybeSend, MaybeSync};
19351957
use lightning::util::logger::{Logger, Record};
19361958
use std::collections::HashMap;
19371959
use std::sync::{Arc, Mutex};
@@ -1963,7 +1985,7 @@ mod tests {
19631985
let test = super::two_peer_forwarding_seed();
19641986

19651987
let logger = Arc::new(TrackingLogger { lines: Mutex::new(HashMap::new()) });
1966-
super::do_test(&test, &(Arc::clone(&logger) as Arc<dyn Logger>));
1988+
super::do_test(&test, &(Arc::clone(&logger) as Arc<dyn Logger + MaybeSend + MaybeSync>));
19671989

19681990
let log_entries = logger.lines.lock().unwrap();
19691991
// 1
@@ -1998,7 +2020,7 @@ mod tests {
19982020
let test = super::gossip_exchange_seed();
19992021

20002022
let logger = Arc::new(TrackingLogger { lines: Mutex::new(HashMap::new()) });
2001-
super::do_test(&test, &(Arc::clone(&logger) as Arc<dyn Logger>));
2023+
super::do_test(&test, &(Arc::clone(&logger) as Arc<dyn Logger + MaybeSend + MaybeSync>));
20022024

20032025
let log_entries = logger.lines.lock().unwrap();
20042026
assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Sending message to all peers except Some(PublicKey(0000000000000000000000000000000000000000000000000000000000000002ff00000000000000000000000000000000000000000000000000000000000002)) or the announced channel's counterparties: ChannelAnnouncement { node_signature_1: 3026020200b202200303030303030303030303030303030303030303030303030303030303030303, node_signature_2: 3026020200b202200202020202020202020202020202020202020202020202020202020202020202, bitcoin_signature_1: 3026020200b202200303030303030303030303030303030303030303030303030303030303030303, bitcoin_signature_2: 3026020200b202200202020202020202020202020202020202020202020202020202020202020202, contents: UnsignedChannelAnnouncement { features: [], chain_hash: 6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000, short_channel_id: 42, node_id_1: NodeId(030303030303030303030303030303030303030303030303030303030303030303), node_id_2: NodeId(020202020202020202020202020202020202020202020202020202020202020202), bitcoin_key_1: NodeId(030303030303030303030303030303030303030303030303030303030303030303), bitcoin_key_2: NodeId(020202020202020202020202020202020202020202020202020202020202020202), excess_data: [] } }".to_string())), Some(&1));
@@ -2011,7 +2033,7 @@ mod tests {
20112033
let test = super::splice_seed();
20122034

20132035
let logger = Arc::new(TrackingLogger { lines: Mutex::new(HashMap::new()) });
2014-
super::do_test(&test, &(Arc::clone(&logger) as Arc<dyn Logger>));
2036+
super::do_test(&test, &(Arc::clone(&logger) as Arc<dyn Logger + MaybeSend + MaybeSync>));
20152037

20162038
let log_entries = logger.lines.lock().unwrap();
20172039

fuzz/src/lsps_message.rs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -77,17 +77,20 @@ pub fn do_test(data: &[u8]) {
7777
genesis_block.header.time,
7878
));
7979

80-
let liquidity_manager = Arc::new(LiquidityManagerSync::new(
81-
Arc::clone(&keys_manager),
82-
Arc::clone(&keys_manager),
83-
Arc::clone(&manager),
84-
None::<Arc<dyn Filter + Send + Sync>>,
85-
None,
86-
kv_store,
87-
Arc::clone(&tx_broadcaster),
88-
None,
89-
None,
90-
).unwrap());
80+
let liquidity_manager = Arc::new(
81+
LiquidityManagerSync::new(
82+
Arc::clone(&keys_manager),
83+
Arc::clone(&keys_manager),
84+
Arc::clone(&manager),
85+
None::<Arc<dyn Filter + Send + Sync>>,
86+
None,
87+
kv_store,
88+
Arc::clone(&tx_broadcaster),
89+
None,
90+
None,
91+
)
92+
.unwrap(),
93+
);
9194
let mut reader = data;
9295
if let Ok(Some(msg)) = liquidity_manager.read(LSPS_MESSAGE_TYPE_ID, &mut reader) {
9396
let secp = Secp256k1::signing_only();

lightning-tests/src/upgrade_downgrade_tests.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ use lightning::chain::channelmonitor::{ANTI_REORG_DELAY, HTLC_FAIL_BACK_BUFFER};
4949
use lightning::events::bump_transaction::sync::WalletSourceSync;
5050
use lightning::events::{ClosureReason, Event, HTLCHandlingFailureType};
5151
use lightning::ln::functional_test_utils::*;
52-
use lightning::ln::funding::SpliceContribution;
5352
use lightning::ln::msgs::BaseMessageHandler as _;
5453
use lightning::ln::msgs::ChannelMessageHandler as _;
5554
use lightning::ln::msgs::MessageSendEvent;
@@ -453,11 +452,13 @@ fn do_test_0_1_htlc_forward_after_splice(fail_htlc: bool) {
453452
reconnect_b_c_args.send_announcement_sigs = (true, true);
454453
reconnect_nodes(reconnect_b_c_args);
455454

456-
let contribution = SpliceContribution::splice_out(vec![TxOut {
455+
let outputs = vec![TxOut {
457456
value: Amount::from_sat(1_000),
458457
script_pubkey: nodes[0].wallet_source.get_change_script().unwrap(),
459-
}]);
460-
let splice_tx = splice_channel(&nodes[0], &nodes[1], ChannelId(chan_id_bytes_a), contribution);
458+
}];
459+
let channel_id = ChannelId(chan_id_bytes_a);
460+
let funding_contribution = initiate_splice_out(&nodes[0], &nodes[1], channel_id, outputs);
461+
let (splice_tx, _) = splice_channel(&nodes[0], &nodes[1], channel_id, funding_contribution);
461462
for node in nodes.iter() {
462463
mine_transaction(node, &splice_tx);
463464
connect_blocks(node, ANTI_REORG_DELAY - 1);

0 commit comments

Comments
 (0)