@@ -24,21 +24,19 @@ extern crate secp256k1;
24
24
use bech32:: u5;
25
25
use bitcoin_hashes:: Hash ;
26
26
use bitcoin_hashes:: sha256;
27
- use lightning:: ln:: features:: InvoiceFeatures ;
28
27
use lightning:: ln:: channelmanager:: PaymentSecret ;
29
- #[ cfg( any( doc, test) ) ]
30
- use lightning:: routing:: network_graph:: RoutingFees ;
28
+ use lightning:: ln:: features:: InvoiceFeatures ;
31
29
use lightning:: routing:: router:: RouteHintHop ;
32
30
33
31
use secp256k1:: key:: PublicKey ;
34
32
use secp256k1:: { Message , Secp256k1 } ;
35
33
use secp256k1:: recovery:: RecoverableSignature ;
36
- use std:: ops:: Deref ;
37
34
35
+ use std:: fmt:: { Display , Formatter , self } ;
38
36
use std:: iter:: FilterMap ;
37
+ use std:: ops:: Deref ;
39
38
use std:: slice:: Iter ;
40
39
use std:: time:: { SystemTime , Duration , UNIX_EPOCH } ;
41
- use std:: fmt:: { Display , Formatter , self } ;
42
40
43
41
mod de;
44
42
mod ser;
@@ -1292,10 +1290,100 @@ impl<S> Display for SignOrCreationError<S> {
1292
1290
}
1293
1291
}
1294
1292
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
+
1295
1374
#[ cfg( test) ]
1296
1375
mod test {
1297
1376
use bitcoin_hashes:: hex:: FromHex ;
1298
1377
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;
1299
1387
1300
1388
#[ test]
1301
1389
fn test_system_time_bounds_assumptions ( ) {
@@ -1600,4 +1688,60 @@ mod test {
1600
1688
let raw_invoice = builder. build_raw ( ) . unwrap ( ) ;
1601
1689
assert_eq ! ( raw_invoice, * invoice. into_signed_raw( ) . raw_invoice( ) )
1602
1690
}
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
+ }
1603
1747
}
0 commit comments