Skip to content

Commit 6c4a8ea

Browse files
When processing BOLT12 payments, there was an asymmetry in the API where payer nodes receive InvoiceReceived events but payee nodes had no way to access the invoices they created and sent as far I know.
This commit adds: - New `Event::InvoiceSent` event generated when a BOLT12 invoice is created and sent in response to an invoice request - New `notify_bolt12_invoice_sent` configuration parameter in UserConfig (defaults to false) to enable/disable the event generation The InvoiceSent event provides the payee with access to: - The created BOLT12 invoice - The context of the BlindedMessagePath - The payment hash and payment secret Signed-off-by: Vincenzo Palazzo <[email protected]>
1 parent 217a5b0 commit 6c4a8ea

File tree

4 files changed

+87
-5
lines changed

4 files changed

+87
-5
lines changed

lightning/src/events/mod.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -968,6 +968,32 @@ pub enum Event {
968968
/// [`InvoiceError`]: crate::offers::invoice_error::InvoiceError
969969
responder: Option<Responder>,
970970
},
971+
/// Indicates a [`Bolt12Invoice`] was created and sent in response to an [`InvoiceRequest`] or
972+
/// a [`Refund`].
973+
///
974+
/// This event will only be generated if [`UserConfig::notify_bolt12_invoice_sent`] is set.
975+
/// This provides symmetrical functionality to [`Event::InvoiceReceived`] but for the payee side,
976+
/// allowing nodes to track and access invoices they have created.
977+
///
978+
/// # Failure Behavior and Persistence
979+
/// This event will eventually be replayed after failures-to-handle (i.e., the event handler
980+
/// returning `Err(ReplayEvent ())`) and will be persisted across restarts.
981+
///
982+
/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
983+
/// [`Refund`]: crate::offers::refund::Refund
984+
/// [`UserConfig::notify_bolt12_invoice_sent`]: crate::util::config::UserConfig::notify_bolt12_invoice_sent
985+
InvoiceSent {
986+
/// The invoice that was created and sent.
987+
invoice: Bolt12Invoice,
988+
/// The context of the [`BlindedMessagePath`] used to receive the original request.
989+
///
990+
/// [`BlindedMessagePath`]: crate::blinded_path::message::BlindedMessagePath
991+
context: Option<OffersContext>,
992+
/// The payment hash for the invoice.
993+
payment_hash: PaymentHash,
994+
/// The payment secret for the invoice.
995+
payment_secret: PaymentSecret,
996+
},
971997
/// Indicates an outbound payment we made succeeded (i.e. it made it all the way to its target
972998
/// and we got back the payment preimage for it).
973999
///
@@ -1980,6 +2006,15 @@ impl Writeable for Event {
19802006
(6, responder, option),
19812007
});
19822008
},
2009+
&Event::InvoiceSent { ref invoice, ref context, ref payment_hash, ref payment_secret } => {
2010+
42u8.write(writer)?;
2011+
write_tlv_fields!(writer, {
2012+
(0, invoice, required),
2013+
(2, context, option),
2014+
(4, payment_hash, required),
2015+
(6, payment_secret, required),
2016+
});
2017+
},
19832018
&Event::FundingTxBroadcastSafe {
19842019
ref channel_id,
19852020
ref user_channel_id,
@@ -2539,6 +2574,23 @@ impl MaybeReadable for Event {
25392574
};
25402575
f()
25412576
},
2577+
42u8 => {
2578+
let mut f = || {
2579+
_init_and_read_len_prefixed_tlv_fields!(reader, {
2580+
(0, invoice, required),
2581+
(2, context, option),
2582+
(4, payment_hash, required),
2583+
(6, payment_secret, required),
2584+
});
2585+
Ok(Some(Event::InvoiceSent {
2586+
invoice: invoice.0.unwrap(),
2587+
context,
2588+
payment_hash: payment_hash.0.unwrap(),
2589+
payment_secret: payment_secret.0.unwrap(),
2590+
}))
2591+
};
2592+
f()
2593+
},
25422594
43u8 => {
25432595
let mut channel_id = RequiredWrapper(None);
25442596
let mut user_channel_id = RequiredWrapper(None);

lightning/src/ln/channelmanager.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12864,7 +12864,7 @@ where
1286412864
None => return None,
1286512865
};
1286612866

