Merge pull request #2008 from valentinewallace/2023-02-remove-manual-retries
authorMatt Corallo <649246+TheBlueMatt@users.noreply.github.com>
Thu, 16 Feb 2023 00:49:04 +0000 (00:49 +0000)
committerGitHub <noreply@github.com>
Thu, 16 Feb 2023 00:49:04 +0000 (00:49 +0000)
Abandon payments on behalf of the user and remove manual retries

.github/workflows/build.yml
.gitignore
Cargo.toml
lightning-custom-message/Cargo.toml [new file with mode: 0644]
lightning-custom-message/src/lib.rs [new file with mode: 0644]
lightning/src/ln/peer_handler.rs
lightning/src/onion_message/messenger.rs

index f729cecc01218fb54839c555c18c64ce36d36395..a8f0aa69d94502caaf8e2e420c85a07821d6555b 100644 (file)
@@ -31,6 +31,8 @@ jobs:
             build-no-std: true
             build-futures: true
             build-tx-sync: true
+          - toolchain: stable
+            test-custom-message: true
           - toolchain: beta
             platform: macos-latest
             build-net-tokio: true
@@ -54,6 +56,8 @@ jobs:
             build-no-std: true
             build-futures: true
             build-tx-sync: true
+          - toolchain: beta
+            test-custom-message: true
           - toolchain: 1.41.1
             build-no-std: false
             test-log-variants: true
@@ -226,6 +230,11 @@ jobs:
           RUSTFLAGS="-C link-dead-code" cargo test --verbose --color always --features rpc-client
           RUSTFLAGS="-C link-dead-code" cargo test --verbose --color always --features rpc-client,rest-client
           RUSTFLAGS="-C link-dead-code" cargo test --verbose --color always --features rpc-client,rest-client,tokio
+      - name: Test Custom Message Macros on Rust ${{ matrix.toolchain }}
+        if: "matrix.test-custom-message"
+        run: |
+          cd lightning-custom-message
+          cargo test --verbose --color always
       - name: Install deps for kcov
         if: matrix.coverage
         run: |
index d99c5a4ddf6603b32fb97d666d49c3ebb631df79..7a889b5b8230af929cd28134454d2f93502531bd 100644 (file)
@@ -9,5 +9,5 @@ Cargo.lock
 .idea
 lightning/target
 lightning/ldk-net_graph-*.bin
+lightning-custom-message/target
 no-std-check/target
-
index e8565e7ac0945d6a189079f40b5c91c96326c1c1..be76477f4c0f0548121cc8f5770053e798bbd3d0 100644 (file)
@@ -12,6 +12,7 @@ members = [
 ]
 
 exclude = [
+    "lightning-custom-message",
     "no-std-check",
 ]
 
