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}