Skip to content

Commit 3622a04

Browse files
committed
Add invoice constructor with custom payment hash
1 parent 5e577cb commit 3622a04

File tree

1 file changed

+81
-21
lines changed

1 file changed

+81
-21
lines changed

lightning-invoice/src/utils.rs

Lines changed: 81 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,61 @@ 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+
///Function that allows to construct invoices with the given payment hash.
358+
///This may be useful if you're building an on-chain swap or integrating with another protocol where the payment hash is fixed outside of lightning.
359+
pub fn create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_hash<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>(
360+
channelmanager: &ChannelManager<M, T, K, F, L>, keys_manager: K, logger: L,
361+
network: Currency, amt_msat: Option<u64>, description: String, duration_since_epoch: Duration,
362+
invoice_expiry_delta_secs: u32, payment_hash: PaymentHash
363+
) -> Result<Invoice, SignOrCreationError<()>>
364+
where
365+
M::Target: chain::Watch<<K::Target as KeysInterface>::Signer>,
366+
T::Target: BroadcasterInterface,
367+
K::Target: KeysInterface,
368+
F::Target: FeeEstimator,
369+
L::Target: Logger,
370+
{
371+
let payment_secret = channelmanager
372+
.create_inbound_payment_for_hash(payment_hash,amt_msat,invoice_expiry_delta_secs)
373+
.map_err(|()| SignOrCreationError::CreationError(CreationError::InvalidAmount))?;
374+
_create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_hash(
375+
channelmanager, keys_manager, logger, network, amt_msat,
376+
InvoiceDescription::Direct(
377+
&Description::new(description).map_err(SignOrCreationError::CreationError)?,
378+
),
379+
duration_since_epoch, invoice_expiry_delta_secs, payment_hash, payment_secret
380+
)
381+
}
382+
383+
fn _create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_hash<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>(
384+
channelmanager: &ChannelManager<M, T, K, F, L>, keys_manager: K, logger: L,
385+
network: Currency, amt_msat: Option<u64>, description: InvoiceDescription, duration_since_epoch: Duration,
386+
invoice_expiry_delta_secs: u32, payment_hash: PaymentHash, payment_secret: PaymentSecret
387+
) -> Result<Invoice, SignOrCreationError<()>>
388+
where
389+
M::Target: chain::Watch<<K::Target as KeysInterface>::Signer>,
390+
T::Target: BroadcasterInterface,
391+
K::Target: KeysInterface,
392+
F::Target: FeeEstimator,
393+
L::Target: Logger,
394+
{
352395
let our_node_pubkey = channelmanager.get_our_node_id();
353396
let channels = channelmanager.list_channels();
354397

@@ -567,7 +610,7 @@ where
567610
mod test {
568611
use core::time::Duration;
569612
use crate::{Currency, Description, InvoiceDescription};
570-
use bitcoin_hashes::Hash;
613+
use bitcoin_hashes::{Hash, sha256};
571614
use bitcoin_hashes::sha256::Hash as Sha256;
572615
use lightning::chain::keysinterface::PhantomKeysManager;
573616
use lightning::ln::{PaymentPreimage, PaymentHash};
@@ -665,6 +708,25 @@ mod test {
665708
assert_eq!(invoice.description(), InvoiceDescription::Hash(&crate::Sha256(Sha256::hash("Testing description_hash".as_bytes()))));
666709
}
667710

711+
#[test]
712+
fn test_create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_hash() {
713+
let chanmon_cfgs = create_chanmon_cfgs(2);
714+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
715+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
716+
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
717+
let payment_hash = PaymentHash([0; 32]);
718+
let payment_secret = &nodes[1].node.create_inbound_payment_for_hash(payment_hash, Some(10_000), 3600);
719+
let invoice = crate::utils::create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_hash(
720+
&nodes[1].node, nodes[1].keys_manager, nodes[1].logger, Currency::BitcoinTestnet,
721+
Some(10_000), "test".to_string(), Duration::from_secs(1234567), 3600,
722+
payment_hash
723+
).unwrap();
724+
assert_eq!(invoice.amount_pico_btc(), Some(100_000));
725+
assert_eq!(invoice.min_final_cltv_expiry(), MIN_FINAL_CLTV_EXPIRY as u64);
726+
assert_eq!(invoice.description(), InvoiceDescription::Direct(&Description("test".to_string())));
727+
assert_eq!(invoice.payment_hash(), &sha256::Hash::from_slice(&payment_hash.0[..]).unwrap());
728+
}
729+
668730
#[test]
669731
fn test_hints_includes_single_channels_to_nodes() {
670732
let chanmon_cfgs = create_chanmon_cfgs(3);
@@ -691,10 +753,8 @@ mod test {
691753
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());
692754
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());
693755
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-
695756
let mut scid_aliases = HashSet::new();
696757
scid_aliases.insert(chan_1_0_high_inbound_capacity.0.short_channel_id_alias.unwrap());
697-
698758
match_invoice_routes(Some(5000), &nodes[0], scid_aliases);
699759
}
700760

0 commit comments

Comments
 (0)