lightning_custom_message/lib.rs
1//! Utilities for supporting custom peer-to-peer messages in LDK.
2//!
3//! [BOLT 1] specifies a custom message type range for use with experimental or application-specific
4//! messages. While a [`CustomMessageHandler`] can be defined to support more than one message type,
5//! defining such a handler requires a significant amount of boilerplate and can be error prone.
6//!
7//! This crate provides the [`composite_custom_message_handler`] macro for easily composing
8//! pre-defined custom message handlers into one handler. The resulting handler can be further
9//! composed with other custom message handlers using the same macro.
10//!
11//! The following example demonstrates defining a `FooBarHandler` to compose separate handlers for
12//! `Foo` and `Bar` messages, and further composing it with a handler for `Baz` messages.
13//!
14//!```
15//! # fn main() {} // Avoid #[macro_export] generating an in-function warning
16//! # extern crate bitcoin;
17//! extern crate lightning;
18//! #[macro_use]
19//! extern crate lightning_custom_message;
20//!
21//! # use bitcoin::secp256k1::PublicKey;
22//! # use lightning::io;
23//! # use lightning::ln::msgs::{DecodeError, Init, LightningError};
24//! use lightning::ln::peer_handler::CustomMessageHandler;
25//! use lightning::ln::wire::{CustomMessageReader, self};
26//! # use lightning::types::features::{InitFeatures, NodeFeatures};
27//! use lightning::util::ser::Writeable;
28//! # use lightning::util::ser::Writer;
29//!
30//! // Assume that `FooHandler` and `BarHandler` are defined in one crate and `BazHandler` is
31//! // defined in another crate, handling messages `Foo`, `Bar`, and `Baz`, respectively.
32//!
33//! #[derive(Debug)]
34//! pub struct Foo;
35//!
36//! macro_rules! foo_type_id {
37//! () => { 32768 }
38//! }
39//!
40//! impl wire::Type for Foo {
41//! fn type_id(&self) -> u16 { foo_type_id!() }
42//! }
43//! impl Writeable for Foo {
44//! // ...
45//! # fn write<W: Writer>(&self, _: &mut W) -> Result<(), io::Error> {
46//! # unimplemented!()
47//! # }
48//! }
49//!
50//! pub struct FooHandler;
51//!
52//! impl CustomMessageReader for FooHandler {
53//! // ...
54//! # type CustomMessage = Foo;
55//! # fn read<R: io::Read>(
56//! # &self, _message_type: u16, _buffer: &mut R
57//! # ) -> Result<Option<Self::CustomMessage>, DecodeError> {
58//! # unimplemented!()
59//! # }
60//! }
61//! impl CustomMessageHandler for FooHandler {
62//! // ...
63//! # fn handle_custom_message(
64//! # &self, _msg: Self::CustomMessage, _sender_node_id: PublicKey
65//! # ) -> Result<(), LightningError> {
66//! # unimplemented!()
67//! # }
68//! # fn get_and_clear_pending_msg(&self) -> Vec<(PublicKey, Self::CustomMessage)> {
69//! # unimplemented!()
70//! # }
71//! # fn peer_disconnected(&self, _their_node_id: PublicKey) {
72//! # unimplemented!()
73//! # }
74//! # fn peer_connected(&self, _their_node_id: PublicKey, _msg: &Init, _inbound: bool) -> Result<(), ()> {
75//! # unimplemented!()
76//! # }
77//! # fn provided_node_features(&self) -> NodeFeatures {
78//! # unimplemented!()
79//! # }
80//! # fn provided_init_features(&self, _their_node_id: PublicKey) -> InitFeatures {
81//! # unimplemented!()
82//! # }
83//! }
84//!
85//! #[derive(Debug)]
86//! pub struct Bar;
87//!
88//! macro_rules! bar_type_id {
89//! () => { 32769 }
90//! }
91//!
92//! impl wire::Type for Bar {
93//! fn type_id(&self) -> u16 { bar_type_id!() }
94//! }
95//! impl Writeable for Bar {
96//! // ...
97//! # fn write<W: Writer>(&self, _: &mut W) -> Result<(), io::Error> {
98//! # unimplemented!()
99//! # }
100//! }
101//!
102//! pub struct BarHandler;
103//!
104//! impl CustomMessageReader for BarHandler {
105//! // ...
106//! # type CustomMessage = Bar;
107//! # fn read<R: io::Read>(
108//! # &self, _message_type: u16, _buffer: &mut R
109//! # ) -> Result<Option<Self::CustomMessage>, DecodeError> {
110//! # unimplemented!()
111//! # }
112//! }
113//! impl CustomMessageHandler for BarHandler {
114//! // ...
115//! # fn handle_custom_message(
116//! # &self, _msg: Self::CustomMessage, _sender_node_id: PublicKey
117//! # ) -> Result<(), LightningError> {
118//! # unimplemented!()
119//! # }
120//! # fn get_and_clear_pending_msg(&self) -> Vec<(PublicKey, Self::CustomMessage)> {
121//! # unimplemented!()
122//! # }
123//! # fn peer_disconnected(&self, _their_node_id: PublicKey) {
124//! # unimplemented!()
125//! # }
126//! # fn peer_connected(&self, _their_node_id: PublicKey, _msg: &Init, _inbound: bool) -> Result<(), ()> {
127//! # unimplemented!()
128//! # }
129//! # fn provided_node_features(&self) -> NodeFeatures {
130//! # unimplemented!()
131//! # }
132//! # fn provided_init_features(&self, _their_node_id: PublicKey) -> InitFeatures {
133//! # unimplemented!()
134//! # }
135//! }
136//!
137//! #[derive(Debug)]
138//! pub struct Baz;
139//!
140//! macro_rules! baz_type_id {
141//! () => { 32770 }
142//! }
143//!
144//! impl wire::Type for Baz {
145//! fn type_id(&self) -> u16 { baz_type_id!() }
146//! }
147//! impl Writeable for Baz {
148//! // ...
149//! # fn write<W: Writer>(&self, _: &mut W) -> Result<(), io::Error> {
150//! # unimplemented!()
151//! # }
152//! }
153//!
154//! pub struct BazHandler;
155//!
156//! impl CustomMessageReader for BazHandler {
157//! // ...
158//! # type CustomMessage = Baz;
159//! # fn read<R: io::Read>(
160//! # &self, _message_type: u16, _buffer: &mut R
161//! # ) -> Result<Option<Self::CustomMessage>, DecodeError> {
162//! # unimplemented!()
163//! # }
164//! }
165//! impl CustomMessageHandler for BazHandler {
166//! // ...
167//! # fn handle_custom_message(
168//! # &self, _msg: Self::CustomMessage, _sender_node_id: PublicKey
169//! # ) -> Result<(), LightningError> {
170//! # unimplemented!()
171//! # }
172//! # fn get_and_clear_pending_msg(&self) -> Vec<(PublicKey, Self::CustomMessage)> {
173//! # unimplemented!()
174//! # }
175//! # fn peer_disconnected(&self, _their_node_id: PublicKey) {
176//! # unimplemented!()
177//! # }
178//! # fn peer_connected(&self, _their_node_id: PublicKey, _msg: &Init, _inbound: bool) -> Result<(), ()> {
179//! # unimplemented!()
180//! # }
181//! # fn provided_node_features(&self) -> NodeFeatures {
182//! # unimplemented!()
183//! # }
184//! # fn provided_init_features(&self, _their_node_id: PublicKey) -> InitFeatures {
185//! # unimplemented!()
186//! # }
187//! }
188//!
189//! // The first crate may define a handler composing `FooHandler` and `BarHandler` and export the
190//! // corresponding message type ids as a macro to use in further composition.
191//!
192//! composite_custom_message_handler!(
193//! pub struct FooBarHandler {
194//! foo: FooHandler,
195//! bar: BarHandler,
196//! }
197//!
198//! pub enum FooBarMessage {
199//! Foo(foo_type_id!()),
200//! Bar(bar_type_id!()),
201//! }
202//! );
203//!
204//! #[macro_export]
205//! macro_rules! foo_bar_type_ids {
206//! () => { foo_type_id!() | bar_type_id!() }
207//! }
208//!
209//! // Another crate can then define a handler further composing `FooBarHandler` with `BazHandler`
210//! // and similarly export the composition of message type ids as a macro.
211//!
212//! composite_custom_message_handler!(
213//! pub struct FooBarBazHandler {
214//! foo_bar: FooBarHandler,
215//! baz: BazHandler,
216//! }
217//!
218//! pub enum FooBarBazMessage {
219//! FooBar(foo_bar_type_ids!()),
220//! Baz(baz_type_id!()),
221//! }
222//! );
223//!
224//! #[macro_export]
225//! macro_rules! foo_bar_baz_type_ids {
226//! () => { foo_bar_type_ids!() | baz_type_id!() }
227//! }
228//!```
229//!
230//! [BOLT 1]: https://github.com/lightning/bolts/blob/master/01-messaging.md
231//! [`CustomMessageHandler`]: crate::lightning::ln::peer_handler::CustomMessageHandler
232
233#![doc(test(no_crate_inject, attr(deny(warnings))))]
234
235pub extern crate bitcoin;
236pub extern crate lightning;
237
238/// Defines a composite type implementing [`CustomMessageHandler`] (and therefore also implementing
239/// [`CustomMessageReader`]), along with a corresponding enumerated custom message [`Type`], from
240/// one or more previously defined custom message handlers.
241///
242/// Useful for parameterizing [`PeerManager`] with custom message handling for one or more sets of
243/// custom messages. Message type ids may be given as a valid `match` pattern, including ranges,
244/// though using OR-ed literal patterns is preferred in order to catch unreachable code for
245/// conflicting handlers.
246///
247/// See [crate documentation] for example usage.
248///
249/// [`CustomMessageHandler`]: crate::lightning::ln::peer_handler::CustomMessageHandler
250/// [`CustomMessageReader`]: crate::lightning::ln::wire::CustomMessageReader
251/// [`Type`]: crate::lightning::ln::wire::Type
252/// [`PeerManager`]: crate::lightning::ln::peer_handler::PeerManager
253/// [crate documentation]: self
254#[macro_export]
255macro_rules! composite_custom_message_handler {
256 (
257 $handler_visibility:vis struct $handler:ident {
258 $($field_visibility:vis $field:ident: $type:ty),* $(,)*
259 }
260
261 $message_visibility:vis enum $message:ident {
262 $($variant:ident($pattern:pat)),* $(,)*
263 }
264 ) => {
265 #[allow(missing_docs)]
266 $handler_visibility struct $handler {
267 $(
268 $field_visibility $field: $type,
269 )*
270 }
271
272 #[allow(missing_docs)]
273 #[derive(Debug)]
274 $message_visibility enum $message {
275 $(
276 $variant(<$type as $crate::lightning::ln::wire::CustomMessageReader>::CustomMessage),
277 )*
278 }
279
280 impl $crate::lightning::ln::peer_handler::CustomMessageHandler for $handler {
281 fn handle_custom_message(
282 &self, msg: Self::CustomMessage, sender_node_id: $crate::bitcoin::secp256k1::PublicKey
283 ) -> Result<(), $crate::lightning::ln::msgs::LightningError> {
284 match msg {
285 $(
286 $message::$variant(message) => {
287 $crate::lightning::ln::peer_handler::CustomMessageHandler::handle_custom_message(
288 &self.$field, message, sender_node_id
289 )
290 },
291 )*
292 }
293 }
294
295 fn get_and_clear_pending_msg(&self) -> Vec<($crate::bitcoin::secp256k1::PublicKey, Self::CustomMessage)> {
296 vec![].into_iter()
297 $(
298 .chain(
299 self.$field
300 .get_and_clear_pending_msg()
301 .into_iter()
302 .map(|(pubkey, message)| (pubkey, $message::$variant(message)))
303 )
304 )*
305 .collect()
306 }
307
308 fn peer_disconnected(&self, their_node_id: $crate::bitcoin::secp256k1::PublicKey) {
309 $(
310 self.$field.peer_disconnected(their_node_id);
311 )*
312 }
313
314 fn peer_connected(&self, their_node_id: $crate::bitcoin::secp256k1::PublicKey, msg: &$crate::lightning::ln::msgs::Init, inbound: bool) -> Result<(), ()> {
315 let mut result = Ok(());
316 $(
317 if let Err(e) = self.$field.peer_connected(their_node_id, msg, inbound) {
318 result = Err(e);
319 }
320 )*
321 result
322 }
323
324 fn provided_node_features(&self) -> $crate::lightning::types::features::NodeFeatures {
325 $crate::lightning::types::features::NodeFeatures::empty()
326 $(
327 | self.$field.provided_node_features()
328 )*
329 }
330
331 fn provided_init_features(
332 &self, their_node_id: $crate::bitcoin::secp256k1::PublicKey
333 ) -> $crate::lightning::types::features::InitFeatures {
334 $crate::lightning::types::features::InitFeatures::empty()
335 $(
336 | self.$field.provided_init_features(their_node_id)
337 )*
338 }
339 }
340
341 impl $crate::lightning::ln::wire::CustomMessageReader for $handler {
342 type CustomMessage = $message;
343 fn read<R: $crate::lightning::io::Read>(
344 &self, message_type: u16, buffer: &mut R
345 ) -> Result<Option<Self::CustomMessage>, $crate::lightning::ln::msgs::DecodeError> {
346 match message_type {
347 $(
348 $pattern => match <$type>::read(&self.$field, message_type, buffer)? {
349 None => unreachable!(),
350 Some(message) => Ok(Some($message::$variant(message))),
351 },
352 )*
353 _ => Ok(None),
354 }
355 }
356 }
357
358 impl $crate::lightning::ln::wire::Type for $message {
359 fn type_id(&self) -> u16 {
360 match self {
361 $(
362 Self::$variant(message) => message.type_id(),
363 )*
364 }
365 }
366 }
367
368 impl $crate::lightning::util::ser::Writeable for $message {
369 fn write<W: $crate::lightning::util::ser::Writer>(&self, writer: &mut W) -> Result<(), $crate::lightning::io::Error> {
370 match self {
371 $(
372 Self::$variant(message) => message.write(writer),
373 )*
374 }
375 }
376 }
377 }
378}