@@ -1291,7 +1291,8 @@ impl<S> Display for SignOrCreationError<S> {
1291
1291
}
1292
1292
1293
1293
mod utils {
1294
- use { CreationError , Currency , Invoice , InvoiceBuilder } ;
1294
+ use { Currency , Invoice , InvoiceBuilder , SemanticError , SignedRawInvoice } ;
1295
+ use bech32:: { FromBase32 , ToBase32 , u5} ;
1295
1296
use bitcoin_hashes:: Hash ;
1296
1297
use lightning:: chain;
1297
1298
use lightning:: chain:: chaininterface:: { BroadcasterInterface , FeeEstimator } ;
@@ -1301,15 +1302,14 @@ mod utils {
1301
1302
use lightning:: routing:: network_graph:: RoutingFees ;
1302
1303
use lightning:: routing:: router:: RouteHintHop ;
1303
1304
use lightning:: util:: logger:: Logger ;
1304
- use secp256k1:: Secp256k1 ;
1305
1305
use std:: ops:: Deref ;
1306
1306
1307
1307
/// Utility to construct an invoice.
1308
1308
#[ allow( dead_code) ]
1309
1309
pub fn from_channelmanager < Signer : Sign , M : Deref , T : Deref , K : Deref , F : Deref , L : Deref > (
1310
1310
channelmanager : & ChannelManager < Signer , M , T , K , F , L > , amt_msat : Option < u64 > , description : String ,
1311
- network : Currency ,
1312
- ) -> Result < Invoice , CreationError >
1311
+ network : Currency , keys_manager : & dyn KeysInterface < Signer = Signer >
1312
+ ) -> Result < Invoice , SemanticError >
1313
1313
where
1314
1314
M :: Target : chain:: Watch < Signer > ,
1315
1315
T :: Target : BroadcasterInterface ,
@@ -1347,7 +1347,6 @@ mod utils {
1347
1347
7200 , // default invoice expiry is 2 hours
1348
1348
0 ,
1349
1349
) ;
1350
- let secp_ctx = Secp256k1 :: new ( ) ;
1351
1350
let our_node_pubkey = channelmanager. get_our_node_id ( ) ;
1352
1351
let mut invoice = InvoiceBuilder :: new ( network)
1353
1352
. description ( description)
@@ -1364,9 +1363,29 @@ mod utils {
1364
1363
invoice = invoice. route ( hint) ;
1365
1364
}
1366
1365
1367
- invoice. build_signed ( |msg_hash| {
1368
- secp_ctx. sign_recoverable ( msg_hash, & channelmanager. get_our_node_secret ( ) )
1369
- } )
1366
+ let raw_invoice = invoice. build_raw ( ) . unwrap ( ) ;
1367
+ let hrp_str = raw_invoice. hrp . to_string ( ) ;
1368
+ let hrp_bytes = hrp_str. as_bytes ( ) ;
1369
+ let data_without_signature = raw_invoice. data . to_base32 ( ) ;
1370
+ let mut invoice_preimage = Vec :: < u8 > :: from ( hrp_bytes) ;
1371
+
1372
+ let mut data_part = Vec :: from ( data_without_signature) ;
1373
+ let overhang = ( data_part. len ( ) * 5 ) % 8 ;
1374
+ if overhang > 0 {
1375
+ // add padding if data does not end at a byte boundary
1376
+ data_part. push ( u5:: try_from_u8 ( 0 ) . unwrap ( ) ) ;
1377
+
1378
+ // if overhang is in (1..3) we need to add u5(0) padding two times
1379
+ if overhang < 3 {
1380
+ data_part. push ( u5:: try_from_u8 ( 0 ) . unwrap ( ) ) ;
1381
+ }
1382
+ }
1383
+
1384
+ invoice_preimage. extend_from_slice ( & Vec :: < u8 > :: from_base32 ( & data_part)
1385
+ . expect ( "No padding error may occur due to appended zero above." ) ) ;
1386
+ let signature = keys_manager. sign_invoice ( invoice_preimage) ;
1387
+ let signed_raw_invoice: Result < SignedRawInvoice , SemanticError > = raw_invoice. sign ( |_| Ok ( signature) ) ;
1388
+ Invoice :: from_signed ( signed_raw_invoice. unwrap ( ) )
1370
1389
}
1371
1390
1372
1391
}
@@ -1696,7 +1715,7 @@ mod test {
1696
1715
let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ None , None ] ) ;
1697
1716
let nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
1698
1717
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 ( ) ;
1718
+ let invoice = :: utils:: from_channelmanager ( & nodes[ 1 ] . node , Some ( 10_000 ) , "test" . to_string ( ) , Currency :: BitcoinTestnet , nodes [ 1 ] . keys_manager ) . unwrap ( ) ;
1700
1719
assert_eq ! ( invoice. amount_pico_btc( ) , Some ( 100_000 ) ) ;
1701
1720
assert_eq ! ( invoice. min_final_cltv_expiry( ) , Some ( & 9 ) ) ;
1702
1721
assert_eq ! ( invoice. description( ) , InvoiceDescription :: Direct ( & Description ( "test" . to_string( ) ) ) ) ;
0 commit comments