From 4624caf5a20b0329160e872259911a57eb451634 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Fri, 9 Aug 2024 00:13:41 +0000 Subject: [PATCH] Move `Payment{Hash,Preimage,Secret}` into a new crate `lightning-invoice` currently has a dependency on the entire `lightning` crate just because it wants to use some of the useful types from it. This is obviously backwards and leads to some awkwardness like the BOLT 11 invoice signing API in the `lightning` crate taking a `[u5]` rather than a `Bolt11Invoice`. This is the first step towards fixing that - moving the common types we need into a new `lightning-types` crate which both can depend on. Since we're using a new crate and can't depend on the existing `lightning` hex utility to implement `Display`, we also take this opportunity to switch to the new `Display` impl macro in `hex_conservative`. --- Cargo.toml | 1 + fuzz/src/chanmon_consistency.rs | 2 +- fuzz/src/full_stack.rs | 2 +- fuzz/src/router.rs | 2 +- lightning-types/Cargo.toml | 24 +++++++ lightning-types/src/lib.rs | 26 ++++++++ lightning-types/src/payment.rs | 115 ++++++++++++++++++++++++++++++++ lightning/Cargo.toml | 2 + lightning/src/lib.rs | 3 + lightning/src/ln/mod.rs | 2 +- lightning/src/ln/types.rs | 70 +------------------ 11 files changed, 176 insertions(+), 73 deletions(-) create mode 100644 lightning-types/Cargo.toml create mode 100644 lightning-types/src/lib.rs create mode 100644 lightning-types/src/payment.rs diff --git a/Cargo.toml b/Cargo.toml index 0aa7f7624..f7f4ba021 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,7 @@ resolver = "2" members = [ "lightning", + "lightning-types", "lightning-block-sync", "lightning-invoice", "lightning-net-tokio", diff --git a/fuzz/src/chanmon_consistency.rs b/fuzz/src/chanmon_consistency.rs index 7e95dc07f..06d2f6c84 100644 --- a/fuzz/src/chanmon_consistency.rs +++ b/fuzz/src/chanmon_consistency.rs @@ -56,7 +56,7 @@ use lightning::ln::msgs::{ self, ChannelMessageHandler, CommitmentUpdate, DecodeError, Init, UpdateAddHTLC, }; use lightning::ln::script::ShutdownScript; -use lightning::ln::{ChannelId, PaymentHash, PaymentPreimage, PaymentSecret}; +use lightning::ln::types::{ChannelId, PaymentHash, PaymentPreimage, PaymentSecret}; use lightning::offers::invoice::{BlindedPayInfo, UnsignedBolt12Invoice}; use lightning::offers::invoice_request::UnsignedInvoiceRequest; use lightning::onion_message::messenger::{Destination, MessageRouter, OnionMessagePath}; diff --git a/fuzz/src/full_stack.rs b/fuzz/src/full_stack.rs index 5499dc5e9..55a965217 100644 --- a/fuzz/src/full_stack.rs +++ b/fuzz/src/full_stack.rs @@ -49,7 +49,7 @@ use lightning::ln::peer_handler::{ IgnoringMessageHandler, MessageHandler, PeerManager, SocketDescriptor, }; use lightning::ln::script::ShutdownScript; -use lightning::ln::{ChannelId, PaymentHash, PaymentPreimage, PaymentSecret}; +use lightning::ln::types::{ChannelId, PaymentHash, PaymentPreimage, PaymentSecret}; use lightning::offers::invoice::{BlindedPayInfo, UnsignedBolt12Invoice}; use lightning::offers::invoice_request::UnsignedInvoiceRequest; use lightning::onion_message::messenger::{Destination, MessageRouter, OnionMessagePath}; diff --git a/fuzz/src/router.rs b/fuzz/src/router.rs index 034672fb2..96046f258 100644 --- a/fuzz/src/router.rs +++ b/fuzz/src/router.rs @@ -18,7 +18,7 @@ use lightning::ln::channel_state::{ChannelCounterparty, ChannelDetails, ChannelS use lightning::ln::channelmanager; use lightning::ln::features::{BlindedHopFeatures, Bolt12InvoiceFeatures}; use lightning::ln::msgs; -use lightning::ln::ChannelId; +use lightning::ln::types::ChannelId; use lightning::offers::invoice::BlindedPayInfo; use lightning::routing::gossip::{NetworkGraph, RoutingFees}; use lightning::routing::router::{ diff --git a/lightning-types/Cargo.toml b/lightning-types/Cargo.toml new file mode 100644 index 000000000..6bdd65d42 --- /dev/null +++ b/lightning-types/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "lightning-types" +version = "0.1.0" +authors = ["Matt Corallo"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/lightningdevkit/rust-lightning/" +description = """ +Basic types which are used in the lightning network +""" +edition = "2021" + +[package.metadata.docs.rs] +rustdoc-args = ["--cfg", "docsrs"] + +[features] + +[dependencies] +bitcoin = { version = "0.31", default-features = false } +# TODO: Once we switch to bitcoin 0.32 drop this explicit dep: +hex-conservative = { version = "0.2", default-features = false } +bech32 = { version = "0.9", default-features = false } + +[lints] +workspace = true diff --git a/lightning-types/src/lib.rs b/lightning-types/src/lib.rs new file mode 100644 index 000000000..0174bcc9b --- /dev/null +++ b/lightning-types/src/lib.rs @@ -0,0 +1,26 @@ +// This file is Copyright its original authors, visible in version control +// history. +// +// This file is licensed under the Apache License, Version 2.0 or the MIT license +// , at your option. +// You may not use this file except in accordance with one or both of these +// licenses. + +#![crate_name = "lightning_types"] + +//! Various types which are used in the lightning network. +//! +//! See the `lightning` crate for usage of these. + +#![cfg_attr(not(test), no_std)] +#![deny(missing_docs)] +#![forbid(unsafe_code)] +#![deny(rustdoc::broken_intra_doc_links)] +#![deny(rustdoc::private_intra_doc_links)] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] + +extern crate alloc; +extern crate core; + +pub mod payment; diff --git a/lightning-types/src/payment.rs b/lightning-types/src/payment.rs new file mode 100644 index 000000000..1c36f332d --- /dev/null +++ b/lightning-types/src/payment.rs @@ -0,0 +1,115 @@ +// This file is Copyright its original authors, visible in version control +// history. +// +// This file is licensed under the Apache License, Version 2.0 or the MIT license +// , at your option. +// You may not use this file except in accordance with one or both of these +// licenses. + +//! Types which describe payments in lightning. + +use alloc::vec::Vec; + +use core::borrow::Borrow; + +use bitcoin::hashes::{ + Hash as _, + sha256::Hash as Sha256, +}; + +// TODO: Once we switch to rust-bitcoin 0.32, import this as bitcoin::hex +use hex_conservative::display::impl_fmt_traits; + +/// The payment hash is the hash of the [`PaymentPreimage`] which is the value used to lock funds +/// in HTLCs while they transit the lightning network. +/// +/// This is not exported to bindings users as we just use [u8; 32] directly +#[derive(Hash, Copy, Clone, PartialEq, Eq, Ord, PartialOrd)] +pub struct PaymentHash(pub [u8; 32]); + +impl Borrow<[u8]> for PaymentHash { + fn borrow(&self) -> &[u8] { + &self.0[..] + } +} + +impl_fmt_traits! { + impl fmt_traits for PaymentHash { + const LENGTH: usize = 32; + } +} + +/// The payment preimage is the "secret key" which is used to claim the funds of an HTLC on-chain +/// or in a lightning channel. +/// +/// This is not exported to bindings users as we just use [u8; 32] directly +#[derive(Hash, Copy, Clone, PartialEq, Eq, Ord, PartialOrd)] +pub struct PaymentPreimage(pub [u8; 32]); + +impl Borrow<[u8]> for PaymentPreimage { + fn borrow(&self) -> &[u8] { + &self.0[..] + } +} + +impl_fmt_traits! { + impl fmt_traits for PaymentPreimage { + const LENGTH: usize = 32; + } +} + +/// Converts a `PaymentPreimage` into a `PaymentHash` by hashing the preimage with SHA256. +impl From for PaymentHash { + fn from(value: PaymentPreimage) -> Self { + PaymentHash(Sha256::hash(&value.0).to_byte_array()) + } +} + +/// The payment secret is used to authenticate the sender of an HTLC to the recipient and tie +/// multi-part HTLCs together into a single payment. +/// +/// This is not exported to bindings users as we just use [u8; 32] directly +#[derive(Hash, Copy, Clone, PartialEq, Eq, Ord, PartialOrd)] +pub struct PaymentSecret(pub [u8; 32]); + +impl Borrow<[u8]> for PaymentSecret { + fn borrow(&self) -> &[u8] { + &self.0[..] + } +} + +impl_fmt_traits! { + impl fmt_traits for PaymentSecret { + const LENGTH: usize = 32; + } +} + +use bech32::{Base32Len, FromBase32, ToBase32, WriteBase32, u5}; + +impl FromBase32 for PaymentSecret { + type Err = bech32::Error; + + fn from_base32(field_data: &[u5]) -> Result { + if field_data.len() != 52 { + return Err(bech32::Error::InvalidLength) + } else { + let data_bytes = Vec::::from_base32(field_data)?; + let mut payment_secret = [0; 32]; + payment_secret.copy_from_slice(&data_bytes); + Ok(PaymentSecret(payment_secret)) + } + } +} + +impl ToBase32 for PaymentSecret { + fn write_base32(&self, writer: &mut W) -> Result<(), ::Err> { + (&self.0[..]).write_base32(writer) + } +} + +impl Base32Len for PaymentSecret { + fn base32_len(&self) -> usize { + 52 + } +} diff --git a/lightning/Cargo.toml b/lightning/Cargo.toml index a0f1e4027..389ab087c 100644 --- a/lightning/Cargo.toml +++ b/lightning/Cargo.toml @@ -40,6 +40,8 @@ grind_signatures = [] default = ["std", "grind_signatures"] [dependencies] +lightning-types = { version = "0.1", path = "../lightning-types", default-features = false } + bech32 = { version = "0.9.1", default-features = false } bitcoin = { version = "0.31.2", default-features = false, features = ["secp-recovery"] } diff --git a/lightning/src/lib.rs b/lightning/src/lib.rs index 54652e320..54e394ced 100644 --- a/lightning/src/lib.rs +++ b/lightning/src/lib.rs @@ -61,6 +61,9 @@ compile_error!("Tests will always fail with cfg=fuzzing"); #[macro_use] extern crate alloc; + +extern crate lightning_types; + pub extern crate bitcoin; #[cfg(any(test, feature = "std"))] extern crate core; diff --git a/lightning/src/ln/mod.rs b/lightning/src/ln/mod.rs index 888044b7a..9bac19104 100644 --- a/lightning/src/ln/mod.rs +++ b/lightning/src/ln/mod.rs @@ -25,7 +25,7 @@ pub mod features; pub mod script; pub mod types; -pub use types::{ChannelId, PaymentHash, PaymentPreimage, PaymentSecret}; +pub use lightning_types::payment::{PaymentHash, PaymentPreimage, PaymentSecret}; #[cfg(fuzzing)] pub mod peer_channel_encryptor; diff --git a/lightning/src/ln/types.rs b/lightning/src/ln/types.rs index b81323978..d5ab05505 100644 --- a/lightning/src/ln/types.rs +++ b/lightning/src/ln/types.rs @@ -121,75 +121,7 @@ impl fmt::Display for ChannelId { } } - -/// The payment hash is the hash of the [`PaymentPreimage`] which is the value used to lock funds -/// in HTLCs while they transit the lightning network. -/// -/// This is not exported to bindings users as we just use [u8; 32] directly -#[derive(Hash, Copy, Clone, PartialEq, Eq, Debug, Ord, PartialOrd)] -pub struct PaymentHash(pub [u8; 32]); - -impl core::fmt::Display for PaymentHash { - fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - crate::util::logger::DebugBytes(&self.0).fmt(f) - } -} - -/// The payment preimage is the "secret key" which is used to claim the funds of an HTLC on-chain -/// or in a lightning channel. -/// -/// This is not exported to bindings users as we just use [u8; 32] directly -#[derive(Hash, Copy, Clone, PartialEq, Eq, Debug, Ord, PartialOrd)] -pub struct PaymentPreimage(pub [u8; 32]); - -impl core::fmt::Display for PaymentPreimage { - fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - crate::util::logger::DebugBytes(&self.0).fmt(f) - } -} - -/// Converts a `PaymentPreimage` into a `PaymentHash` by hashing the preimage with SHA256. -impl From for PaymentHash { - fn from(value: PaymentPreimage) -> Self { - PaymentHash(Sha256::hash(&value.0).to_byte_array()) - } -} - -/// The payment secret is used to authenticate the sender of an HTLC to the recipient and tie -/// multi-part HTLCs together into a single payment. -/// -/// This is not exported to bindings users as we just use [u8; 32] directly -#[derive(Hash, Copy, Clone, PartialEq, Eq, Debug, Ord, PartialOrd)] -pub struct PaymentSecret(pub [u8; 32]); - -use bech32::{Base32Len, FromBase32, ToBase32, WriteBase32, u5}; - -impl FromBase32 for PaymentSecret { - type Err = bech32::Error; - - fn from_base32(field_data: &[u5]) -> Result { - if field_data.len() != 52 { - return Err(bech32::Error::InvalidLength) - } else { - let data_bytes = Vec::::from_base32(field_data)?; - let mut payment_secret = [0; 32]; - payment_secret.copy_from_slice(&data_bytes); - Ok(PaymentSecret(payment_secret)) - } - } -} - -impl ToBase32 for PaymentSecret { - fn write_base32(&self, writer: &mut W) -> Result<(), ::Err> { - (&self.0[..]).write_base32(writer) - } -} - -impl Base32Len for PaymentSecret { - fn base32_len(&self) -> usize { - 52 - } -} +pub use lightning_types::payment::{PaymentHash, PaymentPreimage, PaymentSecret}; #[cfg(test)] mod tests { -- 2.39.5