Skip to content

Commit 14634c6

Browse files
committed
Add nonce to OffersContext::OutboundPayment
To authenticate that a Bolt12Invoice is for a valid InvoiceRequest or Refund, include the nonce from the payer_metadata in the InvoiceRequest reply path or Refund::paths, respectively. This can be used to prevent de-anonymization attacks where an attacker sends invoices using self-constructed paths to nodes near the blinded paths' introduction nodes.
1 parent 868fee7 commit 14634c6

File tree

2 files changed

+16
-6
lines changed

2 files changed

+16
-6
lines changed

lightning/src/blinded_path/message.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,15 @@ pub enum OffersContext {
142142
///
143143
/// [`Refund`]: crate::offers::refund::Refund
144144
/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
145-
payment_id: PaymentId
145+
payment_id: PaymentId,
146+
147+
/// A nonce used for authenticating that a [`Bolt12Invoice`] is for a valid [`Refund`] or
148+
/// [`InvoiceRequest`] and for deriving their signing keys.
149+
///
150+
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
151+
/// [`Refund`]: crate::offers::refund::Refund
152+
/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
153+
nonce: Nonce,
146154
},
147155
}
148156

@@ -158,6 +166,7 @@ impl_writeable_tlv_based_enum!(OffersContext,
158166
},
159167
(2, OutboundPayment) => {
160168
(0, payment_id, required),
169+
(1, nonce, required),
161170
},
162171
);
163172

lightning/src/ln/channelmanager.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8862,7 +8862,7 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
88628862
let secp_ctx = &$self.secp_ctx;
88638863

88648864
let nonce = Nonce::from_entropy_source(entropy);
8865-
let context = OffersContext::OutboundPayment { payment_id };
8865+
let context = OffersContext::OutboundPayment { payment_id, nonce };
88668866
let path = $self.create_blinded_paths_using_absolute_expiry(context, Some(absolute_expiry))
88678867
.and_then(|paths| paths.into_iter().next().ok_or(()))
88688868
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
@@ -8997,8 +8997,9 @@ where
89978997
};
89988998
let invoice_request = builder.build_and_sign()?;
89998999

9000-
let context = OffersContext::OutboundPayment { payment_id };
9001-
let reply_paths = self.create_blinded_paths(context).map_err(|_| Bolt12SemanticError::MissingPaths)?;
9000+
let context = OffersContext::OutboundPayment { payment_id, nonce };
9001+
let reply_paths = self.create_blinded_paths(context)
9002+
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
90029003

90039004
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
90049005

@@ -10697,7 +10698,7 @@ where
1069710698

1069810699
let abandon_if_payment = |context| {
1069910700
match context {
10700-
OffersContext::OutboundPayment { payment_id } => self.abandon_payment(payment_id),
10701+
OffersContext::OutboundPayment { payment_id, .. } => self.abandon_payment(payment_id),
1070110702
_ => {},
1070210703
}
1070310704
};
@@ -10808,7 +10809,7 @@ where
1080810809
OffersMessage::Invoice(invoice) => {
1080910810
let expected_payment_id = match context {
1081010811
OffersContext::Unknown {} if invoice.is_for_refund_without_paths() => None,
10811-
OffersContext::OutboundPayment { payment_id } => Some(payment_id),
10812+
OffersContext::OutboundPayment { payment_id, .. } => Some(payment_id),
1081210813
_ => return ResponseInstruction::NoResponse,
1081310814
};
1081410815

0 commit comments

Comments
 (0)