@@ -120,7 +120,7 @@ use event::{EventHandler, EventQueue};
120
120
use gossip:: GossipSource ;
121
121
use liquidity:: LiquiditySource ;
122
122
use payment_store:: PaymentStore ;
123
- pub use payment_store:: { PaymentDetails , PaymentDirection , PaymentStatus } ;
123
+ pub use payment_store:: { LSPFeeLimits , PaymentDetails , PaymentDirection , PaymentStatus } ;
124
124
use peer_store:: { PeerInfo , PeerStore } ;
125
125
use types:: {
126
126
Broadcaster , ChainMonitor , ChannelManager , FeeEstimator , KeysManager , NetworkGraph ,
@@ -1217,6 +1217,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
1217
1217
amount_msat : invoice. amount_milli_satoshis ( ) ,
1218
1218
direction : PaymentDirection :: Outbound ,
1219
1219
status : PaymentStatus :: Pending ,
1220
+ lsp_fee_limits : None ,
1220
1221
} ;
1221
1222
self . payment_store . insert ( payment) ?;
1222
1223
@@ -1236,6 +1237,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
1236
1237
amount_msat : invoice. amount_milli_satoshis ( ) ,
1237
1238
direction : PaymentDirection :: Outbound ,
1238
1239
status : PaymentStatus :: Failed ,
1240
+ lsp_fee_limits : None ,
1239
1241
} ;
1240
1242
1241
1243
self . payment_store . insert ( payment) ?;
@@ -1323,6 +1325,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
1323
1325
amount_msat : Some ( amount_msat) ,
1324
1326
direction : PaymentDirection :: Outbound ,
1325
1327
status : PaymentStatus :: Pending ,
1328
+ lsp_fee_limits : None ,
1326
1329
} ;
1327
1330
self . payment_store . insert ( payment) ?;
1328
1331
@@ -1343,6 +1346,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
1343
1346
amount_msat : Some ( amount_msat) ,
1344
1347
direction : PaymentDirection :: Outbound ,
1345
1348
status : PaymentStatus :: Failed ,
1349
+ lsp_fee_limits : None ,
1346
1350
} ;
1347
1351
self . payment_store . insert ( payment) ?;
1348
1352
@@ -1397,6 +1401,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
1397
1401
status : PaymentStatus :: Pending ,
1398
1402
direction : PaymentDirection :: Outbound ,
1399
1403
amount_msat : Some ( amount_msat) ,
1404
+ lsp_fee_limits : None ,
1400
1405
} ;
1401
1406
self . payment_store . insert ( payment) ?;
1402
1407
@@ -1417,6 +1422,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
1417
1422
status : PaymentStatus :: Failed ,
1418
1423
direction : PaymentDirection :: Outbound ,
1419
1424
amount_msat : Some ( amount_msat) ,
1425
+ lsp_fee_limits : None ,
1420
1426
} ;
1421
1427
1422
1428
self . payment_store . insert ( payment) ?;
@@ -1590,13 +1596,109 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
1590
1596
amount_msat,
1591
1597
direction : PaymentDirection :: Inbound ,
1592
1598
status : PaymentStatus :: Pending ,
1599
+ lsp_fee_limits : None ,
1593
1600
} ;
1594
1601
1595
1602
self . payment_store . insert ( payment) ?;
1596
1603
1597
1604
Ok ( invoice)
1598
1605
}
1599
1606
1607
+ /// Returns a payable invoice that can be used to request a payment of the amount given and
1608
+ /// receive it via a newly created just-in-time (JIT) channel.
1609
+ ///
1610
+ /// When the returned invoice is paid, the configured [LSPS2]-compliant LSP will open a channel
1611
+ /// to us, supplying just-in-time inbound liquidity.
1612
+ ///
1613
+ /// If set, `max_total_lsp_fee_limit_msat` will limit how much fee we allow the LSP to take for opening the
1614
+ /// channel to us. We'll use its cheapest offer otherwise.
1615
+ ///
1616
+ /// [LSPS2]: https://github.com/BitcoinAndLightningLayerSpecs/lsp/blob/main/LSPS2/README.md
1617
+ pub fn receive_payment_via_jit_channel (
1618
+ & self , amount_msat : u64 , description : & str , expiry_secs : u32 ,
1619
+ max_total_lsp_fee_limit_msat : Option < u64 > ,
1620
+ ) -> Result < Bolt11Invoice , Error > {
1621
+ self . receive_payment_via_jit_channel_inner (
1622
+ Some ( amount_msat) ,
1623
+ description,
1624
+ expiry_secs,
1625
+ max_total_lsp_fee_limit_msat,
1626
+ )
1627
+ }
1628
+
1629
+ fn receive_payment_via_jit_channel_inner (
1630
+ & self , amount_msat : Option < u64 > , description : & str , expiry_secs : u32 ,
1631
+ max_total_lsp_fee_limit_msat : Option < u64 > ,
1632
+ ) -> Result < Bolt11Invoice , Error > {
1633
+ let liquidity_source =
1634
+ self . liquidity_source . as_ref ( ) . ok_or ( Error :: LiquiditySourceUnavailable ) ?;
1635
+
1636
+ let ( node_id, address) = liquidity_source
1637
+ . get_liquidity_source_details ( )
1638
+ . ok_or ( Error :: LiquiditySourceUnavailable ) ?;
1639
+
1640
+ let rt_lock = self . runtime . read ( ) . unwrap ( ) ;
1641
+ let runtime = rt_lock. as_ref ( ) . unwrap ( ) ;
1642
+
1643
+ let peer_info = PeerInfo { node_id, address } ;
1644
+
1645
+ let con_node_id = peer_info. node_id ;
1646
+ let con_addr = peer_info. address . clone ( ) ;
1647
+ let con_logger = Arc :: clone ( & self . logger ) ;
1648
+ let con_pm = Arc :: clone ( & self . peer_manager ) ;
1649
+
1650
+ // We need to use our main runtime here as a local runtime might not be around to poll
1651
+ // connection futures going forward.
1652
+ tokio:: task:: block_in_place ( move || {
1653
+ runtime. block_on ( async move {
1654
+ connect_peer_if_necessary ( con_node_id, con_addr, con_pm, con_logger) . await
1655
+ } )
1656
+ } ) ?;
1657
+
1658
+ log_info ! ( self . logger, "Connected to LSP {}@{}. " , peer_info. node_id, peer_info. address) ;
1659
+
1660
+ let liquidity_source = Arc :: clone ( & liquidity_source) ;
1661
+ let ( invoice, lsp_total_opening_fee) = tokio:: task:: block_in_place ( move || {
1662
+ runtime. block_on ( async move {
1663
+ if let Some ( amount_msat) = amount_msat {
1664
+ liquidity_source
1665
+ . lsps2_receive_to_jit_channel (
1666
+ amount_msat,
1667
+ description,
1668
+ expiry_secs,
1669
+ max_total_lsp_fee_limit_msat,
1670
+ )
1671
+ . await
1672
+ . map ( |( invoice, total_fee) | ( invoice, Some ( total_fee) ) )
1673
+ } else {
1674
+ // TODO: will be implemented in the next commit
1675
+ Err ( Error :: LiquidityRequestFailed )
1676
+ }
1677
+ } )
1678
+ } ) ?;
1679
+
1680
+ // Register payment in payment store.
1681
+ let payment_hash = PaymentHash ( invoice. payment_hash ( ) . to_byte_array ( ) ) ;
1682
+ let lsp_fee_limits =
1683
+ Some ( LSPFeeLimits { max_total_opening_fee_msat : lsp_total_opening_fee } ) ;
1684
+ let payment = PaymentDetails {
1685
+ hash : payment_hash,
1686
+ preimage : None ,
1687
+ secret : Some ( invoice. payment_secret ( ) . clone ( ) ) ,
1688
+ amount_msat,
1689
+ direction : PaymentDirection :: Inbound ,
1690
+ status : PaymentStatus :: Pending ,
1691
+ lsp_fee_limits,
1692
+ } ;
1693
+
1694
+ self . payment_store . insert ( payment) ?;
1695
+
1696
+ // Persist LSP peer to make sure we reconnect on restart.
1697
+ self . peer_store . add_peer ( peer_info) ?;
1698
+
1699
+ Ok ( invoice)
1700
+ }
1701
+
1600
1702
/// Retrieve the details of a specific payment with the given hash.
1601
1703
///
1602
1704
/// Returns `Some` if the payment was known and `None` otherwise.
0 commit comments