@@ -24,21 +24,19 @@ extern crate secp256k1;
2424use bech32:: u5;
2525use bitcoin_hashes:: Hash ;
2626use bitcoin_hashes:: sha256;
27- use lightning:: ln:: features:: InvoiceFeatures ;
2827use lightning:: ln:: channelmanager:: PaymentSecret ;
29- #[ cfg( any( doc, test) ) ]
30- use lightning:: routing:: network_graph:: RoutingFees ;
28+ use lightning:: ln:: features:: InvoiceFeatures ;
3129use lightning:: routing:: router:: RouteHintHop ;
3230
3331use secp256k1:: key:: PublicKey ;
3432use secp256k1:: { Message , Secp256k1 } ;
3533use secp256k1:: recovery:: RecoverableSignature ;
36- use std:: ops:: Deref ;
3734
35+ use std:: fmt:: { Display , Formatter , self } ;
3836use std:: iter:: FilterMap ;
37+ use std:: ops:: Deref ;
3938use std:: slice:: Iter ;
4039use std:: time:: { SystemTime , Duration , UNIX_EPOCH } ;
41- use std:: fmt:: { Display , Formatter , self } ;
4240
4341mod de;
4442mod ser;
@@ -1292,10 +1290,100 @@ impl<S> Display for SignOrCreationError<S> {
12921290 }
12931291}
12941292
1293+ mod utils {
1294+ use { CreationError , Currency , Invoice , InvoiceBuilder } ;
1295+ use bitcoin_hashes:: Hash ;
1296+ use lightning:: chain;
1297+ use lightning:: chain:: chaininterface:: { BroadcasterInterface , FeeEstimator } ;
1298+ use lightning:: chain:: keysinterface:: { Sign , KeysInterface } ;
1299+ use lightning:: ln:: channelmanager:: { ChannelManager , MIN_FINAL_CLTV_EXPIRY } ;
1300+ use lightning:: ln:: features:: InvoiceFeatures ;
1301+ use lightning:: routing:: network_graph:: RoutingFees ;
1302+ use lightning:: routing:: router:: RouteHintHop ;
1303+ use lightning:: util:: logger:: Logger ;
1304+ use secp256k1:: Secp256k1 ;
1305+ use std:: ops:: Deref ;
1306+
1307+ /// Utility to construct an invoice.
1308+ #[ allow( dead_code) ]
1309+ pub fn from_channelmanager < Signer : Sign , M : Deref , T : Deref , K : Deref , F : Deref , L : Deref > (
1310+ channelmanager : & ChannelManager < Signer , M , T , K , F , L > , amt_msat : Option < u64 > , description : String ,
1311+ network : Currency ,
1312+ ) -> Result < Invoice , CreationError >
1313+ where
1314+ M :: Target : chain:: Watch < Signer > ,
1315+ T :: Target : BroadcasterInterface ,
1316+ K :: Target : KeysInterface < Signer = Signer > ,
1317+ F :: Target : FeeEstimator ,
1318+ L :: Target : Logger ,
1319+ {
1320+ // Marshall route hints.
1321+ let our_channels = channelmanager. list_usable_channels ( ) ;
1322+ let mut route_hints = vec ! [ ] ;
1323+ for channel in our_channels {
1324+ let short_channel_id = match channel. short_channel_id {
1325+ Some ( id) => id,
1326+ None => continue ,
1327+ } ;
1328+ let forwarding_info = match channel. counterparty_forwarding_info {
1329+ Some ( info) => info,
1330+ None => continue ,
1331+ } ;
1332+ route_hints. push ( vec ! [ RouteHintHop {
1333+ src_node_id: channel. remote_network_id,
1334+ short_channel_id,
1335+ fees: RoutingFees {
1336+ base_msat: forwarding_info. fee_base_msat,
1337+ proportional_millionths: forwarding_info. fee_proportional_millionths,
1338+ } ,
1339+ cltv_expiry_delta: forwarding_info. cltv_expiry_delta,
1340+ htlc_minimum_msat: None ,
1341+ htlc_maximum_msat: None ,
1342+ } ] ) ;
1343+ }
1344+
1345+ let ( payment_hash, payment_secret) = channelmanager. create_inbound_payment (
1346+ amt_msat,
1347+ 7200 , // default invoice expiry is 2 hours
1348+ 0 ,
1349+ ) ;
1350+ let secp_ctx = Secp256k1 :: new ( ) ;
1351+ let our_node_pubkey = channelmanager. get_our_node_id ( ) ;
1352+ let mut invoice = InvoiceBuilder :: new ( network)
1353+ . description ( description)
1354+ . current_timestamp ( )
1355+ . payee_pub_key ( our_node_pubkey)
1356+ . payment_hash ( Hash :: from_slice ( & payment_hash. 0 ) . unwrap ( ) )
1357+ . payment_secret ( payment_secret)
1358+ . features ( InvoiceFeatures :: known ( ) )
1359+ . min_final_cltv_expiry ( MIN_FINAL_CLTV_EXPIRY . into ( ) ) ;
1360+ if let Some ( amt) = amt_msat {
1361+ invoice = invoice. amount_pico_btc ( amt * 10 ) ;
1362+ }
1363+ for hint in route_hints. drain ( ..) {
1364+ invoice = invoice. route ( hint) ;
1365+ }
1366+
1367+ invoice. build_signed ( |msg_hash| {
1368+ secp_ctx. sign_recoverable ( msg_hash, & channelmanager. get_our_node_secret ( ) )
1369+ } )
1370+ }
1371+
1372+ }
1373+
12951374#[ cfg( test) ]
12961375mod test {
12971376 use bitcoin_hashes:: hex:: FromHex ;
12981377 use bitcoin_hashes:: sha256;
1378+ use { Currency , Description , InvoiceDescription } ;
1379+ use lightning:: ln:: PaymentHash ;
1380+ use lightning:: ln:: functional_test_utils:: * ;
1381+ use lightning:: ln:: features:: InitFeatures ;
1382+ use lightning:: ln:: msgs:: ChannelMessageHandler ;
1383+ use lightning:: routing:: network_graph:: RoutingFees ;
1384+ use lightning:: routing:: router;
1385+ use lightning:: util:: events:: MessageSendEventsProvider ;
1386+ use lightning:: util:: test_utils;
12991387
13001388 #[ test]
13011389 fn test_system_time_bounds_assumptions ( ) {
@@ -1600,4 +1688,60 @@ mod test {
16001688 let raw_invoice = builder. build_raw ( ) . unwrap ( ) ;
16011689 assert_eq ! ( raw_invoice, * invoice. into_signed_raw( ) . raw_invoice( ) )
16021690 }
1691+
1692+ #[ test]
1693+ fn test_from_channelmanager ( ) {
1694+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
1695+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
1696+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ None , None ] ) ;
1697+ let nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
1698+ let _chan = create_announced_chan_between_nodes ( & nodes, 0 , 1 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
1699+ let invoice = :: utils:: from_channelmanager ( & nodes[ 1 ] . node , Some ( 10_000 ) , "test" . to_string ( ) , Currency :: BitcoinTestnet ) . unwrap ( ) ;
1700+ assert_eq ! ( invoice. amount_pico_btc( ) , Some ( 100_000 ) ) ;
1701+ assert_eq ! ( invoice. min_final_cltv_expiry( ) , Some ( & 9 ) ) ;
1702+ assert_eq ! ( invoice. description( ) , InvoiceDescription :: Direct ( & Description ( "test" . to_string( ) ) ) ) ;
1703+
1704+ let mut route_hints = invoice. routes ( ) . clone ( ) ;
1705+ let mut last_hops = Vec :: new ( ) ;
1706+ for hint in route_hints. drain ( ..) {
1707+ last_hops. push ( hint[ hint. len ( ) - 1 ] . clone ( ) ) ;
1708+ }
1709+ let amt_msat = invoice. amount_pico_btc ( ) . unwrap ( ) / 10 ;
1710+
1711+ let first_hops = nodes[ 0 ] . node . list_usable_channels ( ) ;
1712+ let network_graph = nodes[ 0 ] . net_graph_msg_handler . network_graph . read ( ) . unwrap ( ) ;
1713+ let logger = test_utils:: TestLogger :: new ( ) ;
1714+ let route = router:: get_route (
1715+ & nodes[ 0 ] . node . get_our_node_id ( ) ,
1716+ & network_graph,
1717+ & invoice. recover_payee_pub_key ( ) ,
1718+ Some ( invoice. features ( ) . unwrap ( ) . clone ( ) ) ,
1719+ Some ( & first_hops. iter ( ) . collect :: < Vec < _ > > ( ) ) ,
1720+ & last_hops. iter ( ) . collect :: < Vec < _ > > ( ) ,
1721+ amt_msat,
1722+ * invoice. min_final_cltv_expiry ( ) . unwrap ( ) as u32 ,
1723+ & logger,
1724+ ) . unwrap ( ) ;
1725+
1726+ let payment_event = {
1727+ let mut payment_hash = PaymentHash ( [ 0 ; 32 ] ) ;
1728+ payment_hash. 0 . copy_from_slice ( & invoice. payment_hash ( ) . as_ref ( ) [ 0 ..32 ] ) ;
1729+ nodes[ 0 ] . node . send_payment ( & route, payment_hash, & Some ( invoice. payment_secret ( ) . unwrap ( ) . clone ( ) ) ) . unwrap ( ) ;
1730+ let mut added_monitors = nodes[ 0 ] . chain_monitor . added_monitors . lock ( ) . unwrap ( ) ;
1731+ assert_eq ! ( added_monitors. len( ) , 1 ) ;
1732+ added_monitors. clear ( ) ;
1733+
1734+ let mut events = nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
1735+ assert_eq ! ( events. len( ) , 1 ) ;
1736+ SendEvent :: from_event ( events. remove ( 0 ) )
1737+
1738+ } ;
1739+ nodes[ 1 ] . node . handle_update_add_htlc ( & nodes[ 0 ] . node . get_our_node_id ( ) , & payment_event. msgs [ 0 ] ) ;
1740+ nodes[ 1 ] . node . handle_commitment_signed ( & nodes[ 0 ] . node . get_our_node_id ( ) , & payment_event. commitment_msg ) ;
1741+ let mut added_monitors = nodes[ 1 ] . chain_monitor . added_monitors . lock ( ) . unwrap ( ) ;
1742+ assert_eq ! ( added_monitors. len( ) , 1 ) ;
1743+ added_monitors. clear ( ) ;
1744+ let events = nodes[ 1 ] . node . get_and_clear_pending_msg_events ( ) ;
1745+ assert_eq ! ( events. len( ) , 2 ) ;
1746+ }
16031747}
0 commit comments