diff --git a/lightning-custom-message/Cargo.toml b/lightning-custom-message/Cargo.toml
new file mode 100644 (file)
index 0000000..657844c
--- /dev/null
@@ -0,0 +1,18 @@
+[package]
+name = "lightning-custom-message"
+version = "0.0.113"
+authors = ["Jeffrey Czyz"]
+license = "MIT OR Apache-2.0"
+repository = "http://github.com/lightningdevkit/rust-lightning"
+description = """
+Utilities for supporting custom peer-to-peer messages in LDK.
+"""
+edition = "2021"
+
+[package.metadata.docs.rs]
+all-features = true
+rustdoc-args = ["--cfg", "docsrs"]
+
+[dependencies]
+bitcoin = "0.29.0"
+lightning = { version = "0.0.113", path = "../lightning" }
diff --git a/lightning-custom-message/src/lib.rs b/lightning-custom-message/src/lib.rs
new file mode 100644 (file)
index 0000000..a6e4397
--- /dev/null
@@ -0,0 +1,310 @@
+//! 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.
+//!
+//!```
+//! # 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, LightningError};
+//! 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!()
+//! #     }
+//! }
+//!
+//! #[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!()
+//! #     }
+//! }
+//!
+//! #[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 main() {
+//! // 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!() }
+//! }
+//! # }
+//!```
+//!
+//! [BOLT 1]: https://github.com/lightning/bolts/blob/master/01-messaging.md
+//! [`CustomMessageHandler`]: crate::lightning::ln::peer_handler::CustomMessageHandler
+
+#![doc(test(no_crate_inject, attr(deny(warnings))))]
+
+pub extern crate bitcoin;
+pub extern crate lightning;
+
+/// Defines a composite type implementing [`CustomMessageHandler`] (and therefore also implementing
+/// [`CustomMessageReader`]), along with a corresponding enumerated custom message [`Type`], from
+/// one or more previously defined custom message handlers.
+///
+/// Useful for parameterizing [`PeerManager`] with custom message handling for one or more sets of
+/// custom messages. Message type ids may be given as a valid `match` pattern, including ranges,
+/// though using OR-ed literal patterns is preferred in order to catch unreachable code for
+/// conflicting handlers.
+///
+/// See [crate documentation] for example usage.
+///
+/// [`CustomMessageHandler`]: crate::lightning::ln::peer_handler::CustomMessageHandler
+/// [`CustomMessageReader`]: crate::lightning::ln::wire::CustomMessageReader
+/// [`Type`]: crate::lightning::ln::wire::Type
+/// [`PeerManager`]: crate::lightning::ln::peer_handler::PeerManager
+/// [crate documentation]: self
+#[macro_export]
+macro_rules! composite_custom_message_handler {
+       (
+               $handler_visibility:vis struct $handler:ident {
+                       $($field_visibility:vis $field:ident: $type:ty),* $(,)*
+               }
+
+               $message_visibility:vis enum $message:ident {
+                       $($variant:ident($pattern:pat)),* $(,)*
+               }
+       ) => {
+               #[allow(missing_docs)]
+               $handler_visibility struct $handler {
+                       $(
+                               $field_visibility $field: $type,
+                       )*
+               }
+
+               #[allow(missing_docs)]
+               #[derive(Debug)]
+               $message_visibility enum $message {
+                       $(
+                               $variant(<$type as $crate::lightning::ln::wire::CustomMessageReader>::CustomMessage),
+                       )*
+               }
+
+               impl $crate::lightning::ln::peer_handler::CustomMessageHandler for $handler {
+                       fn handle_custom_message(
+                               &self, msg: Self::CustomMessage, sender_node_id: &$crate::bitcoin::secp256k1::PublicKey
+                       ) -> Result<(), $crate::lightning::ln::msgs::LightningError> {
+                               match msg {
+                                       $(
+                                               $message::$variant(message) => {
+                                                       $crate::lightning::ln::peer_handler::CustomMessageHandler::handle_custom_message(
+                                                               &self.$field, message, sender_node_id
+                                                       )
+                                               },
+                                       )*
+                               }
+                       }
+
+                       fn get_and_clear_pending_msg(&self) -> Vec<($crate::bitcoin::secp256k1::PublicKey, Self::CustomMessage)> {
+                               vec![].into_iter()
+                                       $(
+                                               .chain(
+                                                       self.$field
+                                                               .get_and_clear_pending_msg()
+                                                               .into_iter()
+                                                               .map(|(pubkey, message)| (pubkey, $message::$variant(message)))
+                                               )
+                                       )*
+                                       .collect()
+                       }
+               }
+
+               impl $crate::lightning::ln::wire::CustomMessageReader for $handler {
+                       type CustomMessage = $message;
+                       fn read<R: $crate::lightning::io::Read>(
+                               &self, message_type: u16, buffer: &mut R
+                       ) -> Result<Option<Self::CustomMessage>, $crate::lightning::ln::msgs::DecodeError> {
+                               match message_type {
+                                       $(
+                                               $pattern => match <$type>::read(&self.$field, message_type, buffer)? {
+                                                       None => unreachable!(),
+                                                       Some(message) => Ok(Some($message::$variant(message))),
+                                               },
+                                       )*
+                                       _ => Ok(None),
+                               }
+                       }
+               }
+
+               impl $crate::lightning::ln::wire::Type for $message {
+                       fn type_id(&self) -> u16 {
+                               match self {
+                                       $(
+                                               Self::$variant(message) => message.type_id(),
+                                       )*
+                               }
+                       }
+               }
+
+               impl $crate::lightning::util::ser::Writeable for $message {
+                       fn write<W: $crate::lightning::util::ser::Writer>(&self, writer: &mut W) -> Result<(), $crate::lightning::io::Error> {
+                               match self {
+                                       $(
+                                               Self::$variant(message) => message.write(writer),
+                                       )*
+                               }
+                       }
+               }
+       }
+}
index 3775c27e4dff9b0c001303e1ea859b5856431d33..8c3ab968af20f92e3a544d7d1fea024837bd26e6 100644 (file)
@@ -46,16 +46,23 @@ use bitcoin::hashes::sha256::Hash as Sha256;
 use bitcoin::hashes::sha256::HashEngine as Sha256Engine;
 use bitcoin::hashes::{HashEngine, Hash};
 
