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::{LengthLimitedRead, 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: LengthLimitedRead>(
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: LengthLimitedRead>(
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: LengthLimitedRead>(
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::util::ser::LengthLimitedRead>(
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::secp256k1::PublicKey;
400	use core::sync::atomic::{AtomicUsize, Ordering};
401	use lightning::io;
402	use lightning::ln::msgs::{DecodeError, Init, LightningError};
403	use lightning::ln::peer_handler::CustomMessageHandler;
404	use lightning::ln::wire::{CustomMessageReader, Type};
405	use lightning::types::features::{InitFeatures, NodeFeatures};
406	use lightning::util::ser::{LengthLimitedRead, Writeable, Writer};
407
408	#[derive(Debug)]
409	pub struct Foo;
410	impl Type for Foo {
411		fn type_id(&self) -> u16 {
412			32768
413		}
414	}
415	impl Writeable for Foo {
416		fn write<W: Writer>(&self, _: &mut W) -> Result<(), io::Error> {
417			Ok(())
418		}
419	}
420
421	pub struct CountingHandler {
422		pub connect_count: AtomicUsize,
423	}
424	impl CustomMessageReader for CountingHandler {
425		type CustomMessage = Foo;
426		fn read<R: LengthLimitedRead>(
427			&self, _t: u16, _b: &mut R,
428		) -> Result<Option<Foo>, DecodeError> {
429			Ok(None)
430		}
431	}
432	impl CustomMessageHandler for CountingHandler {
433		fn handle_custom_message(&self, _msg: Foo, _: PublicKey) -> Result<(), LightningError> {
434			Ok(())
435		}
436		fn get_and_clear_pending_msg(&self) -> Vec<(PublicKey, Foo)> {
437			vec![]
438		}
439		fn peer_disconnected(&self, _: PublicKey) {
440			self.connect_count.fetch_sub(1, Ordering::SeqCst);
441		}
442		fn peer_connected(&self, _: PublicKey, _: &Init, _: bool) -> Result<(), ()> {
443			self.connect_count.fetch_add(1, Ordering::SeqCst);
444			Ok(())
445		}
446		fn provided_node_features(&self) -> NodeFeatures {
447			NodeFeatures::empty()
448		}
449		fn provided_init_features(&self, _: PublicKey) -> InitFeatures {
450			InitFeatures::empty()
451		}
452	}
453
454	#[derive(Debug)]
455	pub struct Bar;
456	impl Type for Bar {
457		fn type_id(&self) -> u16 {
458			32769
459		}
460	}
461	impl Writeable for Bar {
462		fn write<W: Writer>(&self, _: &mut W) -> Result<(), io::Error> {
463			Ok(())
464		}
465	}
466
467	pub struct ErroringHandler;
468	impl CustomMessageReader for ErroringHandler {
469		type CustomMessage = Bar;
470		fn read<R: LengthLimitedRead>(
471			&self, _t: u16, _b: &mut R,
472		) -> Result<Option<Bar>, DecodeError> {
473			Ok(None)
474		}
475	}
476	impl CustomMessageHandler for ErroringHandler {
477		fn handle_custom_message(&self, _msg: Bar, _: PublicKey) -> Result<(), LightningError> {
478			Ok(())
479		}
480		fn get_and_clear_pending_msg(&self) -> Vec<(PublicKey, Bar)> {
481			vec![]
482		}
483		fn peer_disconnected(&self, _: PublicKey) {
484			debug_assert!(false);
485		}
486		fn peer_connected(&self, _: PublicKey, _: &Init, _: bool) -> Result<(), ()> {
487			Err(())
488		}
489		fn provided_node_features(&self) -> NodeFeatures {
490			NodeFeatures::empty()
491		}
492		fn provided_init_features(&self, _: PublicKey) -> InitFeatures {
493			InitFeatures::empty()
494		}
495	}
496
497	composite_custom_message_handler!(
498		pub struct CompositeHandler {
499			counting: CountingHandler,
500			erroring: ErroringHandler,
501		}
502
503		pub enum CompositeMessage {
504			Foo(32768),
505			Bar(32769),
506		}
507	);
508
509	struct ReservedBlockHandler;
510	impl CustomMessageReader for ReservedBlockHandler {
511		type CustomMessage = Foo;
512		fn read<R: LengthLimitedRead>(
513			&self, message_type: u16, _b: &mut R,
514		) -> Result<Option<Foo>, DecodeError> {
515			// This build defines only the message at 32768; the rest of the block its
516			// protocol reserved (32768..=32777) is for types future versions may add.
517			// A not-yet-defined type is unknown to this build, so per the
518			// `CustomMessageReader` contract it returns `Ok(None)` -- a newer peer can
519			// send one and this older node will treat it as an unknown message.
520			match message_type {
521				32768 => Ok(Some(Foo)),
522				_ => Ok(None),
523			}
524		}
525	}
526	impl CustomMessageHandler for ReservedBlockHandler {
527		fn handle_custom_message(&self, _msg: Foo, _: PublicKey) -> Result<(), LightningError> {
528			Ok(())
529		}
530		fn get_and_clear_pending_msg(&self) -> Vec<(PublicKey, Foo)> {
531			vec![]
532		}
533		fn peer_disconnected(&self, _: PublicKey) {}
534		fn peer_connected(&self, _: PublicKey, _: &Init, _: bool) -> Result<(), ()> {
535			Ok(())
536		}
537		fn provided_node_features(&self) -> NodeFeatures {
538			NodeFeatures::empty()
539		}
540		fn provided_init_features(&self, _: PublicKey) -> InitFeatures {
541			InitFeatures::empty()
542		}
543	}
544
545	composite_custom_message_handler!(
546		struct ReservedBlockComposite {
547			proto: ReservedBlockHandler,
548		}
549
550		enum ReservedBlockMessage {
551			Proto(32768..=32777),
552		}
553	);
554
555	#[test]
556	fn read_treats_a_reserved_in_range_type_as_unknown() {
557		// A sub-handler may own a block of type ids (declared here as a range) yet only
558		// decode the subset its build defines, returning `Ok(None)` for reserved or
559		// not-yet-defined types in the block -- exactly what a node does on receiving a
560		// newer peer's message. `read` must surface that as an unknown message, not
561		// panic.
562		let composite = ReservedBlockComposite { proto: ReservedBlockHandler };
563		let mut buffer: &[u8] = &[];
564		// The message this build defines decodes to its variant.
565		assert!(matches!(
566			composite.read(32768, &mut buffer),
567			Ok(Some(ReservedBlockMessage::Proto(_)))
568		));
569		// A reserved type from the same block is reported unknown, not panicked
570		// (pre-fix the matched arm hit `unreachable!()`).
571		assert!(matches!(composite.read(32770, &mut buffer), Ok(None)));
572	}
573
574	#[test]
575	fn peer_connected_failure_does_not_leak_subhandler_state() {
576		let composite = CompositeHandler {
577			counting: CountingHandler { connect_count: AtomicUsize::new(0) },
578			erroring: ErroringHandler,
579		};
580		let pk_bytes = [
581			0x02, 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE,
582			0x87, 0x0B, 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81,
583			0x5B, 0x16, 0xF8, 0x17, 0x98,
584		];
585		let pk = PublicKey::from_slice(&pk_bytes).unwrap();
586		let init =
587			Init { features: InitFeatures::empty(), networks: None, remote_network_address: None };
588
589		let result = composite.peer_connected(pk, &init, true);
590		assert!(result.is_err(), "Composite must propagate the inner Err");
591
592		let leaked = composite.counting.connect_count.load(Ordering::SeqCst);
593		assert_eq!(
594			leaked, 0,
595			"CountingHandler tracked {leaked} connected peer(s) after the composite \
596			 returned Err; this state will never be cleaned up because per the trait \
597			 contract peer_disconnected won't be called when peer_connected returns Err.",
598		);
599	}
600}