Skip to main content

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				// Per the `CustomMessageHandler::peer_connected` contract, `peer_disconnected`
316				// will not be called by `PeerManager` if we return `Err`. To avoid leaking
317				// per-peer state in sub-handlers that already returned `Ok` when a later one
318				// errors, record each sub-handler's result and roll back the successful ones
319				// ourselves before propagating the failure.
320				$(
321					let $field = self.$field.peer_connected(their_node_id, msg, inbound);
322				)*
323				let any_err = false $( || $field.is_err() )*;
324				if any_err {
325					$(
326						if $field.is_ok() {
327							self.$field.peer_disconnected(their_node_id);
328						}
329					)*
330					Err(())
331				} else {
332					Ok(())
333				}
334			}
335
336			fn provided_node_features(&self) -> $crate::lightning::types::features::NodeFeatures {
337				$crate::lightning::types::features::NodeFeatures::empty()
338					$(
339						| self.$field.provided_node_features()
340					)*
341			}
342
343			fn provided_init_features(
344				&self, their_node_id: $crate::bitcoin::secp256k1::PublicKey
345			) -> $crate::lightning::types::features::InitFeatures {
346				$crate::lightning::types::features::InitFeatures::empty()
347					$(
348						| self.$field.provided_init_features(their_node_id)
349					)*
350			}
351		}
352
353		impl $crate::lightning::ln::wire::CustomMessageReader for $handler {
354			type CustomMessage = $message;
355			fn read<R: $crate::lightning::io::Read>(
356				&self, message_type: u16, buffer: &mut R
357			) -> Result<Option<Self::CustomMessage>, $crate::lightning::ln::msgs::DecodeError> {
358				match message_type {
359					$(
360						$pattern => match <$type>::read(&self.$field, message_type, buffer)? {
361							// A sub-handler returns `None` for a `message_type` it doesn't
362							// recognize. The composite's pattern can be broader than the types
363							// the sub-handler decodes (e.g. a range), and `message_type` is
364							// peer-provided, so report the message as unknown rather than
365							// treating this as unreachable and panicking.
366							None => Ok(None),
367							Some(message) => Ok(Some($message::$variant(message))),
368						},
369					)*
370					_ => Ok(None),
371				}
372			}
373		}
374
375		impl $crate::lightning::ln::wire::Type for $message {
376			fn type_id(&self) -> u16 {
377				match self {
378					$(
379						Self::$variant(message) => message.type_id(),
380					)*
381				}
382			}
383		}
384
385		impl $crate::lightning::util::ser::Writeable for $message {
386			fn write<W: $crate::lightning::util::ser::Writer>(&self, writer: &mut W) -> Result<(), $crate::lightning::io::Error> {
387				match self {
388					$(
389						Self::$variant(message) => message.write(writer),
390					)*
391				}
392			}
393		}
394	}
395}
396
397#[cfg(test)]
398mod tests {
399	use bitcoin::io::Read;
400	use bitcoin::secp256k1::PublicKey;
401	use core::sync::atomic::{AtomicUsize, Ordering};
402	use lightning::io;
403	use lightning::ln::msgs::{DecodeError, Init, LightningError};
404	use lightning::ln::peer_handler::CustomMessageHandler;
405	use lightning::ln::wire::{CustomMessageReader, Type};
406	use lightning::types::features::{InitFeatures, NodeFeatures};
407	use lightning::util::ser::{Writeable, Writer};
408
409	#[derive(Debug)]
410	pub struct Foo;
411	impl Type for Foo {
412		fn type_id(&self) -> u16 {
413			32768
414		}
415	}
416	impl Writeable for Foo {
417		fn write<W: Writer>(&self, _: &mut W) -> Result<(), io::Error> {
418			Ok(())
419		}
420	}
421
422	pub struct CountingHandler {
423		pub connect_count: AtomicUsize,
424	}
425	impl CustomMessageReader for CountingHandler {
426		type CustomMessage = Foo;
427		fn read<R: Read>(
428			&self, _t: u16, _b: &mut R,
429		) -> Result<Option<Foo>, DecodeError> {
430			Ok(None)
431		}
432	}
433	impl CustomMessageHandler for CountingHandler {
434		fn handle_custom_message(&self, _msg: Foo, _: PublicKey) -> Result<(), LightningError> {
435			Ok(())
436		}
437		fn get_and_clear_pending_msg(&self) -> Vec<(PublicKey, Foo)> {
438			vec![]
439		}
440		fn peer_disconnected(&self, _: PublicKey) {
441			self.connect_count.fetch_sub(1, Ordering::SeqCst);
442		}
443		fn peer_connected(&self, _: PublicKey, _: &Init, _: bool) -> Result<(), ()> {
444			self.connect_count.fetch_add(1, Ordering::SeqCst);
445			Ok(())
446		}
447		fn provided_node_features(&self) -> NodeFeatures {
448			NodeFeatures::empty()
449		}
450		fn provided_init_features(&self, _: PublicKey) -> InitFeatures {
451			InitFeatures::empty()
452		}
453	}
454
455	#[derive(Debug)]
456	pub struct Bar;
457	impl Type for Bar {
458		fn type_id(&self) -> u16 {
459			32769
460		}
461	}
462	impl Writeable for Bar {
463		fn write<W: Writer>(&self, _: &mut W) -> Result<(), io::Error> {
464			Ok(())
465		}
466	}
467
468	pub struct ErroringHandler;
469	impl CustomMessageReader for ErroringHandler {
470		type CustomMessage = Bar;
471		fn read<R: Read>(
472			&self, _t: u16, _b: &mut R,
473		) -> Result<Option<Bar>, DecodeError> {
474			Ok(None)
475		}
476	}
477	impl CustomMessageHandler for ErroringHandler {
478		fn handle_custom_message(&self, _msg: Bar, _: PublicKey) -> Result<(), LightningError> {
479			Ok(())
480		}
481		fn get_and_clear_pending_msg(&self) -> Vec<(PublicKey, Bar)> {
482			vec![]
483		}
484		fn peer_disconnected(&self, _: PublicKey) {
485			debug_assert!(false);
486		}
487		fn peer_connected(&self, _: PublicKey, _: &Init, _: bool) -> Result<(), ()> {
488			Err(())
489		}
490		fn provided_node_features(&self) -> NodeFeatures {
491			NodeFeatures::empty()
492		}
493		fn provided_init_features(&self, _: PublicKey) -> InitFeatures {
494			InitFeatures::empty()
495		}
496	}
497
498	composite_custom_message_handler!(
499		pub struct CompositeHandler {
500			counting: CountingHandler,
501			erroring: ErroringHandler,
502		}
503
504		pub enum CompositeMessage {
505			Foo(32768),
506			Bar(32769),
507		}
508	);
509
510	struct ReservedBlockHandler;
511	impl CustomMessageReader for ReservedBlockHandler {
512		type CustomMessage = Foo;
513		fn read<R: Read>(
514			&self, message_type: u16, _b: &mut R,
515		) -> Result<Option<Foo>, DecodeError> {
516			// This build defines only the message at 32768; the rest of the block its
517			// protocol reserved (32768..=32777) is for types future versions may add.
518			// A not-yet-defined type is unknown to this build, so per the
519			// `CustomMessageReader` contract it returns `Ok(None)` -- a newer peer can
520			// send one and this older node will treat it as an unknown message.
521			match message_type {
522				32768 => Ok(Some(Foo)),
523				_ => Ok(None),
524			}
525		}
526	}
527	impl CustomMessageHandler for ReservedBlockHandler {
528		fn handle_custom_message(&self, _msg: Foo, _: PublicKey) -> Result<(), LightningError> {
529			Ok(())
530		}
531		fn get_and_clear_pending_msg(&self) -> Vec<(PublicKey, Foo)> {
532			vec![]
533		}
534		fn peer_disconnected(&self, _: PublicKey) {}
535		fn peer_connected(&self, _: PublicKey, _: &Init, _: bool) -> Result<(), ()> {
536			Ok(())
537		}
538		fn provided_node_features(&self) -> NodeFeatures {
539			NodeFeatures::empty()
540		}
541		fn provided_init_features(&self, _: PublicKey) -> InitFeatures {
542			InitFeatures::empty()
543		}
544	}
545
546	composite_custom_message_handler!(
547		struct ReservedBlockComposite {
548			proto: ReservedBlockHandler,
549		}
550
551		enum ReservedBlockMessage {
552			Proto(32768..=32777),
553		}
554	);
555
556	#[test]
557	fn read_treats_a_reserved_in_range_type_as_unknown() {
558		// A sub-handler may own a block of type ids (declared here as a range) yet only
559		// decode the subset its build defines, returning `Ok(None)` for reserved or
560		// not-yet-defined types in the block -- exactly what a node does on receiving a
561		// newer peer's message. `read` must surface that as an unknown message, not
562		// panic.
563		let composite = ReservedBlockComposite { proto: ReservedBlockHandler };
564		let mut buffer: &[u8] = &[];
565		// The message this build defines decodes to its variant.
566		assert!(matches!(
567			composite.read(32768, &mut buffer),
568			Ok(Some(ReservedBlockMessage::Proto(_)))
569		));
570		// A reserved type from the same block is reported unknown, not panicked
571		// (pre-fix the matched arm hit `unreachable!()`).
572		assert!(matches!(composite.read(32770, &mut buffer), Ok(None)));
573	}
574
575	#[test]
576	fn peer_connected_failure_does_not_leak_subhandler_state() {
577		let composite = CompositeHandler {
578			counting: CountingHandler { connect_count: AtomicUsize::new(0) },
579			erroring: ErroringHandler,
580		};
581		let pk_bytes = [
582			0x02, 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE,
583			0x87, 0x0B, 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81,
584			0x5B, 0x16, 0xF8, 0x17, 0x98,
585		];
586		let pk = PublicKey::from_slice(&pk_bytes).unwrap();
587		let init =
588			Init { features: InitFeatures::empty(), networks: None, remote_network_address: None };
589
590		let result = composite.peer_connected(pk, &init, true);
591		assert!(result.is_err(), "Composite must propagate the inner Err");
592
593		let leaked = composite.counting.connect_count.load(Ordering::SeqCst);
594		assert_eq!(
595			leaked, 0,
596			"CountingHandler tracked {leaked} connected peer(s) after the composite \
597			 returned Err; this state will never be cleaned up because per the trait \
598			 contract peer_disconnected won't be called when peer_connected returns Err.",
599		);
600	}
601}