Skip to content

Commit 75fd0f3

Browse files
Parameterize OnionMessenger by new CustomOnionMessageHandler trait
OnionMessenger::new will now take a custom onion message handler trait implementation. This handler will be used in upcoming commit(s) to handle inbound custom onion messages. The new trait also specifies what custom messages are supported via its associated type, CustomMessage. This associated type must implement a new CustomOnionMessagesContents trait, which requires custom messages to support being written, being read, and supplying their TLV type.
1 parent 2a8179e commit 75fd0f3

File tree

6 files changed

+168
-24
lines changed

6 files changed

+168
-24
lines changed

fuzz/src/onion_message.rs

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ use lightning::ln::msgs::{self, DecodeError, OnionMessageHandler};
1010
use lightning::ln::script::ShutdownScript;
1111
use lightning::util::enforcing_trait_impls::EnforcingSigner;
1212
use lightning::util::logger::Logger;
13-
use lightning::util::ser::{Readable, Writer};
14-
use lightning::onion_message::OnionMessenger;
13+
use lightning::util::ser::{MaybeReadableArgs, Readable, Writeable, Writer};
14+
use lightning::onion_message::{CustomOnionMessageContents, CustomOnionMessageHandler, OnionMessenger};
1515

1616
use utils::test_logger;
1717

18-
use std::io::Cursor;
18+
use std::io::{self, Cursor};
1919
use std::sync::atomic::{AtomicU64, Ordering};
2020

2121
#[inline]
@@ -29,7 +29,8 @@ pub fn do_test<L: Logger>(data: &[u8], logger: &L) {
2929
node_secret: secret,
3030
counter: AtomicU64::new(0),
3131
};
32-
let onion_messenger = OnionMessenger::new(&keys_manager, logger);
32+
let custom_msg_handler = TestCustomMessageHandler {};
33+
let onion_messenger = OnionMessenger::new(&keys_manager, logger, &custom_msg_handler);
3334
let mut pk = [2; 33]; pk[1] = 0xff;
3435
let peer_node_id_not_used = PublicKey::from_slice(&pk).unwrap();
3536
onion_messenger.handle_onion_message(&peer_node_id_not_used, &msg);
@@ -49,6 +50,38 @@ pub extern "C" fn onion_message_run(data: *const u8, datalen: usize) {
4950
do_test(unsafe { std::slice::from_raw_parts(data, datalen) }, &logger);
5051
}
5152

