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}