@@ -14,11 +14,12 @@ use lightning::ln::functional_test_utils::*;
1414use lightning:: ln:: msgs:: BaseMessageHandler ;
1515use lightning:: ln:: msgs:: ChannelMessageHandler ;
1616use lightning:: ln:: msgs:: MessageSendEvent ;
17+ use lightning:: ln:: msgs:: OnionMessageHandler ;
1718use lightning:: ln:: types:: ChannelId ;
1819use lightning:: offers:: invoice_request:: InvoiceRequestFields ;
1920use lightning:: offers:: offer:: OfferId ;
2021use lightning:: routing:: router:: { InFlightHtlcs , Route , RouteParameters , Router } ;
21- use lightning:: sign:: ReceiveAuthKey ;
22+ use lightning:: sign:: { RandomBytes , ReceiveAuthKey } ;
2223
2324use lightning_liquidity:: events:: LiquidityEvent ;
2425use lightning_liquidity:: lsps0:: ser:: LSPSDateTime ;
@@ -1616,6 +1617,269 @@ fn bolt12_custom_router_uses_lsps2_intercept_scid() {
16161617 assert_eq ! ( * lookup. short_channel_id. lock( ) . unwrap( ) , Some ( intercept_scid) ) ;
16171618}
16181619
1620+ #[ test]
1621+ fn bolt12_lsps2_end_to_end_test ( ) {
1622+ // End-to-end test of the BOLT12 + LSPS2 JIT channel flow. Three nodes: payer, service, client.
1623+ // client_trusts_lsp=true; funding transaction broadcast happens after client claims the HTLC.
1624+ let chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
1625+ let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
1626+
1627+ let mut service_node_config = test_default_channel_config ( ) ;
1628+ service_node_config. htlc_interception_flags = HTLCInterceptionFlags :: ToInterceptSCIDs as u8 ;
1629+
1630+ let mut client_node_config = test_default_channel_config ( ) ;
1631+ client_node_config. accept_inbound_channels = true ;
1632+ client_node_config. channel_config . accept_underpaying_htlcs = true ;
1633+
1634+ let node_chanmgrs = create_node_chanmgrs (
1635+ 3 ,
1636+ & node_cfgs,
1637+ & [ Some ( service_node_config) , Some ( client_node_config) , None ] ,
1638+ ) ;
1639+ let nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
1640+ let ( lsps_nodes, promise_secret) = setup_test_lsps2_nodes_with_payer ( nodes) ;
1641+ let LSPSNodesWithPayer { ref service_node, ref client_node, ref payer_node } = lsps_nodes;
1642+
1643+ let payer_node_id = payer_node. node . get_our_node_id ( ) ;
1644+ let service_node_id = service_node. inner . node . get_our_node_id ( ) ;
1645+ let client_node_id = client_node. inner . node . get_our_node_id ( ) ;
1646+
1647+ let service_handler = service_node. liquidity_manager . lsps2_service_handler ( ) . unwrap ( ) ;
1648+
1649+ create_chan_between_nodes_with_value ( & payer_node, & service_node. inner , 2_000_000 , 100_000 ) ;
1650+
1651+ let intercept_scid = service_node. node . get_intercept_scid ( ) ;
1652+ let user_channel_id = 42 ;
1653+ let cltv_expiry_delta: u32 = 144 ;
1654+ let payment_size_msat = Some ( 1_000_000 ) ;
1655+ let fee_base_msat = 1_000 ;
1656+
1657+ execute_lsps2_dance (
1658+ & lsps_nodes,
1659+ intercept_scid,
1660+ user_channel_id,
1661+ cltv_expiry_delta,
1662+ promise_secret,
1663+ payment_size_msat,
1664+ fee_base_msat,
1665+ ) ;
1666+
1667+ // Disconnect payer from client to ensure deterministic onion message routing through service.
1668+ payer_node. node . peer_disconnected ( client_node_id) ;
1669+ client_node. node . peer_disconnected ( payer_node_id) ;
1670+ payer_node. onion_messenger . peer_disconnected ( client_node_id) ;
1671+ client_node. onion_messenger . peer_disconnected ( payer_node_id) ;
1672+
1673+ #[ cfg( c_bindings) ]
1674+ let offer = {
1675+ let mut offer_builder = client_node. node . create_offer_builder ( ) . unwrap ( ) ;
1676+ offer_builder. amount_msats ( payment_size_msat. unwrap ( ) ) ;
1677+ offer_builder. build ( ) . unwrap ( )
1678+ } ;
1679+ #[ cfg( not( c_bindings) ) ]
1680+ let offer = client_node
1681+ . node
1682+ . create_offer_builder ( )
1683+ . unwrap ( )
1684+ . amount_msats ( payment_size_msat. unwrap ( ) )
1685+ . build ( )
1686+ . unwrap ( ) ;
1687+
1688+ let lsps2_router = Arc :: new ( LSPS2BOLT12Router :: new (
1689+ FailingRouter :: new ( ) ,
1690+ Arc :: new ( RandomBytes :: new ( [ 43 ; 32 ] ) ) ,
1691+ ) ) ;
1692+ lsps2_router. register_offer (
1693+ offer. id ( ) ,
1694+ LSPS2Bolt12InvoiceParameters {
1695+ counterparty_node_id : service_node_id,
1696+ intercept_scid,
1697+ cltv_expiry_delta,
1698+ } ,
1699+ ) ;
1700+
1701+ let lsps2_router = Arc :: clone ( & lsps2_router) ;
1702+ * client_node. router . override_create_blinded_payment_paths . lock ( ) . unwrap ( ) =
1703+ Some ( Box :: new ( move |recipient, local_node_receive_key, first_hops, tlvs, amount_msats| {
1704+ let secp_ctx = Secp256k1 :: new ( ) ;
1705+ lsps2_router. create_blinded_payment_paths (
1706+ recipient,
1707+ local_node_receive_key,
1708+ first_hops,
1709+ tlvs,
1710+ amount_msats,
1711+ & secp_ctx,
1712+ )
1713+ } ) ) ;
1714+
1715+ let payment_id = PaymentId ( [ 1 ; 32 ] ) ;
1716+ payer_node. node . pay_for_offer ( & offer, None , payment_id, Default :: default ( ) ) . unwrap ( ) ;
1717+
1718+ let onion_msg = payer_node
1719+ . onion_messenger
1720+ . next_onion_message_for_peer ( service_node_id)
1721+ . expect ( "Payer should send InvoiceRequest toward service" ) ;
1722+ service_node. onion_messenger . handle_onion_message ( payer_node_id, & onion_msg) ;
1723+
1724+ let fwd_msg = service_node
1725+ . onion_messenger
1726+ . next_onion_message_for_peer ( client_node_id)
1727+ . expect ( "Service should forward InvoiceRequest to client" ) ;
1728+ client_node. onion_messenger . handle_onion_message ( service_node_id, & fwd_msg) ;
1729+
1730+ let onion_msg = client_node
1731+ . onion_messenger
1732+ . next_onion_message_for_peer ( service_node_id)
1733+ . expect ( "Client should send Invoice toward service" ) ;
1734+ service_node. onion_messenger . handle_onion_message ( client_node_id, & onion_msg) ;
1735+
1736+ let fwd_msg = service_node
1737+ . onion_messenger
1738+ . next_onion_message_for_peer ( payer_node_id)
1739+ . expect ( "Service should forward Invoice to payer" ) ;
1740+ payer_node. onion_messenger . handle_onion_message ( service_node_id, & fwd_msg) ;
1741+
1742+ check_added_monitors ( & payer_node, 1 ) ;
1743+ let events = payer_node. node . get_and_clear_pending_msg_events ( ) ;
1744+ assert_eq ! ( events. len( ) , 1 ) ;
1745+ let ev = SendEvent :: from_event ( events[ 0 ] . clone ( ) ) ;
1746+
1747+ service_node. inner . node . handle_update_add_htlc ( payer_node_id, & ev. msgs [ 0 ] ) ;
1748+ do_commitment_signed_dance ( & service_node. inner , & payer_node, & ev. commitment_msg , false , true ) ;
1749+ service_node. inner . node . process_pending_htlc_forwards ( ) ;
1750+
1751+ let events = service_node. inner . node . get_and_clear_pending_events ( ) ;
1752+ assert_eq ! ( events. len( ) , 1 ) ;
1753+ let ( payment_hash, expected_outbound_amount_msat) = match & events[ 0 ] {
1754+ Event :: HTLCIntercepted {
1755+ intercept_id,
1756+ requested_next_hop_scid,
1757+ payment_hash,
1758+ expected_outbound_amount_msat,
1759+ ..
1760+ } => {
1761+ assert_eq ! ( * requested_next_hop_scid, intercept_scid) ;
1762+
1763+ service_handler
1764+ . htlc_intercepted (
1765+ * requested_next_hop_scid,
1766+ * intercept_id,
1767+ * expected_outbound_amount_msat,
1768+ * payment_hash,
1769+ )
1770+ . unwrap ( ) ;
1771+ ( * payment_hash, expected_outbound_amount_msat)
1772+ } ,
1773+ other => panic ! ( "Expected HTLCIntercepted event, got: {:?}" , other) ,
1774+ } ;
1775+
1776+ let open_channel_event = service_node. liquidity_manager . next_event ( ) . unwrap ( ) ;
1777+
1778+ match open_channel_event {
1779+ LiquidityEvent :: LSPS2Service ( LSPS2ServiceEvent :: OpenChannel {
1780+ their_network_key,
1781+ amt_to_forward_msat,
1782+ opening_fee_msat,
1783+ user_channel_id : uc_id,
1784+ intercept_scid : iscd,
1785+ } ) => {
1786+ assert_eq ! ( their_network_key, client_node_id) ;
1787+ assert_eq ! ( amt_to_forward_msat, payment_size_msat. unwrap( ) - fee_base_msat) ;
1788+ assert_eq ! ( opening_fee_msat, fee_base_msat) ;
1789+ assert_eq ! ( uc_id, user_channel_id) ;
1790+ assert_eq ! ( iscd, intercept_scid) ;
1791+ } ,
1792+ other => panic ! ( "Expected OpenChannel event, got: {:?}" , other) ,
1793+ } ;
1794+
1795+ let result =
1796+ service_handler. channel_needs_manual_broadcast ( user_channel_id, & client_node_id) . unwrap ( ) ;
1797+ assert ! ( result, "Channel should require manual broadcast" ) ;
1798+
1799+ let ( channel_id, funding_tx) = create_channel_with_manual_broadcast (
1800+ & service_node_id,
1801+ & client_node_id,
1802+ & service_node,
1803+ & client_node,
1804+ user_channel_id,
1805+ expected_outbound_amount_msat,
1806+ true ,
1807+ ) ;
1808+
1809+ service_handler. channel_ready ( user_channel_id, & channel_id, & client_node_id) . unwrap ( ) ;
1810+
1811+ service_node. inner . node . process_pending_htlc_forwards ( ) ;
1812+
1813+ let pay_event = {
1814+ {
1815+ let mut added_monitors =
1816+ service_node. inner . chain_monitor . added_monitors . lock ( ) . unwrap ( ) ;
1817+ assert_eq ! ( added_monitors. len( ) , 1 ) ;
1818+ added_monitors. clear ( ) ;
1819+ }
1820+ let mut events = service_node. inner . node . get_and_clear_pending_msg_events ( ) ;
1821+ assert_eq ! ( events. len( ) , 1 ) ;
1822+ SendEvent :: from_event ( events. remove ( 0 ) )
1823+ } ;
1824+
1825+ client_node. inner . node . handle_update_add_htlc ( service_node_id, & pay_event. msgs [ 0 ] ) ;
1826+ do_commitment_signed_dance (
1827+ & client_node. inner ,
1828+ & service_node. inner ,
1829+ & pay_event. commitment_msg ,
1830+ false ,
1831+ true ,
1832+ ) ;
1833+ client_node. inner . node . process_pending_htlc_forwards ( ) ;
1834+
1835+ let client_events = client_node. inner . node . get_and_clear_pending_events ( ) ;
1836+ assert_eq ! ( client_events. len( ) , 1 ) ;
1837+ let preimage = match & client_events[ 0 ] {
1838+ Event :: PaymentClaimable { payment_hash : ph, purpose, .. } => {
1839+ assert_eq ! ( * ph, payment_hash) ;
1840+ purpose. preimage ( )
1841+ } ,
1842+ other => panic ! ( "Expected PaymentClaimable event on client, got: {:?}" , other) ,
1843+ } ;
1844+
1845+ let broadcasted = service_node. inner . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) ;
1846+ assert ! ( broadcasted. is_empty( ) , "There should be no broadcasted txs yet" ) ;
1847+ drop ( broadcasted) ;
1848+
1849+ client_node. inner . node . claim_funds ( preimage. unwrap ( ) ) ;
1850+
1851+ claim_and_assert_forwarded_only (
1852+ & payer_node,
1853+ & service_node. inner ,
1854+ & client_node. inner ,
1855+ preimage. unwrap ( ) ,
1856+ ) ;
1857+
1858+ let service_events = service_node. node . get_and_clear_pending_events ( ) ;
1859+ assert_eq ! ( service_events. len( ) , 1 ) ;
1860+
1861+ let total_fee_msat = match service_events[ 0 ] . clone ( ) {
1862+ Event :: PaymentForwarded {
1863+ prev_node_id,
1864+ next_node_id,
1865+ skimmed_fee_msat,
1866+ total_fee_earned_msat,
1867+ ..
1868+ } => {
1869+ assert_eq ! ( prev_node_id, Some ( payer_node_id) ) ;
1870+ assert_eq ! ( next_node_id, Some ( client_node_id) ) ;
1871+ service_handler. payment_forwarded ( channel_id, skimmed_fee_msat. unwrap_or ( 0 ) ) . unwrap ( ) ;
1872+ Some ( total_fee_earned_msat. unwrap ( ) - skimmed_fee_msat. unwrap ( ) )
1873+ } ,
1874+ _ => panic ! ( "Expected PaymentForwarded event, got: {:?}" , service_events[ 0 ] ) ,
1875+ } ;
1876+
1877+ let broadcasted = service_node. inner . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) ;
1878+ assert ! ( broadcasted. iter( ) . any( |b| b. compute_txid( ) == funding_tx. compute_txid( ) ) ) ;
1879+
1880+ expect_payment_sent ( & payer_node, preimage. unwrap ( ) , Some ( total_fee_msat) , true , true ) ;
1881+ }
1882+
16191883fn create_channel_with_manual_broadcast (
16201884 service_node_id : & PublicKey , client_node_id : & PublicKey , service_node : & LiquidityNode ,
16211885 client_node : & LiquidityNode , user_channel_id : u128 , expected_outbound_amount_msat : & u64 ,
0 commit comments