-/// Handler for BOLT1-compliant messages.
+/// A handler provided to [`PeerManager`] for reading and handling custom messages.
+///
+/// [BOLT 1] specifies a custom message type range for use with experimental or application-specific
+/// messages. `CustomMessageHandler` allows for user-defined handling of such types. See the
+/// [`lightning_custom_message`] crate for tools useful in composing more than one custom handler.
+///
+/// [BOLT 1]: https://github.com/lightning/bolts/blob/master/01-messaging.md
+/// [`lightning_custom_message`]: https://docs.rs/lightning_custom_message/latest/lightning_custom_message
 pub trait CustomMessageHandler: wire::CustomMessageReader {
-       /// Called with the message type that was received and the buffer to be read.
-       /// Can return a `MessageHandlingError` if the message could not be handled.
+       /// Handles the given message sent from `sender_node_id`, possibly producing messages for
+       /// [`CustomMessageHandler::get_and_clear_pending_msg`] to return and thus for [`PeerManager`]
+       /// to send.
        fn handle_custom_message(&self, msg: Self::CustomMessage, sender_node_id: &PublicKey) -> Result<(), LightningError>;
 
-       /// Gets the list of pending messages which were generated by the custom message
-       /// handler, clearing the list in the process. The first tuple element must
-       /// correspond to the intended recipients node ids. If no connection to one of the
-       /// specified node does not exist, the message is simply not sent to it.
+       /// Returns the list of pending messages that were generated by the handler, clearing the list
+       /// in the process. Each message is paired with the node id of the intended recipient. If no
+       /// connection to the node exists, then the message is simply not sent.
        fn get_and_clear_pending_msg(&self) -> Vec<(PublicKey, Self::CustomMessage)>;
 }
 
index 497628607ce0ff5ec4154f9546a8dc28179747e3..f7656e7949aa9df945010eadee9b0ba30eefb861 100644 (file)
@@ -43,15 +43,14 @@ use crate::prelude::*;
 /// # extern crate bitcoin;
 /// # use bitcoin::hashes::_export::_core::time::Duration;
 /// # use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
-/// # use lightning::chain::keysinterface::{InMemorySigner, KeysManager};
-/// # use lightning::ln::msgs::DecodeError;
+/// # use lightning::chain::keysinterface::KeysManager;
 /// # use lightning::ln::peer_handler::IgnoringMessageHandler;
 /// # use lightning::onion_message::{BlindedPath, CustomOnionMessageContents, Destination, OnionMessageContents, OnionMessenger};
 /// # use lightning::util::logger::{Logger, Record};
 /// # use lightning::util::ser::{Writeable, Writer};
 /// # use lightning::io;
 /// # use std::sync::Arc;
-/// # struct FakeLogger {};
+/// # struct FakeLogger;
 /// # impl Logger for FakeLogger {
 /// #     fn log(&self, record: &Record) { unimplemented!() }
 /// # }
@@ -67,7 +66,7 @@ use crate::prelude::*;
 /// # let your_custom_message_handler = IgnoringMessageHandler {};
 /// // Create the onion messenger. This must use the same `keys_manager` as is passed to your
 /// // ChannelManager.
-/// let onion_messenger = OnionMessenger::new(&keys_manager, &keys_manager, logger, your_custom_message_handler);
+/// let onion_messenger = OnionMessenger::new(&keys_manager, &keys_manager, logger, &your_custom_message_handler);
 ///
 /// # struct YourCustomMessage {}
 /// impl Writeable for YourCustomMessage {