Skip to content

Commit ee2f11c

Browse files
events: add InvoiceSent event for BOLT12 payee symmetry
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 ee2f11c

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)