Skip to content

Commit 9782aec

Browse files
committed
Remove message type bound on ResponseInstruction
Our onion message handlers generally have one or more methods which return a `ResponseInstruction` parameterized with the expected message type (enum) of the message handler. Sadly, that restriction is impossible to represent in our bindings - our bindings concretize all LDK structs, enums, and traits into a single concrete instance with generics set to our concrete trait instances (which hold a jump table). This prevents us from having multiple instances of `ResponseInstruction` structs for different message types. Our bindings do, however, support different parameterizations of standard enums, including `Option`s and tuples. In order to support bindings for the onion message handlers, we are thus forced into std types bound by expected message types, which we do here by making `ResponseInstruction` contain only the instructions and generally using it as a two-tuple of `(message, ResponseInstruction)`.
1 parent bbfa15e commit 9782aec

File tree

6 files changed

+80
-56
lines changed

6 files changed

+80
-56
lines changed

lightning/src/ln/channelmanager.rs

+13-13
Original file line numberDiff line numberDiff line change
@@ -10749,33 +10749,33 @@ where
1074910749
{
1075010750
fn handle_message(
1075110751
&self, message: OffersMessage, context: Option<OffersContext>, responder: Option<Responder>,
10752-
) -> ResponseInstruction<OffersMessage> {
10752+
) -> Option<(OffersMessage, ResponseInstruction)> {
1075310753
let secp_ctx = &self.secp_ctx;
1075410754
let expanded_key = &self.inbound_payment_key;
1075510755

1075610756
match message {
1075710757
OffersMessage::InvoiceRequest(invoice_request) => {
1075810758
let responder = match responder {
1075910759
Some(responder) => responder,
10760-
None => return ResponseInstruction::NoResponse,
10760+
None => return None,
1076110761
};
1076210762

1076310763
let nonce = match context {
1076410764
None if invoice_request.metadata().is_some() => None,
1076510765
Some(OffersContext::InvoiceRequest { nonce }) => Some(nonce),
10766-
_ => return ResponseInstruction::NoResponse,
10766+
_ => return None,
1076710767
};
1076810768

1076910769
let invoice_request = match nonce {
1077010770
Some(nonce) => match invoice_request.verify_using_recipient_data(
1077110771
nonce, expanded_key, secp_ctx,
1077210772
) {
1077310773
Ok(invoice_request) => invoice_request,
10774-
Err(()) => return ResponseInstruction::NoResponse,
10774+
Err(()) => return None,
1077510775
},
1077610776
None => match invoice_request.verify_using_metadata(expanded_key, secp_ctx) {
1077710777
Ok(invoice_request) => invoice_request,
10778-
Err(()) => return ResponseInstruction::NoResponse,
10778+
Err(()) => return None,
1077910779
},
1078010780
};
1078110781

@@ -10859,7 +10859,7 @@ where
1085910859
OffersMessage::Invoice(invoice) => {
1086010860
let payment_id = match self.verify_bolt12_invoice(&invoice, context.as_ref()) {
1086110861
Ok(payment_id) => payment_id,
10862-
Err(()) => return ResponseInstruction::NoResponse,
10862+
Err(()) => return None,
1086310863
};
1086410864

1086510865
let logger = WithContext::from(
@@ -10871,7 +10871,7 @@ where
1087110871
payment_id, invoice, context, responder,
1087210872
};
1087310873
self.pending_events.lock().unwrap().push_back((event, None));
10874-
return ResponseInstruction::NoResponse;
10874+
return None;
1087510875
}
1087610876

1087710877
let error = match self.send_payment_for_verified_bolt12_invoice(
@@ -10890,14 +10890,14 @@ where
1089010890
},
1089110891
Err(Bolt12PaymentError::UnexpectedInvoice)
1089210892
| Err(Bolt12PaymentError::DuplicateInvoice)
10893-
| Ok(()) => return ResponseInstruction::NoResponse,
10893+
| Ok(()) => return None,
1089410894
};
1089510895

1089610896
match responder {
1089710897
Some(responder) => responder.respond(OffersMessage::InvoiceError(error)),
1089810898
None => {
1089910899
log_trace!(logger, "No reply path to send error: {:?}", error);
10900-
ResponseInstruction::NoResponse
10900+
None
1090110901
},
1090210902
}
1090310903
},
@@ -10909,7 +10909,7 @@ where
1090910909
InvoiceError::from_string("Static invoices not yet supported".to_string())
1091010910
))
1091110911
},
10912-
None => return ResponseInstruction::NoResponse,
10912+
None => return None,
1091310913
}
1091410914
},
1091510915
OffersMessage::InvoiceError(invoice_error) => {
@@ -10932,7 +10932,7 @@ where
1093210932
_ => {},
1093310933
}
1093410934

