Skip to content

Commit 902c56a

Browse files
committed
WIP: Authenticate invoice requests
1 parent f7db553 commit 902c56a

File tree

5 files changed

+28
-12
lines changed

5 files changed

+28
-12
lines changed

lightning/src/ln/channelmanager.rs

+20-6
Original file line numberDiff line numberDiff line change
@@ -10257,7 +10257,7 @@ where
1025710257
R::Target: Router,
1025810258
L::Target: Logger,
1025910259
{
10260-
fn handle_message(&self, message: OffersMessage, responder: Option<Responder>) -> ResponseInstruction<OffersMessage> {
10260+
fn handle_message(&self, message: OffersMessage, context: OffersContext, responder: Option<Responder>) -> ResponseInstruction<OffersMessage> {
1026110261
let secp_ctx = &self.secp_ctx;
1026210262
let expanded_key = &self.inbound_payment_key;
1026310263

@@ -10267,17 +10267,31 @@ where
1026710267
Some(responder) => responder,
1026810268
None => return ResponseInstruction::NoResponse,
1026910269
};
10270+
10271+
let nonce = match context {
10272+
OffersContext::Unknown {} if invoice_request.metadata().is_some() => None,
10273+
OffersContext::InvoiceRequest { nonce } => Some(nonce),
10274+
_ => return ResponseInstruction::NoResponse,
10275+
};
10276+
1027010277
let amount_msats = match InvoiceBuilder::<DerivedSigningPubkey>::amount_msats(
1027110278
&invoice_request
1027210279
) {
1027310280
Ok(amount_msats) => amount_msats,
1027410281
Err(error) => return responder.respond(OffersMessage::InvoiceError(error.into())),
1027510282
};
10276-
let invoice_request = match invoice_request.verify(expanded_key, secp_ctx) {
10277-
Ok(invoice_request) => invoice_request,
10278-
Err(()) => {
10279-
let error = Bolt12SemanticError::InvalidMetadata;
10280-
return responder.respond(OffersMessage::InvoiceError(error.into()));
10283+
10284+
let invoice_request = match nonce {
10285+
Some(nonce) => match invoice_request.verify_using_nonce(nonce, expanded_key, secp_ctx) {
10286+
Ok(invoice_request) => invoice_request,
10287+
Err(()) => return ResponseInstruction::NoResponse,
10288+
},
10289+
None => match invoice_request.verify(expanded_key, secp_ctx) {
10290+
Ok(invoice_request) => invoice_request,
10291+
Err(()) => {
10292+
let error = Bolt12SemanticError::InvalidMetadata;
10293+
return responder.respond(OffersMessage::InvoiceError(error.into()));
10294+
},
1028110295
},
1028210296
};
1028310297

lightning/src/ln/peer_handler.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use bitcoin::blockdata::constants::ChainHash;
1919
use bitcoin::secp256k1::{self, Secp256k1, SecretKey, PublicKey};
2020

2121
use crate::sign::{NodeSigner, Recipient};
22+
use crate::blinded_path::message::OffersContext;
2223
use crate::events::{MessageSendEvent, MessageSendEventsProvider};
2324
use crate::ln::types::ChannelId;
2425
use crate::ln::features::{InitFeatures, NodeFeatures};
@@ -145,7 +146,7 @@ impl OnionMessageHandler for IgnoringMessageHandler {
145146
}
146147

147148
impl OffersMessageHandler for IgnoringMessageHandler {
148-
fn handle_message(&self, _message: OffersMessage, _responder: Option<Responder>) -> ResponseInstruction<OffersMessage> {
149+
fn handle_message(&self, _message: OffersMessage, _context: OffersContext, _responder: Option<Responder>) -> ResponseInstruction<OffersMessage> {
149150
ResponseInstruction::NoResponse
150151
}
151152
}

lightning/src/onion_message/functional_tests.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
//! Onion message testing and test utilities live here.
1111
1212
use crate::blinded_path::{BlindedPath, EmptyNodeIdLookUp};
13-
use crate::blinded_path::message::ForwardNode;
13+
use crate::blinded_path::message::{ForwardNode, OffersContext};
1414
use crate::events::{Event, EventsProvider};
1515
use crate::ln::features::{ChannelFeatures, InitFeatures};
1616
use crate::ln::msgs::{self, DecodeError, OnionMessageHandler};
@@ -76,7 +76,7 @@ impl Drop for MessengerNode {
7676
struct TestOffersMessageHandler {}
7777

7878
impl OffersMessageHandler for TestOffersMessageHandler {
79-
fn handle_message(&self, _message: OffersMessage, _responder: Option<Responder>) -> ResponseInstruction<OffersMessage> {
79+
fn handle_message(&self, _message: OffersMessage, _context: OffersContext, _responder: Option<Responder>) -> ResponseInstruction<OffersMessage> {
8080
ResponseInstruction::NoResponse
8181
}
8282
}

lightning/src/onion_message/messenger.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use bitcoin::hashes::sha256::Hash as Sha256;
1616
use bitcoin::secp256k1::{self, PublicKey, Scalar, Secp256k1, SecretKey};
1717

1818
use crate::blinded_path::{BlindedPath, IntroductionNode, NextMessageHop, NodeIdLookUp};
19-
use crate::blinded_path::message::{advance_path_by_one, ForwardNode, ForwardTlvs, ReceiveTlvs};
19+
use crate::blinded_path::message::{advance_path_by_one, ForwardNode, ForwardTlvs, OffersContext, ReceiveTlvs};
2020
use crate::blinded_path::utils;
2121
use crate::events::{Event, EventHandler, EventsProvider};
2222
use crate::sign::{EntropySource, NodeSigner, Recipient};
@@ -1451,7 +1451,7 @@ where
14511451
);
14521452
match message {
14531453
ParsedOnionMessageContents::Offers(msg) => {
1454-
let response_instructions = self.offers_handler.handle_message(msg, responder);
1454+
let response_instructions = self.offers_handler.handle_message(msg, OffersContext::Unknown {}, responder);
14551455
let _ = self.handle_onion_message_response(response_instructions);
14561456
},
14571457
#[cfg(async_payments)]

lightning/src/onion_message/offers.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
//! Message handling for BOLT 12 Offers.
1111
1212
use core::fmt;
13+
use crate::blinded_path::message::OffersContext;
1314
use crate::io::{self, Read};
1415
use crate::ln::msgs::DecodeError;
1516
use crate::offers::invoice_error::InvoiceError;
@@ -44,7 +45,7 @@ pub trait OffersMessageHandler {
4445
/// The returned [`OffersMessage`], if any, is enqueued to be sent by [`OnionMessenger`].
4546
///
4647
/// [`OnionMessenger`]: crate::onion_message::messenger::OnionMessenger
47-
fn handle_message(&self, message: OffersMessage, responder: Option<Responder>) -> ResponseInstruction<OffersMessage>;
48+
fn handle_message(&self, message: OffersMessage, context: OffersContext, responder: Option<Responder>) -> ResponseInstruction<OffersMessage>;
4849

4950
/// Releases any [`OffersMessage`]s that need to be sent.
5051
///

0 commit comments

Comments
 (0)