Skip to content

Commit ec538d1

Browse files
Update send_onion_message API to take new OnionMessageContents enum
OnionMessageContents specifies the data TLV that the sender wants in the onion message. This enum only has one variant for now, Custom. When offers are added, additional variants for invoice, invoice_request, and invoice_error will be added. This commit does not actually implement sending the custom OM contents, just the API change.
1 parent 87b637c commit ec538d1

File tree

4 files changed

+62
-28
lines changed

4 files changed

+62
-28
lines changed

lightning/src/onion_message/functional_tests.rs

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
use chain::keysinterface::{KeysInterface, Recipient};
1313
use ln::features::InitFeatures;
1414
use ln::msgs::{self, DecodeError, OnionMessageHandler};
15-
use super::{BlindedRoute, CustomOnionMessageContents, CustomOnionMessageHandler, Destination, OnionMessenger, SendError};
15+
use super::{BlindedRoute, CustomOnionMessageContents, CustomOnionMessageHandler, Destination, OnionMessageContents, OnionMessenger, SendError};
1616
use util::enforcing_trait_impls::EnforcingSigner;
1717
use util::ser::{MaybeReadableArgs, Writeable, Writer};
1818
use util::test_utils;
@@ -119,80 +119,87 @@ fn pass_along_path(path: &Vec<MessengerNode>, expected_path_id: Option<[u8; 32]>
119119
#[test]
120120
fn one_hop() {
121121
let nodes = create_nodes(2);
122+
let test_msg = OnionMessageContents::Custom(TestCustomMessage {});
122123

123-
nodes[0].messenger.send_onion_message(&[], Destination::Node(nodes[1].get_node_pk()), None).unwrap();
124+
nodes[0].messenger.send_onion_message(&[], Destination::Node(nodes[1].get_node_pk()), test_msg, None).unwrap();
124125
pass_along_path(&nodes, None);
125126
}
126127

127128
#[test]
128129
fn two_unblinded_hops() {
129130
let nodes = create_nodes(3);
131+
let test_msg = OnionMessageContents::Custom(TestCustomMessage {});
130132

131-
nodes[0].messenger.send_onion_message(&[nodes[1].get_node_pk()], Destination::Node(nodes[2].get_node_pk()), None).unwrap();
133+
nodes[0].messenger.send_onion_message(&[nodes[1].get_node_pk()], Destination::Node(nodes[2].get_node_pk()), test_msg, None).unwrap();
132134
pass_along_path(&nodes, None);
133135
}
134136

135137
#[test]
136138
fn two_unblinded_two_blinded() {
137139
let nodes = create_nodes(5);
140+
let test_msg = OnionMessageContents::Custom(TestCustomMessage {});
138141

139142
let secp_ctx = Secp256k1::new();
140143
let blinded_route = BlindedRoute::new(&[nodes[3].get_node_pk(), nodes[4].get_node_pk()], &*nodes[4].keys_manager, &secp_ctx).unwrap();
141144

142-
nodes[0].messenger.send_onion_message(&[nodes[1].get_node_pk(), nodes[2].get_node_pk()], Destination::BlindedRoute(blinded_route), None).unwrap();
145+
nodes[0].messenger.send_onion_message(&[nodes[1].get_node_pk(), nodes[2].get_node_pk()], Destination::BlindedRoute(blinded_route), test_msg, None).unwrap();
143146
pass_along_path(&nodes, None);
144147
}
145148

146149
#[test]
147150
fn three_blinded_hops() {
148151
let nodes = create_nodes(4);
152+
let test_msg = OnionMessageContents::Custom(TestCustomMessage {});
149153

150154
let secp_ctx = Secp256k1::new();
151155
let blinded_route = BlindedRoute::new(&[nodes[1].get_node_pk(), nodes[2].get_node_pk(), nodes[3].get_node_pk()], &*nodes[3].keys_manager, &secp_ctx).unwrap();
152156

153-
nodes[0].messenger.send_onion_message(&[], Destination::BlindedRoute(blinded_route), None).unwrap();
157+
nodes[0].messenger.send_onion_message(&[], Destination::BlindedRoute(blinded_route), test_msg, None).unwrap();
154158
pass_along_path(&nodes, None);
155159
}
156160

157161
#[test]
158162
fn too_big_packet_error() {
159163
// Make sure we error as expected if a packet is too big to send.
160164
let nodes = create_nodes(2);
165+
let test_msg = OnionMessageContents::Custom(TestCustomMessage {});
161166

162167
let hop_node_id = nodes[1].get_node_pk();
163168
let hops = [hop_node_id; 400];
164-
let err = nodes[0].messenger.send_onion_message(&hops, Destination::Node(hop_node_id), None).unwrap_err();
169+
let err = nodes[0].messenger.send_onion_message(&hops, Destination::Node(hop_node_id), test_msg, None).unwrap_err();
165170
assert_eq!(err, SendError::TooBigPacket);
166171
}
167172

168173
#[test]
169174
fn invalid_blinded_route_error() {
170175
// Make sure we error as expected if a provided blinded route has 0 or 1 hops.
171176
let nodes = create_nodes(3);
177+
let test_msg = TestCustomMessage {};
172178

173179
// 0 hops
174180
let secp_ctx = Secp256k1::new();
175181
let mut blinded_route = BlindedRoute::new(&[nodes[1].get_node_pk(), nodes[2].get_node_pk()], &*nodes[2].keys_manager, &secp_ctx).unwrap();
176182
blinded_route.blinded_hops.clear();
177-
let err = nodes[0].messenger.send_onion_message(&[], Destination::BlindedRoute(blinded_route), None).unwrap_err();
183+
let err = nodes[0].messenger.send_onion_message(&[], Destination::BlindedRoute(blinded_route), OnionMessageContents::Custom(test_msg.clone()), None).unwrap_err();
178184
assert_eq!(err, SendError::TooFewBlindedHops);
179185

180186
// 1 hop
181187
let mut blinded_route = BlindedRoute::new(&[nodes[1].get_node_pk(), nodes[2].get_node_pk()], &*nodes[2].keys_manager, &secp_ctx).unwrap();
182188
blinded_route.blinded_hops.remove(0);
183189
assert_eq!(blinded_route.blinded_hops.len(), 1);
184-
let err = nodes[0].messenger.send_onion_message(&[], Destination::BlindedRoute(blinded_route), None).unwrap_err();
190+
let err = nodes[0].messenger.send_onion_message(&[], Destination::BlindedRoute(blinded_route), OnionMessageContents::Custom(test_msg), None).unwrap_err();
185191
assert_eq!(err, SendError::TooFewBlindedHops);
186192
}
187193

188194
#[test]
189195
fn reply_path() {
190196
let nodes = create_nodes(4);
197+
let test_msg = TestCustomMessage {};
191198
let secp_ctx = Secp256k1::new();
192199

193200
// Destination::Node
194201
let reply_path = BlindedRoute::new(&[nodes[2].get_node_pk(), nodes[1].get_node_pk(), nodes[0].get_node_pk()], &*nodes[0].keys_manager, &secp_ctx).unwrap();
195-
nodes[0].messenger.send_onion_message(&[nodes[1].get_node_pk(), nodes[2].get_node_pk()], Destination::Node(nodes[3].get_node_pk()), Some(reply_path)).unwrap();
202+
nodes[0].messenger.send_onion_message(&[nodes[1].get_node_pk(), nodes[2].get_node_pk()], Destination::Node(nodes[3].get_node_pk()), OnionMessageContents::Custom(test_msg.clone()), Some(reply_path)).unwrap();
196203
pass_along_path(&nodes, None);
197204
// Make sure the last node successfully decoded the reply path.
198205
nodes[3].logger.assert_log_contains(
@@ -203,7 +210,7 @@ fn reply_path() {
203210
let blinded_route = BlindedRoute::new(&[nodes[1].get_node_pk(), nodes[2].get_node_pk(), nodes[3].get_node_pk()], &*nodes[3].keys_manager, &secp_ctx).unwrap();
204211
let reply_path = BlindedRoute::new(&[nodes[2].get_node_pk(), nodes[1].get_node_pk(), nodes[0].get_node_pk()], &*nodes[0].keys_manager, &secp_ctx).unwrap();
205212

206-
nodes[0].messenger.send_onion_message(&[], Destination::BlindedRoute(blinded_route), Some(reply_path)).unwrap();
213+
nodes[0].messenger.send_onion_message(&[], Destination::BlindedRoute(blinded_route), OnionMessageContents::Custom(test_msg), Some(reply_path)).unwrap();
207214
pass_along_path(&nodes, None);
208215
nodes[3].logger.assert_log_contains(
209216
"lightning::onion_message::messenger".to_string(),
@@ -213,9 +220,10 @@ fn reply_path() {
213220
#[test]
214221
fn peer_buffer_full() {
215222
let nodes = create_nodes(2);
223+
let test_msg = TestCustomMessage {};
216224
for _ in 0..188 { // Based on MAX_PER_PEER_BUFFER_SIZE in OnionMessenger
217-
nodes[0].messenger.send_onion_message(&[], Destination::Node(nodes[1].get_node_pk()), None).unwrap();
225+
nodes[0].messenger.send_onion_message(&[], Destination::Node(nodes[1].get_node_pk()), OnionMessageContents::Custom(test_msg.clone()), None).unwrap();
218226
}
219-
let err = nodes[0].messenger.send_onion_message(&[], Destination::Node(nodes[1].get_node_pk()), None).unwrap_err();
227+
let err = nodes[0].messenger.send_onion_message(&[], Destination::Node(nodes[1].get_node_pk()), OnionMessageContents::Custom(test_msg), None).unwrap_err();
220228
assert_eq!(err, SendError::BufferFull);
221229
}

lightning/src/onion_message/messenger.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use ln::msgs::{self, OnionMessageHandler};
2121
use ln::onion_utils;
2222
use ln::peer_handler::IgnoringMessageHandler;
2323
use super::blinded_route::{BlindedRoute, ForwardTlvs, ReceiveTlvs};
24-
pub use super::packet::CustomOnionMessageContents;
24+
pub use super::packet::{CustomOnionMessageContents, OnionMessageContents};
2525
use super::packet::{BIG_PACKET_HOP_DATA_LEN, ForwardControlTlvs, Packet, Payload, ReceiveControlTlvs, SMALL_PACKET_HOP_DATA_LEN};
2626
use super::utils;
2727
use util::events::OnionMessageProvider;
@@ -34,7 +34,7 @@ use prelude::*;
3434

3535
/// A sender, receiver and forwarder of onion messages. In upcoming releases, this object will be
3636
/// used to retrieve invoices and fulfill invoice requests from [offers]. Currently, only sending
37-
/// and receiving empty onion messages is supported.
37+
/// and receiving custom onion messages is supported.
3838
///
3939
/// # Example
4040
///
@@ -45,7 +45,7 @@ use prelude::*;
4545
/// # use lightning::chain::keysinterface::{InMemorySigner, KeysManager, KeysInterface};
4646
/// # use lightning::ln::msgs::DecodeError;
4747
/// # use lightning::ln::peer_handler::IgnoringMessageHandler;
48-
/// # use lightning::onion_message::{BlindedRoute, CustomOnionMessageContents, Destination, OnionMessenger};
48+
/// # use lightning::onion_message::{BlindedRoute, CustomOnionMessageContents, Destination, OnionMessageContents, OnionMessenger};
4949
/// # use lightning::util::logger::{Logger, Record};
5050
/// # use lightning::util::ser::{MaybeReadableArgs, Writeable, Writer};
5151
/// # use lightning::io;
@@ -88,19 +88,24 @@ use prelude::*;
8888
/// // if the message type is unknown
8989
/// }
9090
/// }
91+
/// // Send a custom onion message to a node id.
9192
/// let intermediate_hops = [hop_node_id1, hop_node_id2];
9293
/// let reply_path = None;
93-
/// onion_messenger.send_onion_message(&intermediate_hops, Destination::Node(destination_node_id), reply_path);
94+
/// # let your_custom_message = YourCustomMessage {};
95+
/// let message = OnionMessageContents::Custom(your_custom_message);
96+
/// onion_messenger.send_onion_message(&intermediate_hops, Destination::Node(destination_node_id), message, reply_path);
9497
///
9598
/// // Create a blinded route to yourself, for someone to send an onion message to.
9699
/// # let your_node_id = hop_node_id1;
97100
/// let hops = [hop_node_id3, hop_node_id4, your_node_id];
98101
/// let blinded_route = BlindedRoute::new(&hops, &keys_manager, &secp_ctx).unwrap();
99102
///
100-
/// // Send an empty onion message to a blinded route.
103+
/// // Send a custom onion message to a blinded route.
101104
/// # let intermediate_hops = [hop_node_id1, hop_node_id2];
102105
/// let reply_path = None;
103-
/// onion_messenger.send_onion_message(&intermediate_hops, Destination::BlindedRoute(blinded_route), reply_path);
106+
/// # let your_custom_message = YourCustomMessage {};
107+
/// let message = OnionMessageContents::Custom(your_custom_message);
108+
/// onion_messenger.send_onion_message(&intermediate_hops, Destination::BlindedRoute(blinded_route), message, reply_path);
104109
/// ```
105110
///
106111
/// [offers]: <https://github.com/lightning/bolts/pull/798>
@@ -192,9 +197,9 @@ impl<Signer: Sign, K: Deref, L: Deref, CMH: Deref> OnionMessenger<Signer, K, L,
192197
}
193198
}
194199

195-
/// Send an empty onion message to `destination`, routing it through `intermediate_nodes`.
200+
/// Send an onion message with contents `message` to `destination`, routing it through `intermediate_nodes`.
196201
/// See [`OnionMessenger`] for example usage.
197-
pub fn send_onion_message(&self, intermediate_nodes: &[PublicKey], destination: Destination, reply_path: Option<BlindedRoute>) -> Result<(), SendError> {
202+
pub fn send_onion_message<T: CustomOnionMessageContents>(&self, intermediate_nodes: &[PublicKey], destination: Destination, message: OnionMessageContents<T>, reply_path: Option<BlindedRoute>) -> Result<(), SendError> {
198203
if let Destination::BlindedRoute(BlindedRoute { ref blinded_hops, .. }) = destination {
199204
if blinded_hops.len() < 2 {
200205
return Err(SendError::TooFewBlindedHops);

lightning/src/onion_message/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,5 @@ mod functional_tests;
2929

3030
// Re-export structs so they can be imported with just the `onion_message::` module prefix.
3131
pub use self::blinded_route::{BlindedRoute, BlindedHop};
32-
pub use self::messenger::{CustomOnionMessageContents, CustomOnionMessageHandler, Destination, OnionMessenger, SendError, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
32+
pub use self::messenger::{CustomOnionMessageContents, CustomOnionMessageHandler, Destination, OnionMessageContents, OnionMessenger, SendError, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
3333
pub(crate) use self::packet::Packet;

lightning/src/onion_message/packet.rs

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -104,13 +104,34 @@ pub(super) enum Payload {
104104
}
105105
}
106106

107-
// Coming soon:
108-
// enum Message {
109-
// InvoiceRequest(InvoiceRequest),
110-
// Invoice(Invoice),
111-
// InvoiceError(InvoiceError),
112-
// CustomMessage<T>,
113-
// }
107+
#[derive(Debug)]
108+
/// The contents of an onion message. In the context of offers, this would be the invoice, invoice
109+
/// request, or invoice error.
110+
pub enum OnionMessageContents<T> where T: CustomOnionMessageContents {
111+
// Coming soon:
112+
// Invoice,
113+
// InvoiceRequest,
114+
// InvoiceError,
115+
/// A custom onion message specified by the user.
116+
Custom(T),
117+
}
118+
119+
impl<T> OnionMessageContents<T> where T: CustomOnionMessageContents {
120+
/// Returns the type that was used to decode the message payload.
121+
pub fn tlv_type(&self) -> u64 {
122+
match self {
123+
&OnionMessageContents::Custom(ref msg) => msg.tlv_type(),
124+
}
125+
}
126+
}
127+
128+
impl<T: CustomOnionMessageContents> Writeable for OnionMessageContents<T> {
129+
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
130+
match self {
131+
OnionMessageContents::Custom(msg) => Ok(msg.write(w)?),
132+
}
133+
}
134+
}
114135

115136
/// The contents of a custom onion message. Must implement `MaybeReadableArgs<u64>` where the `u64`
116137
/// is the custom TLV type attempting to be read, and return `Ok(None)` if the TLV type is unknown.

0 commit comments

Comments
 (0)