10935-
ResponseInstruction::NoResponse
10935+
None
1093610936
},
1093710937
}
1093810938
}
@@ -10956,8 +10956,8 @@ where
1095610956
{
1095710957
fn held_htlc_available(
1095810958
&self, _message: HeldHtlcAvailable, _responder: Option<Responder>
10959-
) -> ResponseInstruction<ReleaseHeldHtlc> {
10960-
ResponseInstruction::NoResponse
10959+
) -> Option<(ReleaseHeldHtlc, ResponseInstruction)> {
10960+
None
1096110961
}
1096210962

1096310963
fn release_held_htlc(&self, _message: ReleaseHeldHtlc) {}

lightning/src/ln/peer_handler.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -144,21 +144,21 @@ impl OnionMessageHandler for IgnoringMessageHandler {
144144
}
145145

146146
impl OffersMessageHandler for IgnoringMessageHandler {
147-
fn handle_message(&self, _message: OffersMessage, _context: Option<OffersContext>, _responder: Option<Responder>) -> ResponseInstruction<OffersMessage> {
148-
ResponseInstruction::NoResponse
147+
fn handle_message(&self, _message: OffersMessage, _context: Option<OffersContext>, _responder: Option<Responder>) -> Option<(OffersMessage, ResponseInstruction)> {
148+
None
149149
}
150150
}
151151
impl AsyncPaymentsMessageHandler for IgnoringMessageHandler {
152152
fn held_htlc_available(
153153
&self, _message: HeldHtlcAvailable, _responder: Option<Responder>,
154-
) -> ResponseInstruction<ReleaseHeldHtlc> {
155-
ResponseInstruction::NoResponse
154+
) -> Option<(ReleaseHeldHtlc, ResponseInstruction)> {
155+
None
156156
}
157157
fn release_held_htlc(&self, _message: ReleaseHeldHtlc) {}
158158
}
159159
impl CustomOnionMessageHandler for IgnoringMessageHandler {
160160
type CustomMessage = Infallible;
161-
fn handle_custom_message(&self, _message: Self::CustomMessage, _context: Option<Vec<u8>>, _responder: Option<Responder>) -> ResponseInstruction<Self::CustomMessage> {
161+
fn handle_custom_message(&self, _message: Self::CustomMessage, _context: Option<Vec<u8>>, _responder: Option<Responder>) -> Option<(Infallible, ResponseInstruction)> {
162162
// Since we always return `None` in the read the handle method should never be called.
163163
unreachable!();
164164
}

lightning/src/onion_message/async_payments.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pub trait AsyncPaymentsMessageHandler {
3030
/// the held funds.
3131
fn held_htlc_available(
3232
&self, message: HeldHtlcAvailable, responder: Option<Responder>,
33-
) -> ResponseInstruction<ReleaseHeldHtlc>;
33+
) -> Option<(ReleaseHeldHtlc, ResponseInstruction)>;
3434

3535
/// Handle a [`ReleaseHeldHtlc`] message. If authentication of the message succeeds, an HTLC
3636
/// should be released to the corresponding payee.

lightning/src/onion_message/functional_tests.rs

+12-9
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ impl Drop for MessengerNode {
7676
struct TestOffersMessageHandler {}
7777

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

@@ -86,8 +86,8 @@ struct TestAsyncPaymentsMessageHandler {}
8686
impl AsyncPaymentsMessageHandler for TestAsyncPaymentsMessageHandler {
8787
fn held_htlc_available(
8888
&self, _message: HeldHtlcAvailable, _responder: Option<Responder>,
89-
) -> ResponseInstruction<ReleaseHeldHtlc> {
90-
ResponseInstruction::NoResponse
89+
) -> Option<(ReleaseHeldHtlc, ResponseInstruction)> {
90+
None
9191
}
9292
fn release_held_htlc(&self, _message: ReleaseHeldHtlc) {}
9393
}
@@ -174,7 +174,7 @@ impl Drop for TestCustomMessageHandler {
174174

175175
impl CustomOnionMessageHandler for TestCustomMessageHandler {
176176
type CustomMessage = TestCustomMessage;
177-
fn handle_custom_message(&self, msg: Self::CustomMessage, context: Option<Vec<u8>>, responder: Option<Responder>) -> ResponseInstruction<Self::CustomMessage> {
177+
fn handle_custom_message(&self, msg: Self::CustomMessage, context: Option<Vec<u8>>, responder: Option<Responder>) -> Option<(Self::CustomMessage, ResponseInstruction)> {
178178
let expectation = self.get_next_expectation();
179179
assert_eq!(msg, expectation.expect);
180180

@@ -193,7 +193,7 @@ impl CustomOnionMessageHandler for TestCustomMessageHandler {
193193
responder.respond_with_reply_path(response, MessageContext::Custom(context.unwrap_or_else(Vec::new)))
194194
},
195195
Some(responder) => responder.respond(response),
196-
None => ResponseInstruction::NoResponse,
196+
None => None
197197
}
198198
}
199199
fn read_custom_message<R: io::Read>(&self, message_type: u64, buffer: &mut R) -> Result<Option<Self::CustomMessage>, DecodeError> where Self: Sized {
@@ -444,8 +444,9 @@ fn async_response_over_one_blinded_hop() {
444444
let response_instruction = nodes[0].custom_message_handler.handle_custom_message(message, None, responder);
445445

446446
// 6. Simulate Alice asynchronously responding back to Bob with a response.
447+
let (msg, instructions) = response_instruction.unwrap();
447448
assert_eq!(
448-
nodes[0].messenger.handle_onion_message_response(response_instruction),
449+
nodes[0].messenger.handle_onion_message_response(msg, instructions),
449450
Ok(Some(SendSuccess::Buffered)),
450451
);
451452

@@ -477,8 +478,9 @@ fn async_response_with_reply_path_succeeds() {
477478
alice.custom_message_handler.expect_message_and_response(message.clone());
478479
let response_instruction = alice.custom_message_handler.handle_custom_message(message, None, Some(responder));
479480

481+
let (msg, instructions) = response_instruction.unwrap();
480482
assert_eq!(
481-
alice.messenger.handle_onion_message_response(response_instruction),
483+
alice.messenger.handle_onion_message_response(msg, instructions),
482484
Ok(Some(SendSuccess::Buffered)),
483485
);
484486

@@ -516,8 +518,9 @@ fn async_response_with_reply_path_fails() {
516518
alice.custom_message_handler.expect_message_and_response(message.clone());
517519
let response_instruction = alice.custom_message_handler.handle_custom_message(message, None, Some(responder));
518520

521+
let (msg, instructions) = response_instruction.unwrap();
519522
assert_eq!(
520-
alice.messenger.handle_onion_message_response(response_instruction),
523+
alice.messenger.handle_onion_message_response(msg, instructions),
521524
Err(SendError::PathNotFound),
522525
);
523526
}

lightning/src/onion_message/messenger.rs

+48-27
Original file line numberDiff line numberDiff line change
@@ -365,30 +365,24 @@ impl Responder {
365365
/// Creates a [`ResponseInstruction::WithoutReplyPath`] for a given response.
366366
///
367367
/// Use when the recipient doesn't need to send back a reply to us.
368-
pub fn respond<T: OnionMessageContents>(self, response: T) -> ResponseInstruction<T> {
369-
ResponseInstruction::WithoutReplyPath(OnionMessageResponse {
370-
message: response,
371-
reply_path: self.reply_path,
372-
})
368+
pub fn respond<T: OnionMessageContents>(self, response: T) -> Option<(T, ResponseInstruction)> {
369+
Some((response, ResponseInstruction::WithoutReplyPath {
370+
send_path: self.reply_path,
371+
}))
373372
}
374373

375374
/// Creates a [`ResponseInstruction::WithReplyPath`] for a given response.
376375
///
377376
/// Use when the recipient needs to send back a reply to us.
378-
pub fn respond_with_reply_path<T: OnionMessageContents>(self, response: T, context: MessageContext) -> ResponseInstruction<T> {
379-
ResponseInstruction::WithReplyPath(OnionMessageResponse {
380-
message: response,
381-
reply_path: self.reply_path,
382-
}, context)
377+
pub fn respond_with_reply_path<T: OnionMessageContents>(self, response: T, context: MessageContext) -> Option<(T, ResponseInstruction)> {
378+
Some((response, ResponseInstruction::WithReplyPath {
379+
send_path: self.reply_path,
380+
context: context,
381+
}))
383382
}
384383
}
385384

386-
/// This struct contains the information needed to reply to a received message.
387-
pub struct OnionMessageResponse<T: OnionMessageContents> {
388-
message: T,
389-
reply_path: BlindedMessagePath,
390-
}
391-
385+
/*#[cfg(not(c_bindings))]
392386
/// `ResponseInstruction` represents instructions for responding to received messages.
393387
pub enum ResponseInstruction<T: OnionMessageContents> {
394388
/// Indicates that a response should be sent including a reply path for
@@ -401,6 +395,26 @@ pub enum ResponseInstruction<T: OnionMessageContents> {
401395
NoResponse,
402396
}
403397
398+
#[cfg(c_bindings)]*/
399+
/// `ResponseInstruction` represents instructions for responding to received messages.
400+
pub enum ResponseInstruction {
401+
/// Indicates that a response should be sent including a reply path for
402+
/// the recipient to respond back.
403+
WithReplyPath {
404+
/// The path over which we'll send our reply.
405+
send_path: BlindedMessagePath,
406+
/// The context to include in the reply path we'll give the recipient so they can respond
407+
/// to us.
408+
context: MessageContext,
409+
},
410+
/// Indicates that a response should be sent without including a reply path
411+
/// for the recipient to respond back.
412+
WithoutReplyPath {
413+
/// The path over which we'll send our reply.
414+
send_path: BlindedMessagePath,
415+
}
416+
}
417+
404418
/// An [`OnionMessage`] for [`OnionMessenger`] to send.
405419
///
406420
/// These are obtained when released from [`OnionMessenger`]'s handlers after which they are
@@ -799,7 +813,9 @@ pub trait CustomOnionMessageHandler {
799813
/// Called with the custom message that was received, returning a response to send, if any.
800814
///
801815
/// The returned [`Self::CustomMessage`], if any, is enqueued to be sent by [`OnionMessenger`].
802-
fn handle_custom_message(&self, message: Self::CustomMessage, context: Option<Vec<u8>>, responder: Option<Responder>) -> ResponseInstruction<Self::CustomMessage>;
816+
fn handle_custom_message(
817+
&self, message: Self::CustomMessage, context: Option<Vec<u8>>, responder: Option<Responder>
818+
) -> Option<(Self::CustomMessage, ResponseInstruction)>;
803819

804820
/// Read a custom message of type `message_type` from `buffer`, returning `Ok(None)` if the
805821
/// message type is unknown.
@@ -1320,15 +1336,14 @@ where
13201336
/// the response is prepared and ready for sending, that task can invoke this method to enqueue
13211337
/// the response for delivery.
13221338
pub fn handle_onion_message_response<T: OnionMessageContents>(
1323-
&self, response: ResponseInstruction<T>
1339+
&self, response_message: T, response: ResponseInstruction,
13241340
) -> Result<Option<SendSuccess>, SendError> {
1325-
let (response, context) = match response {
1326-
ResponseInstruction::WithReplyPath(response, context) => (response, Some(context)),
1327-
ResponseInstruction::WithoutReplyPath(response) => (response, None),
1328-
ResponseInstruction::NoResponse => return Ok(None),
1341+
let (response_path, context) = match response {
1342+
ResponseInstruction::WithReplyPath { send_path, context } => (send_path, Some(context)),
1343+
ResponseInstruction::WithoutReplyPath { send_path } => (send_path, None),
13291344
};
13301345

1331-
let message_type = response.message.msg_type();
1346+
let message_type = response_message.msg_type();
13321347
let reply_path = if let Some(context) = context {
13331348
match self.create_blinded_path(context) {
13341349
Ok(reply_path) => Some(reply_path),
@@ -1344,7 +1359,7 @@ where
13441359
} else { None };
13451360

13461361
self.find_path_and_enqueue_onion_message(
1347-
response.message, Destination::BlindedPath(response.reply_path), reply_path,
1362+
response_message, Destination::BlindedPath(response_path), reply_path,
13481363
format_args!(
13491364
"when responding with {} to an onion message",
13501365
message_type,
@@ -1564,14 +1579,18 @@ where
15641579
}
15651580
};
15661581
let response_instructions = self.offers_handler.handle_message(msg, context, responder);
1567-
let _ = self.handle_onion_message_response(response_instructions);
1582+
if let Some((msg, instructions)) = response_instructions {
1583+
let _ = self.handle_onion_message_response(msg, instructions);
1584+
}
15681585
},
15691586
#[cfg(async_payments)]
15701587
ParsedOnionMessageContents::AsyncPayments(AsyncPaymentsMessage::HeldHtlcAvailable(msg)) => {
15711588
let response_instructions = self.async_payments_handler.held_htlc_available(
15721589
msg, responder
15731590
);
1574-
let _ = self.handle_onion_message_response(response_instructions);
1591+
if let Some((msg, instructions)) = response_instructions {
1592+
let _ = self.handle_onion_message_response(msg, instructions);
1593+
}
15751594
},
15761595
#[cfg(async_payments)]
15771596
ParsedOnionMessageContents::AsyncPayments(AsyncPaymentsMessage::ReleaseHeldHtlc(msg)) => {
@@ -1587,7 +1606,9 @@ where
15871606
}
15881607
};
15891608
let response_instructions = self.custom_handler.handle_custom_message(msg, context, responder);
1590-
let _ = self.handle_onion_message_response(response_instructions);
1609+
if let Some((msg, instructions)) = response_instructions {
1610+
let _ = self.handle_onion_message_response(msg, instructions);
1611+
}
15911612
},
15921613
}
15931614
},

lightning/src/onion_message/offers.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pub trait OffersMessageHandler {
4747
/// [`OnionMessenger`]: crate::onion_message::messenger::OnionMessenger
4848
fn handle_message(
4949
&self, message: OffersMessage, context: Option<OffersContext>, responder: Option<Responder>,
50-
) -> ResponseInstruction<OffersMessage>;
50+
) -> Option<(OffersMessage, ResponseInstruction)>;
5151

5252
/// Releases any [`OffersMessage`]s that need to be sent.
5353
///

0 commit comments

Comments
 (0)