@@ -20,6 +20,7 @@ use std::time::Duration;
2020use bitcoin:: Amount ;
2121use electrsd:: corepc_node:: Client as BitcoindClient ;
2222use electrum_client:: ElectrumApi ;
23+ use ldk_node:: bitcoin:: secp256k1:: PublicKey ;
2324use ldk_node:: { Event , Node } ;
2425
2526use super :: external_node:: ExternalNode ;
@@ -87,6 +88,29 @@ pub(crate) async fn wait_for_htlcs_settled(
8788 panic ! ( "HTLCs did not settle on {} channel {} within 15s" , peer. name( ) , ext_channel_id) ;
8889}
8990
91+ /// Blocks execution until the channel with the specified peer becomes active (`is_usable == true`).
92+ /// Maximum wait time is 15 seconds (30 attempts with a 500ms interval).
93+ pub ( crate ) async fn wait_for_channel_usable ( node : & Node , counterparty_node_id : PublicKey ) {
94+ let mut usable = false ;
95+
96+ for _ in 0 ..30 {
97+ for channel in node. list_channels ( ) {
98+ if channel. counterparty_node_id == counterparty_node_id && channel. is_usable {
99+ usable = true ;
100+ break ;
101+ }
102+ }
103+
104+ if usable {
105+ break ;
106+ }
107+
108+ tokio:: time:: sleep ( Duration :: from_millis ( 500 ) ) . await ;
109+ }
110+
111+ assert ! ( usable, "Timeout waiting for channel with {} to become usable" , counterparty_node_id) ;
112+ }
113+
90114/// Build a fresh LDK node configured for interop tests. Uses electrum at the
91115/// docker-compose default port and bumps sync timeouts for combo stress.
92116pub ( crate ) fn setup_ldk_node ( ) -> Node {
@@ -150,9 +174,15 @@ pub(crate) async fn run_interop_scenario<N, E, F>(
150174 node. stop ( ) . unwrap ( ) ;
151175}
152176
153- /// Open a channel, send a BOLT11 payment in each direction, then cooperatively close.
154- pub ( crate ) async fn basic_channel_cycle_scenario < E : ElectrumApi > (
177+ enum PaymentProtocol {
178+ Bolt11 ,
179+ Bolt12 ,
180+ }
181+
182+ /// Open a channel, send a BOLT11/BOLT12 payment in each direction, then cooperatively close.
183+ async fn basic_channel_cycle_scenario < E : ElectrumApi > (
155184 node : & Node , peer : & ( impl ExternalNode + ?Sized ) , bitcoind : & BitcoindClient , electrs : & E ,
185+ protocol : PaymentProtocol ,
156186) {
157187 let ( user_ch, ext_ch) = channel:: open_channel_to_external (
158188 node,
@@ -164,12 +194,36 @@ pub(crate) async fn basic_channel_cycle_scenario<E: ElectrumApi>(
164194 )
165195 . await ;
166196
167- payment:: send_bolt11_to_peer ( node, peer, 10_000_000 , "basic-send" ) . await ;
168- payment:: receive_bolt11_payment ( node, peer, 10_000_000 ) . await ;
197+ match protocol {
198+ PaymentProtocol :: Bolt11 => {
199+ payment:: send_bolt11_to_peer ( node, peer, 10_000_000 , "basic-send-bolt11" ) . await ;
200+ payment:: receive_bolt11_payment ( node, peer, 10_000_000 ) . await ;
201+ } ,
202+ PaymentProtocol :: Bolt12 => {
203+ payment:: send_bolt12_to_peer ( node, peer, 10_000_000 , "basic-send-bolt12" ) . await ;
204+ payment:: receive_bolt12_payment ( node, peer, 10_000_000 ) . await ;
205+ } ,
206+ }
169207
170208 channel:: cooperative_close ( node, peer, bitcoind, electrs, & user_ch, & ext_ch, Side :: Ldk ) . await ;
171209}
172210
211+ /// Specialized version of `basic_channel_cycle_scenario` for BOLT11 payments.
212+ /// See [`basic_channel_cycle_scenario`] for details.
213+ pub ( crate ) async fn basic_channel_cycle_bolt11_scenario < E : ElectrumApi > (
214+ node : & Node , peer : & ( impl ExternalNode + ?Sized ) , bitcoind : & BitcoindClient , electrs : & E ,
215+ ) {
216+ basic_channel_cycle_scenario ( node, peer, bitcoind, electrs, PaymentProtocol :: Bolt11 ) . await ;
217+ }
218+
219+ /// Specialized version of `basic_channel_cycle_scenario` for BOLT12 payments.
220+ /// See [`basic_channel_cycle_scenario`] for details.
221+ pub ( crate ) async fn basic_channel_cycle_bolt12_scenario < E : ElectrumApi > (
222+ node : & Node , peer : & ( impl ExternalNode + ?Sized ) , bitcoind : & BitcoindClient , electrs : & E ,
223+ ) {
224+ basic_channel_cycle_scenario ( node, peer, bitcoind, electrs, PaymentProtocol :: Bolt12 ) . await ;
225+ }
226+
173227/// Open a channel, send keysend in both directions, then cooperatively close.
174228pub ( crate ) async fn keysend_scenario < E : ElectrumApi > (
175229 node : & Node , peer : & ( impl ExternalNode + ?Sized ) , bitcoind : & BitcoindClient , electrs : & E ,
@@ -189,8 +243,9 @@ pub(crate) async fn keysend_scenario<E: ElectrumApi>(
189243}
190244
191245/// Open a channel, send a payment, then force-close from the LDK side.
192- pub ( crate ) async fn force_close_after_payment_scenario < E : ElectrumApi > (
246+ async fn force_close_after_payment_scenario < E : ElectrumApi > (
193247 node : & Node , peer : & ( impl ExternalNode + ?Sized ) , bitcoind : & BitcoindClient , electrs : & E ,
248+ protocol : PaymentProtocol ,
194249) {
195250 let ( user_ch, ext_ch) = channel:: open_channel_to_external (
196251 node,
@@ -201,11 +256,38 @@ pub(crate) async fn force_close_after_payment_scenario<E: ElectrumApi>(
201256 Some ( 500_000_000 ) ,
202257 )
203258 . await ;
204- payment:: send_bolt11_to_peer ( node, peer, 5_000_000 , "force-close" ) . await ;
259+
260+ match protocol {
261+ PaymentProtocol :: Bolt11 => {
262+ payment:: send_bolt11_to_peer ( node, peer, 5_000_000 , "force-close-bolt11" ) . await ;
263+ } ,
264+ PaymentProtocol :: Bolt12 => {
265+ payment:: send_bolt12_to_peer ( node, peer, 5_000_000 , "force-close-bolt12" ) . await ;
266+ } ,
267+ }
268+
205269 wait_for_htlcs_settled ( peer, & ext_ch) . await ;
206270 channel:: force_close ( node, peer, bitcoind, electrs, & user_ch, & ext_ch, Side :: Ldk ) . await ;
207271}
208272
273+ /// Specialized version of `force_close_after_payment_scenario` for BOLT11 payments.
274+ /// See [`force_close_after_payment_scenario`] for details.
275+ pub ( crate ) async fn force_close_after_payment_bolt11_scenario < E : ElectrumApi > (
276+ node : & Node , peer : & ( impl ExternalNode + ?Sized ) , bitcoind : & BitcoindClient , electrs : & E ,
277+ ) {
278+ force_close_after_payment_scenario ( node, peer, bitcoind, electrs, PaymentProtocol :: Bolt11 )
279+ . await ;
280+ }
281+
282+ /// Specialized version of `force_close_after_payment_scenario` for BOLT12 payments.
283+ /// See [`force_close_after_payment_scenario`] for details.
284+ pub ( crate ) async fn force_close_after_payment_bolt12_scenario < E : ElectrumApi > (
285+ node : & Node , peer : & ( impl ExternalNode + ?Sized ) , bitcoind : & BitcoindClient , electrs : & E ,
286+ ) {
287+ force_close_after_payment_scenario ( node, peer, bitcoind, electrs, PaymentProtocol :: Bolt12 )
288+ . await ;
289+ }
290+
209291/// Open a channel, dispatch a payment with a mid-flight disconnect+reconnect,
210292/// then cooperatively close.
211293pub ( crate ) async fn disconnect_during_payment_scenario < E : ElectrumApi > (
@@ -226,8 +308,9 @@ pub(crate) async fn disconnect_during_payment_scenario<E: ElectrumApi>(
226308}
227309
228310/// Open a channel, splice-in additional funds, send a post-splice payment, then close.
229- pub ( crate ) async fn splice_in_scenario < E : ElectrumApi > (
311+ async fn splice_in_scenario < E : ElectrumApi > (
230312 node : & Node , peer : & ( impl ExternalNode + ?Sized ) , bitcoind : & BitcoindClient , electrs : & E ,
313+ protocol : PaymentProtocol ,
231314) {
232315 let ( user_ch, ext_ch) = channel:: open_channel_to_external (
233316 node,
@@ -245,7 +328,33 @@ pub(crate) async fn splice_in_scenario<E: ElectrumApi>(
245328 sync_wallets_with_retry ( node) . await ;
246329 expect_channel_ready_event ! ( node, ext_node_id) ;
247330
248- payment:: send_bolt11_to_peer ( node, peer, 5_000_000 , "post-splice" ) . await ;
331+ match protocol {
332+ PaymentProtocol :: Bolt11 => {
333+ payment:: send_bolt11_to_peer ( node, peer, 5_000_000 , "post-splice-bolt11" ) . await ;
334+ } ,
335+ PaymentProtocol :: Bolt12 => {
336+ // Wait for Onion Message router updates the channel to usable state.
337+ // Without this, Bolt12 pathfinding will fail even though the channel technically fired `ChannelReady`.
338+ wait_for_channel_usable ( node, ext_node_id) . await ;
339+ payment:: send_bolt12_to_peer ( node, peer, 5_000_000 , "post-splice-bolt12" ) . await ;
340+ } ,
341+ }
249342
250343 channel:: cooperative_close ( node, peer, bitcoind, electrs, & user_ch, & ext_ch, Side :: Ldk ) . await ;
251344}
345+
346+ /// Specialized version of `splice_in_scenario` for BOLT11 payments.
347+ /// See [`splice_in_scenario`] for details.
348+ pub ( crate ) async fn splice_in_bolt11_scenario < E : ElectrumApi > (
349+ node : & Node , peer : & ( impl ExternalNode + ?Sized ) , bitcoind : & BitcoindClient , electrs : & E ,
350+ ) {
351+ splice_in_scenario ( node, peer, bitcoind, electrs, PaymentProtocol :: Bolt11 ) . await ;
352+ }
353+
354+ /// Specialized version of `splice_in_scenario` for BOLT12 payments.
355+ /// See [`splice_in_scenario`] for details.
356+ pub ( crate ) async fn splice_in_bolt12_scenario < E : ElectrumApi > (
357+ node : & Node , peer : & ( impl ExternalNode + ?Sized ) , bitcoind : & BitcoindClient , electrs : & E ,
358+ ) {
359+ splice_in_scenario ( node, peer, bitcoind, electrs, PaymentProtocol :: Bolt12 ) . await ;
360+ }
0 commit comments