@@ -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,262 @@ 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+ let offer = client_node
1674+ . node
1675+ . create_offer_builder ( )
1676+ . unwrap ( )
1677+ . amount_msats ( payment_size_msat. unwrap ( ) )
1678+ . build ( )
1679+ . unwrap ( ) ;
1680+
1681+ let lsps2_router = Arc :: new ( LSPS2BOLT12Router :: new (
1682+ FailingRouter :: new ( ) ,
1683+ Arc :: new ( RandomBytes :: new ( [ 43 ; 32 ] ) ) ,
1684+ ) ) ;
1685+ lsps2_router. register_offer (
1686+ offer. id ( ) ,
1687+ LSPS2Bolt12InvoiceParameters {
1688+ counterparty_node_id : service_node_id,
1689+ intercept_scid,
1690+ cltv_expiry_delta,
1691+ } ,
1692+ ) ;
1693+
1694+ let lsps2_router = Arc :: clone ( & lsps2_router) ;
1695+ * client_node. router . override_create_blinded_payment_paths . lock ( ) . unwrap ( ) =
1696+ Some ( Box :: new ( move |recipient, local_node_receive_key, first_hops, tlvs, amount_msats| {
1697+ let secp_ctx = Secp256k1 :: new ( ) ;
1698+ lsps2_router. create_blinded_payment_paths (
1699+ recipient,
1700+ local_node_receive_key,
1701+ first_hops,
1702+ tlvs,
1703+ amount_msats,
1704+ & secp_ctx,
1705+ )
1706+ } ) ) ;
1707+
1708+ let payment_id = PaymentId ( [ 1 ; 32 ] ) ;
1709+ payer_node. node . pay_for_offer ( & offer, None , payment_id, Default :: default ( ) ) . unwrap ( ) ;
1710+
1711+ let onion_msg = payer_node
1712+ . onion_messenger
1713+ . next_onion_message_for_peer ( service_node_id)
1714+ . expect ( "Payer should send InvoiceRequest toward service" ) ;
1715+ service_node. onion_messenger . handle_onion_message ( payer_node_id, & onion_msg) ;
1716+
1717+ let fwd_msg = service_node
1718+ . onion_messenger
1719+ . next_onion_message_for_peer ( client_node_id)
1720+ . expect ( "Service should forward InvoiceRequest to client" ) ;
1721+ client_node. onion_messenger . handle_onion_message ( service_node_id, & fwd_msg) ;
1722+
1723+ let onion_msg = client_node
1724+ . onion_messenger
1725+ . next_onion_message_for_peer ( service_node_id)
1726+ . expect ( "Client should send Invoice toward service" ) ;
1727+ service_node. onion_messenger . handle_onion_message ( client_node_id, & onion_msg) ;
1728+
1729+ let fwd_msg = service_node
1730+ . onion_messenger
1731+ . next_onion_message_for_peer ( payer_node_id)
1732+ . expect ( "Service should forward Invoice to payer" ) ;
1733+ payer_node. onion_messenger . handle_onion_message ( service_node_id, & fwd_msg) ;
1734+
1735+ check_added_monitors ( & payer_node, 1 ) ;
1736+ let events = payer_node. node . get_and_clear_pending_msg_events ( ) ;
1737+ assert_eq ! ( events. len( ) , 1 ) ;
1738+ let ev = SendEvent :: from_event ( events[ 0 ] . clone ( ) ) ;
1739+
1740+ service_node. inner . node . handle_update_add_htlc ( payer_node_id, & ev. msgs [ 0 ] ) ;
1741+ do_commitment_signed_dance ( & service_node. inner , & payer_node, & ev. commitment_msg , false , true ) ;
1742+ service_node. inner . node . process_pending_htlc_forwards ( ) ;
1743+
1744+ let events = service_node. inner . node . get_and_clear_pending_events ( ) ;
1745+ assert_eq ! ( events. len( ) , 1 ) ;
1746+ let ( payment_hash, expected_outbound_amount_msat) = match & events[ 0 ] {
1747+ Event :: HTLCIntercepted {
1748+ intercept_id,
1749+ requested_next_hop_scid,
1750+ payment_hash,
1751+ expected_outbound_amount_msat,
1752+ ..
1753+ } => {
1754+ assert_eq ! ( * requested_next_hop_scid, intercept_scid) ;
1755+
1756+ service_handler
1757+ . htlc_intercepted (
1758+ * requested_next_hop_scid,
1759+ * intercept_id,
1760+ * expected_outbound_amount_msat,
1761+ * payment_hash,
1762+ )
1763+ . unwrap ( ) ;
1764+ ( * payment_hash, expected_outbound_amount_msat)
1765+ } ,
1766+ other => panic ! ( "Expected HTLCIntercepted event, got: {:?}" , other) ,
1767+ } ;
1768+
1769+ let open_channel_event = service_node. liquidity_manager . next_event ( ) . unwrap ( ) ;
1770+
1771+ match open_channel_event {
1772+ LiquidityEvent :: LSPS2Service ( LSPS2ServiceEvent :: OpenChannel {
1773+ their_network_key,
1774+ amt_to_forward_msat,
1775+ opening_fee_msat,
1776+ user_channel_id : uc_id,
1777+ intercept_scid : iscd,
1778+ } ) => {
1779+ assert_eq ! ( their_network_key, client_node_id) ;
1780+ assert_eq ! ( amt_to_forward_msat, payment_size_msat. unwrap( ) - fee_base_msat) ;
1781+ assert_eq ! ( opening_fee_msat, fee_base_msat) ;
1782+ assert_eq ! ( uc_id, user_channel_id) ;
1783+ assert_eq ! ( iscd, intercept_scid) ;
1784+ } ,
1785+ other => panic ! ( "Expected OpenChannel event, got: {:?}" , other) ,
1786+ } ;
1787+
1788+ let result =
1789+ service_handler. channel_needs_manual_broadcast ( user_channel_id, & client_node_id) . unwrap ( ) ;
1790+ assert ! ( result, "Channel should require manual broadcast" ) ;
1791+
1792+ let ( channel_id, funding_tx) = create_channel_with_manual_broadcast (
1793+ & service_node_id,
1794+ & client_node_id,
1795+ & service_node,
1796+ & client_node,
1797+ user_channel_id,
1798+ expected_outbound_amount_msat,
1799+ true ,
1800+ ) ;
1801+
1802+ service_handler. channel_ready ( user_channel_id, & channel_id, & client_node_id) . unwrap ( ) ;
1803+
1804+ service_node. inner . node . process_pending_htlc_forwards ( ) ;
1805+
1806+ let pay_event = {
1807+ {
1808+ let mut added_monitors =
1809+ service_node. inner . chain_monitor . added_monitors . lock ( ) . unwrap ( ) ;
1810+ assert_eq ! ( added_monitors. len( ) , 1 ) ;
1811+ added_monitors. clear ( ) ;
1812+ }
1813+ let mut events = service_node. inner . node . get_and_clear_pending_msg_events ( ) ;
1814+ assert_eq ! ( events. len( ) , 1 ) ;
1815+ SendEvent :: from_event ( events. remove ( 0 ) )
1816+ } ;
1817+
1818+ client_node. inner . node . handle_update_add_htlc ( service_node_id, & pay_event. msgs [ 0 ] ) ;
1819+ do_commitment_signed_dance (
1820+ & client_node. inner ,
1821+ & service_node. inner ,
1822+ & pay_event. commitment_msg ,
1823+ false ,
1824+ true ,
1825+ ) ;
1826+ client_node. inner . node . process_pending_htlc_forwards ( ) ;
1827+
1828+ let client_events = client_node. inner . node . get_and_clear_pending_events ( ) ;
1829+ assert_eq ! ( client_events. len( ) , 1 ) ;
1830+ let preimage = match & client_events[ 0 ] {
1831+ Event :: PaymentClaimable { payment_hash : ph, purpose, .. } => {
1832+ assert_eq ! ( * ph, payment_hash) ;
1833+ purpose. preimage ( )
1834+ } ,
1835+ other => panic ! ( "Expected PaymentClaimable event on client, got: {:?}" , other) ,
1836+ } ;
1837+
1838+ let broadcasted = service_node. inner . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) ;
1839+ assert ! ( broadcasted. is_empty( ) , "There should be no broadcasted txs yet" ) ;
1840+ drop ( broadcasted) ;
1841+
1842+ client_node. inner . node . claim_funds ( preimage. unwrap ( ) ) ;
1843+
1844+ claim_and_assert_forwarded_only (
1845+ & payer_node,
1846+ & service_node. inner ,
1847+ & client_node. inner ,
1848+ preimage. unwrap ( ) ,
1849+ ) ;
1850+
1851+ let service_events = service_node. node . get_and_clear_pending_events ( ) ;
1852+ assert_eq ! ( service_events. len( ) , 1 ) ;
1853+
1854+ let total_fee_msat = match service_events[ 0 ] . clone ( ) {
1855+ Event :: PaymentForwarded {
1856+ prev_node_id,
1857+ next_node_id,
1858+ skimmed_fee_msat,
1859+ total_fee_earned_msat,
1860+ ..
1861+ } => {
1862+ assert_eq ! ( prev_node_id, Some ( payer_node_id) ) ;
1863+ assert_eq ! ( next_node_id, Some ( client_node_id) ) ;
1864+ service_handler. payment_forwarded ( channel_id, skimmed_fee_msat. unwrap_or ( 0 ) ) . unwrap ( ) ;
1865+ Some ( total_fee_earned_msat. unwrap ( ) - skimmed_fee_msat. unwrap ( ) )
1866+ } ,
1867+ _ => panic ! ( "Expected PaymentForwarded event, got: {:?}" , service_events[ 0 ] ) ,
1868+ } ;
1869+
1870+ let broadcasted = service_node. inner . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) ;
1871+ assert ! ( broadcasted. iter( ) . any( |b| b. compute_txid( ) == funding_tx. compute_txid( ) ) ) ;
1872+
1873+ expect_payment_sent ( & payer_node, preimage. unwrap ( ) , Some ( total_fee_msat) , true , true ) ;
1874+ }
1875+
16191876fn create_channel_with_manual_broadcast (
16201877 service_node_id : & PublicKey , client_node_id : & PublicKey , service_node : & LiquidityNode ,
16211878 client_node : & LiquidityNode , user_channel_id : u128 , expected_outbound_amount_msat : & u64 ,
0 commit comments