12867-
let invoice_request = match self.flow.verify_invoice_request(invoice_request, context) {
12867+
let invoice_request = match self.flow.verify_invoice_request(invoice_request, context.clone()) {
1286812868
Ok(invoice_request) => invoice_request,
1286912869
Err(_) => return None,
1287012870
};
@@ -12888,13 +12888,26 @@ where
1288812888
};
1288912889

1289012890
let entropy = &*self.entropy_source;
12891-
let (response, context) = self.flow.create_response_for_invoice_request(
12891+
let (response, response_context) = self.flow.create_response_for_invoice_request(
1289212892
&self.node_signer, &self.router, entropy, invoice_request, amount_msats,
1289312893
payment_hash, payment_secret, self.list_usable_channels()
1289412894
);
1289512895

12896-
match context {
12897-
Some(context) => Some((response, responder.respond_with_reply_path(context))),
12896+
// Generate InvoiceSent event if configured to do so
12897+
if self.default_configuration.notify_bolt12_invoice_sent {
12898+
if let OffersMessage::Invoice(ref invoice) = response {
12899+
let event = Event::InvoiceSent {
12900+
invoice: invoice.clone(),
12901+
context: context.clone(),
12902+
payment_hash,
12903+
payment_secret,
12904+
};
12905+
self.pending_events.lock().unwrap().push_back((event, None));
12906+
}
12907+
}
12908+
12909+
match response_context {
12910+
Some(resp_context) => Some((response, responder.respond_with_reply_path(resp_context))),
1289812911
None => Some((response, responder.respond()))
1289912912
}
1290012913
},

lightning/src/ln/offers_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1186,7 +1186,7 @@ fn pays_bolt12_invoice_asynchronously() {
11861186
let onion_message = alice.onion_messenger.next_onion_message_for_peer(bob_id).unwrap();
11871187
bob.onion_messenger.handle_onion_message(alice_id, &onion_message);
11881188

1189-
// Re-process the same onion message to ensure idempotency —
1189+
// Re-process the same onion message to ensure idempotency —
11901190
// we should not generate a duplicate `InvoiceReceived` event.
11911191
bob.onion_messenger.handle_onion_message(alice_id, &onion_message);
11921192

lightning/src/util/config.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -919,6 +919,21 @@ pub struct UserConfig {
919919
/// [`ChannelManager::send_payment_for_bolt12_invoice`]: crate::ln::channelmanager::ChannelManager::send_payment_for_bolt12_invoice
920920
/// [`ChannelManager::abandon_payment`]: crate::ln::channelmanager::ChannelManager::abandon_payment
921921
pub manually_handle_bolt12_invoices: bool,
922+
/// If this is set to `true`, the user will receive [`Event::InvoiceSent`] events when a
923+
/// BOLT12 invoice is created and sent to a payer.
924+
///
925+
/// This provides symmetrical functionality to [`Event::InvoiceReceived`] but for the payee side,
926+
/// allowing nodes to track and access invoices they have created. This can be useful for
927+
/// accounting, proof of invoice creation, or debugging purposes.
928+
///
929+
/// When set to `true`, [`Event::InvoiceSent`] will be generated whenever a BOLT12 invoice
930+
/// is successfully created and sent in response to an invoice request.
931+
///
932+
/// Default value: `false`
933+
///
934+
/// [`Event::InvoiceSent`]: crate::events::Event::InvoiceSent
935+
/// [`Event::InvoiceReceived`]: crate::events::Event::InvoiceReceived
936+
pub notify_bolt12_invoice_sent: bool,
922937
/// If this is set to `true`, dual-funded channels will be enabled.
923938
///
924939
/// Default value: `false`
@@ -936,6 +951,7 @@ impl Default for UserConfig {
936951
manually_accept_inbound_channels: false,
937952
accept_intercept_htlcs: false,
938953
manually_handle_bolt12_invoices: false,
954+
notify_bolt12_invoice_sent: false,
939955
enable_dual_funded_channels: false,
940956
}
941957
}
@@ -956,6 +972,7 @@ impl Readable for UserConfig {
956972
manually_accept_inbound_channels: Readable::read(reader)?,
957973
accept_intercept_htlcs: Readable::read(reader)?,
958974
manually_handle_bolt12_invoices: Readable::read(reader)?,
975+
notify_bolt12_invoice_sent: Readable::read(reader)?,
959976
enable_dual_funded_channels: Readable::read(reader)?,
960977
})
961978
}

0 commit comments

Comments
 (0)