#lightning #message #supporting #p2p #bitcoin #ldk #foo-bar

lightning-custom-message

Utilities for supporting custom peer-to-peer messages in LDK

22 releases

0.0.125 Oct 14, 2024
0.0.124-rc1 Aug 29, 2024
0.0.123 May 9, 2024
0.0.121 Jan 23, 2024
0.0.114 Mar 4, 2023

#6 in #ldk

23 downloads per month

MIT/Apache

7MB
113K SLoC

Utilities for supporting custom peer-to-peer messages in LDK.

BOLT 1 specifies a custom message type range for use with experimental or application-specific messages. While a CustomMessageHandler can be defined to support more than one message type, defining such a handler requires a significant amount of boilerplate and can be error prone.

This crate provides the composite_custom_message_handler macro for easily composing pre-defined custom message handlers into one handler. The resulting handler can be further composed with other custom message handlers using the same macro.

The following example demonstrates defining a FooBarHandler to compose separate handlers for Foo and Bar messages, and further composing it with a handler for Baz messages.

 # fn main() {} // Avoid #[macro_export] generating an in-function warning
 # extern crate bitcoin;
 extern crate lightning;
 #[macro_use]
 extern crate lightning_custom_message;

 # use bitcoin::secp256k1::PublicKey;
 # use lightning::io;
 # use lightning::ln::msgs::{DecodeError, Init, LightningError};
 # use lightning::ln::features::{InitFeatures, NodeFeatures};
 use lightning::ln::peer_handler::CustomMessageHandler;
 use lightning::ln::wire::{CustomMessageReader, self};
 use lightning::util::ser::Writeable;
 # use lightning::util::ser::Writer;

 // Assume that `FooHandler` and `BarHandler` are defined in one crate and `BazHandler` is
 // defined in another crate, handling messages `Foo`, `Bar`, and `Baz`, respectively.

 #[derive(Debug)]
 pub struct Foo;

 macro_rules! foo_type_id {
     () => { 32768 }
 }

 impl wire::Type for Foo {
     fn type_id(&self) -> u16 { foo_type_id!() }
 }
 impl Writeable for Foo {
     // ...
 #     fn write<W: Writer>(&self, _: &mut W) -> Result<(), io::Error> {
 #         unimplemented!()
 #     }
 }

 pub struct FooHandler;

 impl CustomMessageReader for FooHandler {
     // ...
 #     type CustomMessage = Foo;
 #     fn read<R: io::Read>(
 #         &self, _message_type: u16, _buffer: &mut R
 #     ) -> Result<Option<Self::CustomMessage>, DecodeError> {
 #         unimplemented!()
 #     }
 }
 impl CustomMessageHandler for FooHandler {
     // ...
 #     fn handle_custom_message(
 #         &self, _msg: Self::CustomMessage, _sender_node_id: &PublicKey
 #     ) -> Result<(), LightningError> {
 #         unimplemented!()
 #     }
 #     fn get_and_clear_pending_msg(&self) -> Vec<(PublicKey, Self::CustomMessage)> {
 #         unimplemented!()
 #     }
 #     fn peer_disconnected(&self, _their_node_id: &PublicKey) {
 #         unimplemented!()
 #     }
 #     fn peer_connected(&self, _their_node_id: &PublicKey, _msg: &Init, _inbound: bool) -> Result<(), ()> {
 #         unimplemented!()
 #     }
 #     fn provided_node_features(&self) -> NodeFeatures {
 #         unimplemented!()
 #     }
 #     fn provided_init_features(&self, _their_node_id: &PublicKey) -> InitFeatures {
 #         unimplemented!()
 #     }
 }

 #[derive(Debug)]
 pub struct Bar;

 macro_rules! bar_type_id {
     () => { 32769 }
 }

 impl wire::Type for Bar {
     fn type_id(&self) -> u16 { bar_type_id!() }
 }
 impl Writeable for Bar {
     // ...
 #     fn write<W: Writer>(&self, _: &mut W) -> Result<(), io::Error> {
 #         unimplemented!()
 #     }
 }

 pub struct BarHandler;

 impl CustomMessageReader for BarHandler {
     // ...
 #     type CustomMessage = Bar;
 #     fn read<R: io::Read>(
 #         &self, _message_type: u16, _buffer: &mut R
 #     ) -> Result<Option<Self::CustomMessage>, DecodeError> {
 #         unimplemented!()
 #     }
 }
 impl CustomMessageHandler for BarHandler {
     // ...
 #     fn handle_custom_message(
 #         &self, _msg: Self::CustomMessage, _sender_node_id: &PublicKey
 #     ) -> Result<(), LightningError> {
 #         unimplemented!()
 #     }
 #     fn get_and_clear_pending_msg(&self) -> Vec<(PublicKey, Self::CustomMessage)> {
 #         unimplemented!()
 #     }
 #     fn peer_disconnected(&self, _their_node_id: &PublicKey) {
 #         unimplemented!()
 #     }
 #     fn peer_connected(&self, _their_node_id: &PublicKey, _msg: &Init, _inbound: bool) -> Result<(), ()> {
 #         unimplemented!()
 #     }
 #     fn provided_node_features(&self) -> NodeFeatures {
 #         unimplemented!()
 #     }
 #     fn provided_init_features(&self, _their_node_id: &PublicKey) -> InitFeatures {
 #         unimplemented!()
 #     }
 }

 #[derive(Debug)]
 pub struct Baz;

 macro_rules! baz_type_id {
     () => { 32770 }
 }

 impl wire::Type for Baz {
     fn type_id(&self) -> u16 { baz_type_id!() }
 }
 impl Writeable for Baz {
     // ...
 #     fn write<W: Writer>(&self, _: &mut W) -> Result<(), io::Error> {
 #         unimplemented!()
 #     }
 }

 pub struct BazHandler;

 impl CustomMessageReader for BazHandler {
     // ...
 #     type CustomMessage = Baz;
 #     fn read<R: io::Read>(
 #         &self, _message_type: u16, _buffer: &mut R
 #     ) -> Result<Option<Self::CustomMessage>, DecodeError> {
 #         unimplemented!()
 #     }
 }
 impl CustomMessageHandler for BazHandler {
     // ...
 #     fn handle_custom_message(
 #         &self, _msg: Self::CustomMessage, _sender_node_id: &PublicKey
 #     ) -> Result<(), LightningError> {
 #         unimplemented!()
 #     }
 #     fn get_and_clear_pending_msg(&self) -> Vec<(PublicKey, Self::CustomMessage)> {
 #         unimplemented!()
 #     }
 #     fn peer_disconnected(&self, _their_node_id: &PublicKey) {
 #         unimplemented!()
 #     }
 #     fn peer_connected(&self, _their_node_id: &PublicKey, _msg: &Init, _inbound: bool) -> Result<(), ()> {
 #         unimplemented!()
 #     }
 #     fn provided_node_features(&self) -> NodeFeatures {
 #         unimplemented!()
 #     }
 #     fn provided_init_features(&self, _their_node_id: &PublicKey) -> InitFeatures {
 #         unimplemented!()
 #     }
 }

 // The first crate may define a handler composing `FooHandler` and `BarHandler` and export the
 // corresponding message type ids as a macro to use in further composition.

 composite_custom_message_handler!(
     pub struct FooBarHandler {
         foo: FooHandler,
         bar: BarHandler,
     }

     pub enum FooBarMessage {
         Foo(foo_type_id!()),
         Bar(bar_type_id!()),
     }
 );

 #[macro_export]
 macro_rules! foo_bar_type_ids {
     () => { foo_type_id!() | bar_type_id!() }
 }

 // Another crate can then define a handler further composing `FooBarHandler` with `BazHandler`
 // and similarly export the composition of message type ids as a macro.

 composite_custom_message_handler!(
     pub struct FooBarBazHandler {
         foo_bar: FooBarHandler,
         baz: BazHandler,
     }

     pub enum FooBarBazMessage {
         FooBar(foo_bar_type_ids!()),
         Baz(baz_type_id!()),
     }
 );

 #[macro_export]
 macro_rules! foo_bar_baz_type_ids {
     () => { foo_bar_type_ids!() | baz_type_id!() }
 }

Dependencies

~7.5MB
~96K SLoC