53+
struct TestCustomMessage {}
54+
55+
const CUSTOM_MESSAGE_TYPE: u64 = 4242;
56+
const CUSTOM_MESSAGE_CONTENTS: [u8; 32] = [42; 32];
57+
58+
impl CustomOnionMessageContents for TestCustomMessage {
59+
fn tlv_type(&self) -> u64 {
60+
CUSTOM_MESSAGE_TYPE
61+
}
62+
}
63+
64+
impl Writeable for TestCustomMessage {
65+
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
66+
Ok(CUSTOM_MESSAGE_CONTENTS.write(w)?)
67+
}
68+
}
69+
70+
impl MaybeReadableArgs<u64> for TestCustomMessage {
71+
fn read<R: io::Read>(buffer: &mut R, _message_type: u64,) -> Result<Option<Self>, DecodeError> where Self: Sized {
72+
let mut buf = Vec::new();
73+
buffer.read_to_end(&mut buf)?;
74+
return Ok(Some(TestCustomMessage {}))
75+
}
76+
}
77+
78+
struct TestCustomMessageHandler {}
79+
80+
impl CustomOnionMessageHandler for TestCustomMessageHandler {
81+
type CustomMessage = TestCustomMessage;
82+
fn handle_custom_message(&self, _msg: Self::CustomMessage) {}
83+
}
84+
5285
pub struct VecWriter(pub Vec<u8>);
5386
impl Writer for VecWriter {
5487
fn write_all(&mut self, buf: &[u8]) -> Result<(), ::std::io::Error> {

lightning/src/ln/peer_handler.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ use ln::features::{InitFeatures, NodeFeatures};
2121
use ln::msgs;
2222
use ln::msgs::{ChannelMessageHandler, LightningError, NetAddress, OnionMessageHandler, RoutingMessageHandler};
2323
use ln::channelmanager::{SimpleArcChannelManager, SimpleRefChannelManager};
24-
use util::ser::{VecWriter, Writeable, Writer};
24+
use util::ser::{MaybeReadableArgs, VecWriter, Writeable, Writer};
2525
use ln::peer_channel_encryptor::{PeerChannelEncryptor,NextNoiseStep};
2626
use ln::wire;
2727
use ln::wire::Encode;
28-
use onion_message::{SimpleArcOnionMessenger, SimpleRefOnionMessenger};
28+
use onion_message::{CustomOnionMessageContents, CustomOnionMessageHandler, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
2929
use routing::gossip::{NetworkGraph, P2PGossipSync};
3030
use util::atomic_counter::AtomicCounter;
3131
use util::crypto::sign;
@@ -95,6 +95,23 @@ impl OnionMessageHandler for IgnoringMessageHandler {
9595
InitFeatures::empty()
9696
}
9797
}
98+
impl CustomOnionMessageHandler for IgnoringMessageHandler {
99+
type CustomMessage = Infallible;
100+
fn handle_custom_message(&self, _msg: Self::CustomMessage) {
101+
// Since we always return `None` in the read the handle method should never be called.
102+
unreachable!();
103+
}
104+
}
105+
impl MaybeReadableArgs<u64> for Infallible {
106+
fn read<R: io::Read>(_buffer: &mut R, _msg_type: u64) -> Result<Option<Self>, msgs::DecodeError> where Self: Sized {
107+
Ok(None)
108+
}
109+
}
110+
111+
impl CustomOnionMessageContents for Infallible {
112+
fn tlv_type(&self) -> u64 { unreachable!(); }
113+
}
114+
98115
impl Deref for IgnoringMessageHandler {
99116
type Target = IgnoringMessageHandler;
100117
fn deref(&self) -> &Self { self }

lightning/src/onion_message/functional_tests.rs

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,21 @@
1111
1212
use chain::keysinterface::{KeysInterface, Recipient};
1313
use ln::features::InitFeatures;
14-
use ln::msgs::{self, OnionMessageHandler};
15-
use super::{BlindedRoute, Destination, OnionMessenger, SendError};
14+
use ln::msgs::{self, DecodeError, OnionMessageHandler};
15+
use super::{BlindedRoute, CustomOnionMessageContents, CustomOnionMessageHandler, Destination, OnionMessenger, SendError};
1616
use util::enforcing_trait_impls::EnforcingSigner;
17+
use util::ser::{MaybeReadableArgs, Writeable, Writer};
1718
use util::test_utils;
1819

1920
use bitcoin::network::constants::Network;
2021
use bitcoin::secp256k1::{PublicKey, Secp256k1};
2122

23+
use io;
2224
use sync::Arc;
2325

2426
struct MessengerNode {
2527
keys_manager: Arc<test_utils::TestKeysInterface>,
26-
messenger: OnionMessenger<EnforcingSigner, Arc<test_utils::TestKeysInterface>, Arc<test_utils::TestLogger>>,
28+
messenger: OnionMessenger<EnforcingSigner, Arc<test_utils::TestKeysInterface>, Arc<test_utils::TestLogger>, Arc<TestCustomMessageHandler>>,
2729
logger: Arc<test_utils::TestLogger>,
2830
}
2931

@@ -34,6 +36,43 @@ impl MessengerNode {
3436
}
3537
}
3638

39+
#[derive(Clone)]
40+
struct TestCustomMessage {}
41+
42+
const CUSTOM_MESSAGE_TYPE: u64 = 4242;
43+
const CUSTOM_MESSAGE_CONTENTS: [u8; 32] = [42; 32];
44+
45+
impl CustomOnionMessageContents for TestCustomMessage {
46+
fn tlv_type(&self) -> u64 {
47+
CUSTOM_MESSAGE_TYPE
48+
}
49+
}
50+
51+
impl Writeable for TestCustomMessage {
52+
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
53+
Ok(CUSTOM_MESSAGE_CONTENTS.write(w)?)
54+
}
55+
}
56+
57+
impl MaybeReadableArgs<u64> for TestCustomMessage {
58+
fn read<R: io::Read>(buffer: &mut R, message_type: u64) -> Result<Option<Self>, DecodeError> where Self: Sized {
59+
if message_type == CUSTOM_MESSAGE_TYPE {
60+
let mut buf = Vec::new();
61+
buffer.read_to_end(&mut buf)?;
62+
assert_eq!(buf, CUSTOM_MESSAGE_CONTENTS);
63+
return Ok(Some(TestCustomMessage {}))
64+
}
65+
Ok(None)
66+
}
67+
}
68+
69+
struct TestCustomMessageHandler {}
70+
71+
impl CustomOnionMessageHandler for TestCustomMessageHandler {
72+
type CustomMessage = TestCustomMessage;
73+
fn handle_custom_message(&self, _msg: Self::CustomMessage) {}
74+
}
75+
3776
fn create_nodes(num_messengers: u8) -> Vec<MessengerNode> {
3877
let mut nodes = Vec::new();
3978
for i in 0..num_messengers {
@@ -42,7 +81,7 @@ fn create_nodes(num_messengers: u8) -> Vec<MessengerNode> {
4281
let keys_manager = Arc::new(test_utils::TestKeysInterface::new(&seed, Network::Testnet));
4382
nodes.push(MessengerNode {
4483
keys_manager: keys_manager.clone(),
45-
messenger: OnionMessenger::new(keys_manager, logger.clone()),
84+
messenger: OnionMessenger::new(keys_manager, logger.clone(), Arc::new(TestCustomMessageHandler {})),
4685
logger,
4786
});
4887
}

lightning/src/onion_message/messenger.rs

Lines changed: 60 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ use chain::keysinterface::{InMemorySigner, KeysInterface, KeysManager, Recipient
1919
use ln::features::{InitFeatures, NodeFeatures};
2020
use ln::msgs::{self, OnionMessageHandler};
2121
use ln::onion_utils;
22+
use ln::peer_handler::IgnoringMessageHandler;
2223
use super::blinded_route::{BlindedRoute, ForwardTlvs, ReceiveTlvs};
24+
pub use super::packet::CustomOnionMessageContents;
2325
use super::packet::{BIG_PACKET_HOP_DATA_LEN, ForwardControlTlvs, Packet, Payload, ReceiveControlTlvs, SMALL_PACKET_HOP_DATA_LEN};
2426
use super::utils;
2527
use util::events::OnionMessageProvider;
@@ -41,8 +43,12 @@ use prelude::*;
4143
/// # use bitcoin::hashes::_export::_core::time::Duration;
4244
/// # use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
4345
/// # use lightning::chain::keysinterface::{InMemorySigner, KeysManager, KeysInterface};
44-
/// # use lightning::onion_message::{BlindedRoute, Destination, OnionMessenger};
46+
/// # use lightning::ln::msgs::DecodeError;
47+
/// # use lightning::ln::peer_handler::IgnoringMessageHandler;
48+
/// # use lightning::onion_message::{BlindedRoute, CustomOnionMessageContents, Destination, OnionMessenger};
4549
/// # use lightning::util::logger::{Logger, Record};
50+
/// # use lightning::util::ser::{MaybeReadableArgs, Writeable, Writer};
51+
/// # use lightning::io;
4652
/// # use std::sync::Arc;
4753
/// # struct FakeLogger {};
4854
/// # impl Logger for FakeLogger {
@@ -58,12 +64,31 @@ use prelude::*;
5864
/// # let (hop_node_id2, hop_node_id3, hop_node_id4) = (hop_node_id1, hop_node_id1,
5965
/// hop_node_id1);
6066
/// # let destination_node_id = hop_node_id1;
61-
/// #
67+
/// # let your_custom_message_handler = IgnoringMessageHandler {};
6268
/// // Create the onion messenger. This must use the same `keys_manager` as is passed to your
6369
/// // ChannelManager.
64-
/// let onion_messenger = OnionMessenger::new(&keys_manager, logger);
70+
/// let onion_messenger = OnionMessenger::new(&keys_manager, logger, your_custom_message_handler);
6571
///
66-
/// // Send an empty onion message to a node id.
72+
/// # struct YourCustomMessage {}
73+
/// impl Writeable for YourCustomMessage {
74+
/// fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
75+
/// # Ok(())
76+
/// // Write your custom onion message to `w`
77+
/// }
78+
/// }
79+
/// impl CustomOnionMessageContents for YourCustomMessage {
80+
/// fn tlv_type(&self) -> u64 {
81+
/// # let your_custom_message_type = 42;
82+
/// your_custom_message_type
83+
/// }
84+
/// }
85+
/// impl MaybeReadableArgs<u64> for YourCustomMessage {
86+
/// fn read<R: io::Read>(r: &mut R, message_type: u64) -> Result<Option<Self>, DecodeError> {
87+
/// # unreachable!()
88+
/// // Read your custom onion message of type `message_type` from `r`, or return `None`
89+
/// // if the message type is unknown
90+
/// }
91+
/// }
6792
/// let intermediate_hops = [hop_node_id1, hop_node_id2];
6893
/// let reply_path = None;
6994
/// onion_messenger.send_onion_message(&intermediate_hops, Destination::Node(destination_node_id), reply_path);
@@ -81,17 +106,18 @@ use prelude::*;
81106
///
82107
/// [offers]: <https://github.com/lightning/bolts/pull/798>
83108
/// [`OnionMessenger`]: crate::onion_message::OnionMessenger
84-
pub struct OnionMessenger<Signer: Sign, K: Deref, L: Deref>
109+
pub struct OnionMessenger<Signer: Sign, K: Deref, L: Deref, CMH: Deref>
85110
where K::Target: KeysInterface<Signer = Signer>,
86111
L::Target: Logger,
112+
CMH:: Target: CustomOnionMessageHandler,
87113
{
88114
keys_manager: K,
89115
logger: L,
90116
pending_messages: Mutex<HashMap<PublicKey, VecDeque<msgs::OnionMessage>>>,
91117
secp_ctx: Secp256k1<secp256k1::All>,
118+
custom_handler: CMH,
92119
// Coming soon:
93120
// invoice_handler: InvoiceHandler,
94-
// custom_handler: CustomHandler, // handles custom onion messages
95121
}
96122

97123
/// The destination of an onion message.
@@ -130,20 +156,40 @@ pub enum SendError {
130156
BufferFull,
131157
}
132158

133-
impl<Signer: Sign, K: Deref, L: Deref> OnionMessenger<Signer, K, L>
159+
/// Handler for custom onion messages. If you are using [`SimpleArcOnionMessenger`],
160+
/// [`SimpleRefOnionMessenger`], or prefer to ignore inbound custom onion messages,
161+
/// [`IgnoringMessageHandler`] must be provided to [`OnionMessenger::new`]. Otherwise, a custom
162+
/// implementation of this trait must be provided, with [`CustomMessage`] specifying the supported
163+
/// message types.
164+
///
165+
/// See [`OnionMessenger`] for example usage.
166+
///
167+
/// [`IgnoringMessageHandler`]: crate::ln::peer_handler::IgnoringMessageHandler
168+
/// [`CustomMessage`]: Self::CustomMessage
169+
pub trait CustomOnionMessageHandler {
170+
/// The message known to the handler. To support multiple message types, you may want to make this
171+
/// an enum with a variant for each supported message.
172+
type CustomMessage: CustomOnionMessageContents;
173+
/// Called with the custom message that was received.
174+
fn handle_custom_message(&self, msg: Self::CustomMessage);
175+
}
176+
177+
impl<Signer: Sign, K: Deref, L: Deref, CMH: Deref> OnionMessenger<Signer, K, L, CMH>
134178
where K::Target: KeysInterface<Signer = Signer>,
135179
L::Target: Logger,
180+
CMH::Target: CustomOnionMessageHandler,
136181
{
137182
/// Constructs a new `OnionMessenger` to send, forward, and delegate received onion messages to
138183
/// their respective handlers.
139-
pub fn new(keys_manager: K, logger: L) -> Self {
184+
pub fn new(keys_manager: K, logger: L, custom_handler: CMH) -> Self {
140185
let mut secp_ctx = Secp256k1::new();
141186
secp_ctx.seeded_randomize(&keys_manager.get_secure_random_bytes());
142187
OnionMessenger {
143188
keys_manager,
144189
pending_messages: Mutex::new(HashMap::new()),
145190
secp_ctx,
146191
logger,
192+
custom_handler,
147193
}
148194
}
149195

@@ -221,9 +267,10 @@ fn outbound_buffer_full(peer_node_id: &PublicKey, buffer: &HashMap<PublicKey, Ve
221267
false
222268
}
223269

224-
impl<Signer: Sign, K: Deref, L: Deref> OnionMessageHandler for OnionMessenger<Signer, K, L>
270+
impl<Signer: Sign, K: Deref, L: Deref, CMH: Deref> OnionMessageHandler for OnionMessenger<Signer, K, L, CMH>
225271
where K::Target: KeysInterface<Signer = Signer>,
226272
L::Target: Logger,
273+
CMH::Target: CustomOnionMessageHandler,
227274
{
228275
/// Handle an incoming onion message. Currently, if a message was destined for us we will log, but
229276
/// soon we'll delegate the onion message to a handler that can generate invoices or send
@@ -361,9 +408,10 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessageHandler for OnionMessenger<Si
361408
}
362409
}
363410

364-
impl<Signer: Sign, K: Deref, L: Deref> OnionMessageProvider for OnionMessenger<Signer, K, L>
411+
impl<Signer: Sign, K: Deref, L: Deref, CMH: Deref> OnionMessageProvider for OnionMessenger<Signer, K, L, CMH>
365412
where K::Target: KeysInterface<Signer = Signer>,
366413
L::Target: Logger,
414+
CMH::Target: CustomOnionMessageHandler,
367415
{
368416
fn next_onion_message_for_peer(&self, peer_node_id: PublicKey) -> Option<msgs::OnionMessage> {
369417
let mut pending_msgs = self.pending_messages.lock().unwrap();
@@ -383,15 +431,15 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessageProvider for OnionMessenger<S
383431
///
384432
/// [`SimpleArcChannelManager`]: crate::ln::channelmanager::SimpleArcChannelManager
385433
/// [`SimpleArcPeerManager`]: crate::ln::peer_handler::SimpleArcPeerManager
386-
pub type SimpleArcOnionMessenger<L> = OnionMessenger<InMemorySigner, Arc<KeysManager>, Arc<L>>;
434+
pub type SimpleArcOnionMessenger<L> = OnionMessenger<InMemorySigner, Arc<KeysManager>, Arc<L>, IgnoringMessageHandler>;
387435
/// Useful for simplifying the parameters of [`SimpleRefChannelManager`] and
388436
/// [`SimpleRefPeerManager`]. See their docs for more details.
389437
///
390438
/// (C-not exported) as general type aliases don't make sense in bindings.
391439
///
392440
/// [`SimpleRefChannelManager`]: crate::ln::channelmanager::SimpleRefChannelManager
393441
/// [`SimpleRefPeerManager`]: crate::ln::peer_handler::SimpleRefPeerManager
394-
pub type SimpleRefOnionMessenger<'a, 'b, L> = OnionMessenger<InMemorySigner, &'a KeysManager, &'b L>;
442+
pub type SimpleRefOnionMessenger<'a, 'b, L> = OnionMessenger<InMemorySigner, &'a KeysManager, &'b L, IgnoringMessageHandler>;
395443

396444
/// Construct onion packet payloads and keys for sending an onion message along the given
397445
/// `unblinded_path` to the given `destination`.

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::{Destination, OnionMessenger, SendError, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
32+
pub use self::messenger::{CustomOnionMessageContents, CustomOnionMessageHandler, Destination, OnionMessenger, SendError, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
3333
pub(crate) use self::packet::Packet;

lightning/src/onion_message/packet.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use ln::msgs::DecodeError;
1616
use ln::onion_utils;
1717
use super::blinded_route::{BlindedRoute, ForwardTlvs, ReceiveTlvs};
1818
use util::chacha20poly1305rfc::{ChaChaPolyReadAdapter, ChaChaPolyWriteAdapter};
19-
use util::ser::{BigSize, FixedLengthReader, LengthRead, LengthReadable, LengthReadableArgs, Readable, ReadableArgs, Writeable, Writer};
19+
use util::ser::{BigSize, FixedLengthReader, LengthRead, LengthReadable, LengthReadableArgs, MaybeReadableArgs, Readable, ReadableArgs, Writeable, Writer};
2020

2121
use core::cmp;
2222
use io::{self, Read};
@@ -112,6 +112,13 @@ pub(super) enum Payload {
112112
// CustomMessage<T>,
113113
// }
114114

115+
/// The contents of a custom onion message. Must implement `MaybeReadableArgs<u64>` where the `u64`
116+
/// is the custom TLV type attempting to be read, and return `Ok(None)` if the TLV type is unknown.
117+
pub trait CustomOnionMessageContents: Writeable + MaybeReadableArgs<u64> {
118+
/// Returns the TLV type identifying the message contents. MUST be >= 64.
119+
fn tlv_type(&self) -> u64;
120+
}
121+
115122
/// Forward control TLVs in their blinded and unblinded form.
116123
pub(super) enum ForwardControlTlvs {
117124
/// If we're sending to a blinded route, the node that constructed the blinded route has provided

0 commit comments

Comments
 (0)