Skip to content

Commit 5e14c24

Browse files
authored
Merge pull request #1894 from ssbright/2022-12-custom_payment_hash
Add invoice constructor with custom payment hash
2 parents 2cb3467 + 5f71fe9 commit 5e14c24

File tree

1 file changed

+82
-21
lines changed

1 file changed

+82
-21
lines changed

lightning-invoice/src/utils.rs

Lines changed: 82 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -294,12 +294,12 @@ pub fn create_invoice_from_channelmanager_with_description_hash_and_duration_sin
294294
network: Currency, amt_msat: Option<u64>, description_hash: Sha256,
295295
duration_since_epoch: Duration, invoice_expiry_delta_secs: u32
296296
) -> Result<Invoice, SignOrCreationError<()>>
297-
where
298-
M::Target: chain::Watch<<K::Target as KeysInterface>::Signer>,
299-
T::Target: BroadcasterInterface,
300-
K::Target: KeysInterface,
301-
F::Target: FeeEstimator,
302-
L::Target: Logger,
297+
where
298+
M::Target: chain::Watch<<K::Target as KeysInterface>::Signer>,
299+
T::Target: BroadcasterInterface,
300+
K::Target: KeysInterface,
301+
F::Target: FeeEstimator,
302+
L::Target: Logger,
303303
{
304304
_create_invoice_from_channelmanager_and_duration_since_epoch(
305305
channelmanager, keys_manager, logger, network, amt_msat,
@@ -316,12 +316,12 @@ pub fn create_invoice_from_channelmanager_and_duration_since_epoch<M: Deref, T:
316316
network: Currency, amt_msat: Option<u64>, description: String, duration_since_epoch: Duration,
317317
invoice_expiry_delta_secs: u32
318318
) -> Result<Invoice, SignOrCreationError<()>>
319-
where
320-
M::Target: chain::Watch<<K::Target as KeysInterface>::Signer>,
321-
T::Target: BroadcasterInterface,
322-
K::Target: KeysInterface,
323-
F::Target: FeeEstimator,
324-
L::Target: Logger,
319+
where
320+
M::Target: chain::Watch<<K::Target as KeysInterface>::Signer>,
321+
T::Target: BroadcasterInterface,
322+
K::Target: KeysInterface,
323+
F::Target: FeeEstimator,
324+
L::Target: Logger,
325325
{
326326
_create_invoice_from_channelmanager_and_duration_since_epoch(
327327
channelmanager, keys_manager, logger, network, amt_msat,
@@ -337,18 +337,62 @@ fn _create_invoice_from_channelmanager_and_duration_since_epoch<M: Deref, T: Der
337337
network: Currency, amt_msat: Option<u64>, description: InvoiceDescription,
338338
duration_since_epoch: Duration, invoice_expiry_delta_secs: u32
339339
) -> Result<Invoice, SignOrCreationError<()>>
340-
where
341-
M::Target: chain::Watch<<K::Target as KeysInterface>::Signer>,
342-
T::Target: BroadcasterInterface,
343-
K::Target: KeysInterface,
344-
F::Target: FeeEstimator,
345-
L::Target: Logger,
340+
where
341+
M::Target: chain::Watch<<K::Target as KeysInterface>::Signer>,
342+
T::Target: BroadcasterInterface,
343+
K::Target: KeysInterface,
344+
F::Target: FeeEstimator,
345+
L::Target: Logger,
346346
{
347347
// `create_inbound_payment` only returns an error if the amount is greater than the total bitcoin
348348
// supply.
349349
let (payment_hash, payment_secret) = channelmanager
350350
.create_inbound_payment(amt_msat, invoice_expiry_delta_secs)
351351
.map_err(|()| SignOrCreationError::CreationError(CreationError::InvalidAmount))?;
352+
_create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_hash(
353+
channelmanager, keys_manager, logger, network, amt_msat, description, duration_since_epoch, invoice_expiry_delta_secs, payment_hash, payment_secret)
354+
}
355+
356+
/// See [`create_invoice_from_channelmanager_and_duration_since_epoch`]
357+
/// This version allows for providing a custom [`PaymentHash`] for the invoice.
358+
/// This may be useful if you're building an on-chain swap or involving another protocol where
359+
/// the payment hash is also involved outside the scope of lightning.
360+
pub fn create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_hash<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>(
361+
channelmanager: &ChannelManager<M, T, K, F, L>, keys_manager: K, logger: L,
362+
network: Currency, amt_msat: Option<u64>, description: String, duration_since_epoch: Duration,
363+
invoice_expiry_delta_secs: u32, payment_hash: PaymentHash
364+
) -> Result<Invoice, SignOrCreationError<()>>
365+
where
366+
M::Target: chain::Watch<<K::Target as KeysInterface>::Signer>,
367+
T::Target: BroadcasterInterface,
368+
K::Target: KeysInterface,
369+
F::Target: FeeEstimator,
370+
L::Target: Logger,
371+
{
372+
let payment_secret = channelmanager
373+
.create_inbound_payment_for_hash(payment_hash,amt_msat, invoice_expiry_delta_secs)
374+
.map_err(|()| SignOrCreationError::CreationError(CreationError::InvalidAmount))?;
375+
_create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_hash(
376+
channelmanager, keys_manager, logger, network, amt_msat,
377+
InvoiceDescription::Direct(
378+
&Description::new(description).map_err(SignOrCreationError::CreationError)?,
379+
),
380+
duration_since_epoch, invoice_expiry_delta_secs, payment_hash, payment_secret
381+
)
382+
}
383+
384+
fn _create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_hash<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>(
385+
channelmanager: &ChannelManager<M, T, K, F, L>, keys_manager: K, logger: L,
386+
network: Currency, amt_msat: Option<u64>, description: InvoiceDescription, duration_since_epoch: Duration,
387+
invoice_expiry_delta_secs: u32, payment_hash: PaymentHash, payment_secret: PaymentSecret
388+
) -> Result<Invoice, SignOrCreationError<()>>
389+
where
390+
M::Target: chain::Watch<<K::Target as KeysInterface>::Signer>,
391+
T::Target: BroadcasterInterface,
392+
K::Target: KeysInterface,
393+
F::Target: FeeEstimator,
394+
L::Target: Logger,
395+
{
352396
let our_node_pubkey = channelmanager.get_our_node_id();
353397
let channels = channelmanager.list_channels();
354398

@@ -567,7 +611,7 @@ where
567611
mod test {
568612
use core::time::Duration;
569613
use crate::{Currency, Description, InvoiceDescription};
570-
use bitcoin_hashes::Hash;
614+
use bitcoin_hashes::{Hash, sha256};
571615
use bitcoin_hashes::sha256::Hash as Sha256;
572616
use lightning::chain::keysinterface::PhantomKeysManager;
573617
use lightning::ln::{PaymentPreimage, PaymentHash};
@@ -665,6 +709,25 @@ mod test {
665709
assert_eq!(invoice.description(), InvoiceDescription::Hash(&crate::Sha256(Sha256::hash("Testing description_hash".as_bytes()))));
666710
}
667711

712+
#[test]
713+
fn test_create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_hash() {
714+
let chanmon_cfgs = create_chanmon_cfgs(2);
715+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
716+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
717+
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
718+
let payment_hash = PaymentHash([0; 32]);
719+
let payment_secret = &nodes[1].node.create_inbound_payment_for_hash(payment_hash, Some(10_000), 3600);
720+
let invoice = crate::utils::create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_hash(
721+
&nodes[1].node, nodes[1].keys_manager, nodes[1].logger, Currency::BitcoinTestnet,
722+
Some(10_000), "test".to_string(), Duration::from_secs(1234567), 3600,
723+
payment_hash
724+
).unwrap();
725+
assert_eq!(invoice.amount_pico_btc(), Some(100_000));
726+
assert_eq!(invoice.min_final_cltv_expiry(), MIN_FINAL_CLTV_EXPIRY as u64);
727+
assert_eq!(invoice.description(), InvoiceDescription::Direct(&Description("test".to_string())));
728+
assert_eq!(invoice.payment_hash(), &sha256::Hash::from_slice(&payment_hash.0[..]).unwrap());
729+
}
730+
668731
#[test]
669732
fn test_hints_includes_single_channels_to_nodes() {
670733
let chanmon_cfgs = create_chanmon_cfgs(3);
@@ -691,10 +754,8 @@ mod test {
691754
let _chan_1_0_low_inbound_capacity = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 0, 100_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
692755
let chan_1_0_high_inbound_capacity = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 0, 10_000_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
693756
let _chan_1_0_medium_inbound_capacity = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 0, 1_000_000, 0, channelmanager::provided_init_features(), channelmanager::provided_init_features());
694-
695757
let mut scid_aliases = HashSet::new();
696758
scid_aliases.insert(chan_1_0_high_inbound_capacity.0.short_channel_id_alias.unwrap());
697-
698759
match_invoice_routes(Some(5000), &nodes[0], scid_aliases);
699760
}
700761

0 commit comments

Comments
 (0)