mirror of
https://github.com/lightningdevkit/rust-lightning.git
synced 2025-02-24 23:08:36 +01:00
Merge pull request #3234 from TheBlueMatt/2024-08-lightning-dep-inv
Swap the dep order between `lightning` and `lightning-invoice`
This commit is contained in:
commit
398314b720
34 changed files with 1874 additions and 1603 deletions
|
@ -3,6 +3,7 @@ resolver = "2"
|
|||
|
||||
members = [
|
||||
"lightning",
|
||||
"lightning-types",
|
||||
"lightning-block-sync",
|
||||
"lightning-invoice",
|
||||
"lightning-net-tokio",
|
||||
|
|
|
@ -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};
|
||||
|
@ -71,6 +71,8 @@ use lightning::util::logger::Logger;
|
|||
use lightning::util::ser::{Readable, ReadableArgs, Writeable, Writer};
|
||||
use lightning::util::test_channel_signer::{EnforcementState, TestChannelSigner};
|
||||
|
||||
use lightning_invoice::RawBolt11Invoice;
|
||||
|
||||
use crate::utils::test_logger::{self, Output};
|
||||
use crate::utils::test_persister::TestPersister;
|
||||
|
||||
|
@ -79,7 +81,6 @@ use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature};
|
|||
use bitcoin::secp256k1::schnorr;
|
||||
use bitcoin::secp256k1::{self, Message, PublicKey, Scalar, Secp256k1, SecretKey};
|
||||
|
||||
use bech32::u5;
|
||||
use std::cmp::{self, Ordering};
|
||||
use std::io::Cursor;
|
||||
use std::mem;
|
||||
|
@ -332,7 +333,7 @@ impl NodeSigner for KeyProvider {
|
|||
}
|
||||
|
||||
fn sign_invoice(
|
||||
&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient,
|
||||
&self, _invoice: &RawBolt11Invoice, _recipient: Recipient,
|
||||
) -> Result<RecoverableSignature, ()> {
|
||||
unreachable!()
|
||||
}
|
||||
|
|
|
@ -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};
|
||||
|
@ -68,6 +68,8 @@ use lightning::util::logger::Logger;
|
|||
use lightning::util::ser::{Readable, ReadableArgs, Writeable};
|
||||
use lightning::util::test_channel_signer::{EnforcementState, TestChannelSigner};
|
||||
|
||||
use lightning_invoice::RawBolt11Invoice;
|
||||
|
||||
use crate::utils::test_logger;
|
||||
use crate::utils::test_persister::TestPersister;
|
||||
|
||||
|
@ -76,7 +78,6 @@ use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature};
|
|||
use bitcoin::secp256k1::schnorr;
|
||||
use bitcoin::secp256k1::{self, Message, PublicKey, Scalar, Secp256k1, SecretKey};
|
||||
|
||||
use bech32::u5;
|
||||
use std::cell::RefCell;
|
||||
use std::cmp;
|
||||
use std::convert::TryInto;
|
||||
|
@ -406,7 +407,7 @@ impl NodeSigner for KeyProvider {
|
|||
}
|
||||
|
||||
fn sign_invoice(
|
||||
&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient,
|
||||
&self, _invoice: &RawBolt11Invoice, _recipient: Recipient,
|
||||
) -> Result<RecoverableSignature, ()> {
|
||||
unreachable!()
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
// Imports that need to be added manually
|
||||
use bech32::u5;
|
||||
use bitcoin::script::ScriptBuf;
|
||||
use bitcoin::secp256k1::ecdh::SharedSecret;
|
||||
use bitcoin::secp256k1::ecdsa::RecoverableSignature;
|
||||
|
@ -27,6 +26,8 @@ use lightning::util::logger::Logger;
|
|||
use lightning::util::ser::{Readable, Writeable, Writer};
|
||||
use lightning::util::test_channel_signer::TestChannelSigner;
|
||||
|
||||
use lightning_invoice::RawBolt11Invoice;
|
||||
|
||||
use crate::utils::test_logger;
|
||||
|
||||
use std::io::{self, Cursor};
|
||||
|
@ -225,7 +226,7 @@ impl NodeSigner for KeyProvider {
|
|||
}
|
||||
|
||||
fn sign_invoice(
|
||||
&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient,
|
||||
&self, _invoice: &RawBolt11Invoice, _recipient: Recipient,
|
||||
) -> Result<RecoverableSignature, ()> {
|
||||
unreachable!()
|
||||
}
|
||||
|
|
|
@ -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::{
|
||||
|
|
|
@ -16,18 +16,17 @@ rustdoc-args = ["--cfg", "docsrs"]
|
|||
|
||||
[features]
|
||||
default = ["std"]
|
||||
no-std = ["lightning/no-std"]
|
||||
std = ["bitcoin/std", "lightning/std", "bech32/std"]
|
||||
no-std = ["bitcoin/no-std"]
|
||||
std = ["bitcoin/std", "bech32/std"]
|
||||
|
||||
[dependencies]
|
||||
bech32 = { version = "0.9.1", default-features = false }
|
||||
lightning = { version = "0.0.123-beta", path = "../lightning", default-features = false }
|
||||
lightning-types = { version = "0.1", path = "../lightning-types", default-features = false }
|
||||
secp256k1 = { version = "0.28.0", default-features = false, features = ["recovery", "alloc"] }
|
||||
serde = { version = "1.0.118", optional = true }
|
||||
bitcoin = { version = "0.31.2", default-features = false }
|
||||
|
||||
[dev-dependencies]
|
||||
lightning = { version = "0.0.123-beta", path = "../lightning", default-features = false, features = ["_test_utils"] }
|
||||
serde_json = { version = "1"}
|
||||
hashbrown = { version = "0.13", default-features = false }
|
||||
|
||||
|
|
|
@ -14,9 +14,8 @@ use bitcoin::{PubkeyHash, ScriptHash, WitnessVersion};
|
|||
use bitcoin::hashes::Hash;
|
||||
use bitcoin::hashes::sha256;
|
||||
use crate::prelude::*;
|
||||
use lightning::ln::types::PaymentSecret;
|
||||
use lightning::routing::gossip::RoutingFees;
|
||||
use lightning::routing::router::{RouteHint, RouteHintHop};
|
||||
use lightning_types::payment::PaymentSecret;
|
||||
use lightning_types::routing::{RoutingFees, RouteHint, RouteHintHop};
|
||||
|
||||
use secp256k1::ecdsa::{RecoveryId, RecoverableSignature};
|
||||
use secp256k1::PublicKey;
|
||||
|
@ -918,8 +917,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn test_parse_route() {
|
||||
use lightning::routing::gossip::RoutingFees;
|
||||
use lightning::routing::router::{RouteHint, RouteHintHop};
|
||||
use lightning_types::routing::{RoutingFees, RouteHint, RouteHintHop};
|
||||
use crate::PrivateRoute;
|
||||
use bech32::FromBase32;
|
||||
|
||||
|
@ -974,7 +972,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn test_payment_secret_and_features_de_and_ser() {
|
||||
use lightning::ln::features::Bolt11InvoiceFeatures;
|
||||
use lightning_types::features::Bolt11InvoiceFeatures;
|
||||
use secp256k1::ecdsa::{RecoveryId, RecoverableSignature};
|
||||
use crate::TaggedField::*;
|
||||
use crate::{SiPrefix, SignedRawBolt11Invoice, Bolt11InvoiceSignature, RawBolt11Invoice, RawHrp, RawDataPart,
|
||||
|
|
|
@ -25,11 +25,8 @@
|
|||
#[cfg(not(any(feature = "std", feature = "no-std")))]
|
||||
compile_error!("at least one of the `std` or `no-std` features must be enabled");
|
||||
|
||||
pub mod payment;
|
||||
pub mod utils;
|
||||
|
||||
extern crate bech32;
|
||||
#[macro_use] extern crate lightning;
|
||||
extern crate lightning_types;
|
||||
extern crate secp256k1;
|
||||
extern crate alloc;
|
||||
#[cfg(any(test, feature = "std"))]
|
||||
|
@ -40,12 +37,11 @@ extern crate serde;
|
|||
#[cfg(feature = "std")]
|
||||
use std::time::SystemTime;
|
||||
|
||||
use bech32::u5;
|
||||
use bech32::{FromBase32, u5};
|
||||
use bitcoin::{Address, Network, PubkeyHash, ScriptHash, WitnessProgram, WitnessVersion};
|
||||
use bitcoin::address::Payload;
|
||||
use bitcoin::hashes::{Hash, sha256};
|
||||
use lightning::ln::features::Bolt11InvoiceFeatures;
|
||||
use lightning::util::invoice::construct_invoice_preimage;
|
||||
use lightning_types::features::Bolt11InvoiceFeatures;
|
||||
|
||||
use secp256k1::PublicKey;
|
||||
use secp256k1::{Message, Secp256k1};
|
||||
|
@ -64,12 +60,10 @@ use core::str;
|
|||
use serde::{Deserialize, Deserializer,Serialize, Serializer, de::Error};
|
||||
|
||||
#[doc(no_inline)]
|
||||
pub use lightning::ln::types::PaymentSecret;
|
||||
pub use lightning_types::payment::PaymentSecret;
|
||||
#[doc(no_inline)]
|
||||
pub use lightning::routing::router::{RouteHint, RouteHintHop};
|
||||
#[doc(no_inline)]
|
||||
pub use lightning::routing::gossip::RoutingFees;
|
||||
use lightning::util::string::UntrustedString;
|
||||
pub use lightning_types::routing::{RoutingFees, RouteHint, RouteHintHop};
|
||||
use lightning_types::string::UntrustedString;
|
||||
|
||||
mod de;
|
||||
mod ser;
|
||||
|
@ -139,11 +133,9 @@ pub const DEFAULT_EXPIRY_TIME: u64 = 3600;
|
|||
|
||||
/// Default minimum final CLTV expiry as defined by [BOLT 11].
|
||||
///
|
||||
/// Note that this is *not* the same value as rust-lightning's minimum CLTV expiry, which is
|
||||
/// provided in [`MIN_FINAL_CLTV_EXPIRY_DELTA`].
|
||||
/// Note that this is *not* the same value as rust-lightning's minimum CLTV expiry.
|
||||
///
|
||||
/// [BOLT 11]: https://github.com/lightning/bolts/blob/master/11-payment-encoding.md
|
||||
/// [`MIN_FINAL_CLTV_EXPIRY_DELTA`]: lightning::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY_DELTA
|
||||
pub const DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA: u64 = 18;
|
||||
|
||||
/// Builder for [`Bolt11Invoice`]s. It's the most convenient and advised way to use this library. It
|
||||
|
@ -151,7 +143,6 @@ pub const DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA: u64 = 18;
|
|||
///
|
||||
/// ```
|
||||
/// extern crate secp256k1;
|
||||
/// extern crate lightning;
|
||||
/// extern crate lightning_invoice;
|
||||
/// extern crate bitcoin;
|
||||
///
|
||||
|
@ -161,7 +152,7 @@ pub const DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA: u64 = 18;
|
|||
/// use secp256k1::Secp256k1;
|
||||
/// use secp256k1::SecretKey;
|
||||
///
|
||||
/// use lightning::ln::types::PaymentSecret;
|
||||
/// use lightning_types::payment::PaymentSecret;
|
||||
///
|
||||
/// use lightning_invoice::{Currency, InvoiceBuilder};
|
||||
///
|
||||
|
@ -970,7 +961,23 @@ macro_rules! find_all_extract {
|
|||
impl RawBolt11Invoice {
|
||||
/// Hash the HRP as bytes and signatureless data part.
|
||||
fn hash_from_parts(hrp_bytes: &[u8], data_without_signature: &[u5]) -> [u8; 32] {
|
||||
let preimage = construct_invoice_preimage(hrp_bytes, data_without_signature);
|
||||
let mut preimage = Vec::<u8>::from(hrp_bytes);
|
||||
|
||||
let mut data_part = Vec::from(data_without_signature);
|
||||
let overhang = (data_part.len() * 5) % 8;
|
||||
if overhang > 0 {
|
||||
// add padding if data does not end at a byte boundary
|
||||
data_part.push(u5::try_from_u8(0).unwrap());
|
||||
|
||||
// if overhang is in (1..3) we need to add u5(0) padding two times
|
||||
if overhang < 3 {
|
||||
data_part.push(u5::try_from_u8(0).unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
preimage.extend_from_slice(&Vec::<u8>::from_base32(&data_part)
|
||||
.expect("No padding error may occur due to appended zero above."));
|
||||
|
||||
let mut hash: [u8; 32] = Default::default();
|
||||
hash.copy_from_slice(&sha256::Hash::hash(&preimage)[..]);
|
||||
hash
|
||||
|
@ -1636,15 +1643,12 @@ pub enum CreationError {
|
|||
/// The supplied millisatoshi amount was greater than the total bitcoin supply.
|
||||
InvalidAmount,
|
||||
|
||||
/// Route hints were required for this invoice and were missing. Applies to
|
||||
/// [phantom invoices].
|
||||
///
|
||||
/// [phantom invoices]: crate::utils::create_phantom_invoice
|
||||
// TODO: These two errors are really errors with things in the `lightning` crate and thus
|
||||
// shouldn't live here.
|
||||
/// Route hints were required for this invoice and were missing.
|
||||
MissingRouteHints,
|
||||
|
||||
/// The provided `min_final_cltv_expiry_delta` was less than [`MIN_FINAL_CLTV_EXPIRY_DELTA`].
|
||||
///
|
||||
/// [`MIN_FINAL_CLTV_EXPIRY_DELTA`]: lightning::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY_DELTA
|
||||
/// The provided `min_final_cltv_expiry_delta` was less than rust-lightning's minimum.
|
||||
MinFinalCltvExpiryDeltaTooShort,
|
||||
}
|
||||
|
||||
|
@ -1877,14 +1881,14 @@ mod test {
|
|||
#[test]
|
||||
fn test_check_feature_bits() {
|
||||
use crate::TaggedField::*;
|
||||
use lightning::ln::features::Bolt11InvoiceFeatures;
|
||||
use lightning_types::features::Bolt11InvoiceFeatures;
|
||||
use secp256k1::Secp256k1;
|
||||
use secp256k1::SecretKey;
|
||||
use crate::{Bolt11Invoice, RawBolt11Invoice, RawHrp, RawDataPart, Currency, Sha256, PositiveTimestamp,
|
||||
Bolt11SemanticError};
|
||||
|
||||
let private_key = SecretKey::from_slice(&[42; 32]).unwrap();
|
||||
let payment_secret = lightning::ln::types::PaymentSecret([21; 32]);
|
||||
let payment_secret = lightning_types::payment::PaymentSecret([21; 32]);
|
||||
let invoice_template = RawBolt11Invoice {
|
||||
hrp: RawHrp {
|
||||
currency: Currency::Bitcoin,
|
||||
|
@ -1998,7 +2002,7 @@ mod test {
|
|||
#[test]
|
||||
fn test_builder_fail() {
|
||||
use crate::*;
|
||||
use lightning::routing::router::RouteHintHop;
|
||||
use lightning_types::routing::RouteHintHop;
|
||||
use std::iter::FromIterator;
|
||||
use secp256k1::PublicKey;
|
||||
|
||||
|
@ -2052,7 +2056,7 @@ mod test {
|
|||
#[test]
|
||||
fn test_builder_ok() {
|
||||
use crate::*;
|
||||
use lightning::routing::router::RouteHintHop;
|
||||
use lightning_types::routing::RouteHintHop;
|
||||
use secp256k1::Secp256k1;
|
||||
use secp256k1::{SecretKey, PublicKey};
|
||||
use std::time::Duration;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
extern crate bech32;
|
||||
extern crate lightning;
|
||||
extern crate lightning_invoice;
|
||||
extern crate secp256k1;
|
||||
|
||||
|
|
25
lightning-types/Cargo.toml
Normal file
25
lightning-types/Cargo.toml
Normal file
|
@ -0,0 +1,25 @@
|
|||
[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]
|
||||
_test_utils = []
|
||||
|
||||
[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
|
1359
lightning-types/src/features.rs
Normal file
1359
lightning-types/src/features.rs
Normal file
File diff suppressed because it is too large
Load diff
29
lightning-types/src/lib.rs
Normal file
29
lightning-types/src/lib.rs
Normal file
|
@ -0,0 +1,29 @@
|
|||
// This file is Copyright its original authors, visible in version control
|
||||
// history.
|
||||
//
|
||||
// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
|
||||
// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 features;
|
||||
pub mod payment;
|
||||
pub mod routing;
|
||||
pub mod string;
|
112
lightning-types/src/payment.rs
Normal file
112
lightning-types/src/payment.rs
Normal file
|
@ -0,0 +1,112 @@
|
|||
// This file is Copyright its original authors, visible in version control
|
||||
// history.
|
||||
//
|
||||
// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
|
||||
// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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::{sha256::Hash as Sha256, Hash as _};
|
||||
|
||||
// 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<PaymentPreimage> 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::{u5, Base32Len, FromBase32, ToBase32, WriteBase32};
|
||||
|
||||
impl FromBase32 for PaymentSecret {
|
||||
type Err = bech32::Error;
|
||||
|
||||
fn from_base32(field_data: &[u5]) -> Result<PaymentSecret, bech32::Error> {
|
||||
if field_data.len() != 52 {
|
||||
return Err(bech32::Error::InvalidLength);
|
||||
} else {
|
||||
let data_bytes = Vec::<u8>::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<W: WriteBase32>(&self, writer: &mut W) -> Result<(), <W as WriteBase32>::Err> {
|
||||
(&self.0[..]).write_base32(writer)
|
||||
}
|
||||
}
|
||||
|
||||
impl Base32Len for PaymentSecret {
|
||||
fn base32_len(&self) -> usize {
|
||||
52
|
||||
}
|
||||
}
|
50
lightning-types/src/routing.rs
Normal file
50
lightning-types/src/routing.rs
Normal file
|
@ -0,0 +1,50 @@
|
|||
// This file is Copyright its original authors, visible in version control
|
||||
// history.
|
||||
//
|
||||
// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
|
||||
// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
|
||||
// You may not use this file except in accordance with one or both of these
|
||||
// licenses.
|
||||
|
||||
//! Various types which describe routes or information about partial routes within the lightning
|
||||
//! network.
|
||||
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use bitcoin::secp256k1::PublicKey;
|
||||
|
||||
/// Fees for routing via a given channel or a node
|
||||
#[derive(Eq, PartialEq, Copy, Clone, Debug, Hash, Ord, PartialOrd)]
|
||||
pub struct RoutingFees {
|
||||
/// Flat routing fee in millisatoshis.
|
||||
pub base_msat: u32,
|
||||
/// Liquidity-based routing fee in millionths of a routed amount.
|
||||
/// In other words, 10000 is 1%.
|
||||
pub proportional_millionths: u32,
|
||||
}
|
||||
|
||||
/// A list of hops along a payment path terminating with a channel to the recipient.
|
||||
#[derive(Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub struct RouteHint(pub Vec<RouteHintHop>);
|
||||
|
||||
/// A channel descriptor for a hop along a payment path.
|
||||
///
|
||||
/// While this generally comes from BOLT 11's `r` field, this struct includes more fields than are
|
||||
/// available in BOLT 11. Thus, encoding and decoding this via `lightning-invoice` is lossy, as
|
||||
/// fields not supported in BOLT 11 will be stripped.
|
||||
#[derive(Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub struct RouteHintHop {
|
||||
/// The node_id of the non-target end of the route
|
||||
pub src_node_id: PublicKey,
|
||||
/// The short_channel_id of this channel
|
||||
pub short_channel_id: u64,
|
||||
/// The fees which must be paid to use this channel
|
||||
pub fees: RoutingFees,
|
||||
/// The difference in CLTV values between this node and the next node.
|
||||
pub cltv_expiry_delta: u16,
|
||||
/// The minimum value, in msat, which must be relayed to the next hop.
|
||||
pub htlc_minimum_msat: Option<u64>,
|
||||
/// The maximum value in msat available for routing with a single HTLC.
|
||||
pub htlc_maximum_msat: Option<u64>,
|
||||
}
|
|
@ -9,31 +9,13 @@
|
|||
|
||||
//! Utilities for strings.
|
||||
|
||||
use alloc::string::String;
|
||||
use core::fmt;
|
||||
use crate::io::{self, Read};
|
||||
use crate::ln::msgs;
|
||||
use crate::util::ser::{Writeable, Writer, Readable};
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use crate::prelude::*;
|
||||
|
||||
/// Struct to `Display` fields in a safe way using `PrintableString`
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
|
||||
pub struct UntrustedString(pub String);
|
||||
|
||||
impl Writeable for UntrustedString {
|
||||
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
|
||||
self.0.write(w)
|
||||
}
|
||||
}
|
||||
|
||||
impl Readable for UntrustedString {
|
||||
fn read<R: Read>(r: &mut R) -> Result<Self, msgs::DecodeError> {
|
||||
let s: String = Readable::read(r)?;
|
||||
Ok(Self(s))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for UntrustedString {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
PrintableString(&self.0).fmt(f)
|
|
@ -17,7 +17,7 @@ rustdoc-args = ["--cfg", "docsrs"]
|
|||
|
||||
[features]
|
||||
# Internal test utilities exposed to other repo crates
|
||||
_test_utils = ["regex", "bitcoin/bitcoinconsensus"]
|
||||
_test_utils = ["regex", "bitcoin/bitcoinconsensus", "lightning-types/_test_utils"]
|
||||
# Unlog messages superior at targeted level.
|
||||
max_level_off = []
|
||||
max_level_error = []
|
||||
|
@ -31,8 +31,8 @@ unsafe_revoked_tx_signing = []
|
|||
# Override signing to not include randomness when generating signatures for test vectors.
|
||||
_test_vectors = []
|
||||
|
||||
no-std = ["hashbrown", "possiblyrandom", "bitcoin/no-std", "core2/alloc", "libm"]
|
||||
std = ["bitcoin/std", "bech32/std"]
|
||||
no-std = ["hashbrown", "possiblyrandom", "bitcoin/no-std", "lightning-invoice/no-std", "core2/alloc", "libm"]
|
||||
std = ["bitcoin/std", "bech32/std", "lightning-invoice/std"]
|
||||
|
||||
# Generates low-r bitcoin signatures, which saves 1 byte in 50% of the cases
|
||||
grind_signatures = []
|
||||
|
@ -40,6 +40,9 @@ grind_signatures = []
|
|||
default = ["std", "grind_signatures"]
|
||||
|
||||
[dependencies]
|
||||
lightning-types = { version = "0.1", path = "../lightning-types", default-features = false }
|
||||
lightning-invoice = { version = "0.31.0-beta", path = "../lightning-invoice", default-features = false }
|
||||
|
||||
bech32 = { version = "0.9.1", default-features = false }
|
||||
bitcoin = { version = "0.31.2", default-features = false, features = ["secp-recovery"] }
|
||||
|
||||
|
@ -53,6 +56,7 @@ libm = { version = "0.2", optional = true, default-features = false }
|
|||
|
||||
[dev-dependencies]
|
||||
regex = "1.5.6"
|
||||
lightning-types = { version = "0.1", path = "../lightning-types", features = ["_test_utils"] }
|
||||
|
||||
[dev-dependencies.bitcoin]
|
||||
version = "0.31.2"
|
||||
|
|
|
@ -93,7 +93,7 @@ pub(crate) fn verify_channel_type_features(channel_type_features: &Option<Channe
|
|||
supported_feature_set |= additional_permitted_features;
|
||||
}
|
||||
|
||||
if !features.is_subset(&supported_feature_set) {
|
||||
if features.requires_unknown_bits_from(&supported_feature_set) {
|
||||
return Err(DecodeError::UnknownRequiredFeature);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -9,12 +9,12 @@
|
|||
|
||||
//! Convenient utilities for paying Lightning invoices.
|
||||
|
||||
use crate::Bolt11Invoice;
|
||||
use bitcoin::hashes::Hash;
|
||||
use lightning_invoice::Bolt11Invoice;
|
||||
|
||||
use lightning::ln::types::PaymentHash;
|
||||
use lightning::ln::channelmanager::RecipientOnionFields;
|
||||
use lightning::routing::router::{PaymentParameters, RouteParameters};
|
||||
use crate::ln::channelmanager::RecipientOnionFields;
|
||||
use crate::ln::types::PaymentHash;
|
||||
use crate::routing::router::{PaymentParameters, RouteParameters};
|
||||
|
||||
/// Builds the necessary parameters to pay or pre-flight probe the given zero-amount
|
||||
/// [`Bolt11Invoice`] using [`ChannelManager::send_payment`] or
|
||||
|
@ -26,10 +26,11 @@ use lightning::routing::router::{PaymentParameters, RouteParameters};
|
|||
/// Will always succeed unless the invoice has an amount specified, in which case
|
||||
/// [`payment_parameters_from_invoice`] should be used.
|
||||
///
|
||||
/// [`ChannelManager::send_payment`]: lightning::ln::channelmanager::ChannelManager::send_payment
|
||||
/// [`ChannelManager::send_preflight_probes`]: lightning::ln::channelmanager::ChannelManager::send_preflight_probes
|
||||
pub fn payment_parameters_from_zero_amount_invoice(invoice: &Bolt11Invoice, amount_msat: u64)
|
||||
-> Result<(PaymentHash, RecipientOnionFields, RouteParameters), ()> {
|
||||
/// [`ChannelManager::send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment
|
||||
/// [`ChannelManager::send_preflight_probes`]: crate::ln::channelmanager::ChannelManager::send_preflight_probes
|
||||
pub fn payment_parameters_from_zero_amount_invoice(
|
||||
invoice: &Bolt11Invoice, amount_msat: u64,
|
||||
) -> Result<(PaymentHash, RecipientOnionFields, RouteParameters), ()> {
|
||||
if invoice.amount_milli_satoshis().is_some() {
|
||||
Err(())
|
||||
} else {
|
||||
|
@ -46,10 +47,11 @@ pub fn payment_parameters_from_zero_amount_invoice(invoice: &Bolt11Invoice, amou
|
|||
/// Will always succeed unless the invoice has no amount specified, in which case
|
||||
/// [`payment_parameters_from_zero_amount_invoice`] should be used.
|
||||
///
|
||||
/// [`ChannelManager::send_payment`]: lightning::ln::channelmanager::ChannelManager::send_payment
|
||||
/// [`ChannelManager::send_preflight_probes`]: lightning::ln::channelmanager::ChannelManager::send_preflight_probes
|
||||
pub fn payment_parameters_from_invoice(invoice: &Bolt11Invoice)
|
||||
-> Result<(PaymentHash, RecipientOnionFields, RouteParameters), ()> {
|
||||
/// [`ChannelManager::send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment
|
||||
/// [`ChannelManager::send_preflight_probes`]: crate::ln::channelmanager::ChannelManager::send_preflight_probes
|
||||
pub fn payment_parameters_from_invoice(
|
||||
invoice: &Bolt11Invoice,
|
||||
) -> Result<(PaymentHash, RecipientOnionFields, RouteParameters), ()> {
|
||||
if let Some(amount_msat) = invoice.amount_milli_satoshis() {
|
||||
Ok(params_from_invoice(invoice, amount_msat))
|
||||
} else {
|
||||
|
@ -57,18 +59,20 @@ pub fn payment_parameters_from_invoice(invoice: &Bolt11Invoice)
|
|||
}
|
||||
}
|
||||
|
||||
fn params_from_invoice(invoice: &Bolt11Invoice, amount_msat: u64)
|
||||
-> (PaymentHash, RecipientOnionFields, RouteParameters) {
|
||||
fn params_from_invoice(
|
||||
invoice: &Bolt11Invoice, amount_msat: u64,
|
||||
) -> (PaymentHash, RecipientOnionFields, RouteParameters) {
|
||||
let payment_hash = PaymentHash((*invoice.payment_hash()).to_byte_array());
|
||||
|
||||
let mut recipient_onion = RecipientOnionFields::secret_only(*invoice.payment_secret());
|
||||
recipient_onion.payment_metadata = invoice.payment_metadata().map(|v| v.clone());
|
||||
|
||||
let mut payment_params = PaymentParameters::from_node_id(
|
||||
invoice.recover_payee_pub_key(),
|
||||
invoice.min_final_cltv_expiry_delta() as u32
|
||||
)
|
||||
.with_route_hints(invoice.route_hints()).unwrap();
|
||||
invoice.recover_payee_pub_key(),
|
||||
invoice.min_final_cltv_expiry_delta() as u32,
|
||||
)
|
||||
.with_route_hints(invoice.route_hints())
|
||||
.unwrap();
|
||||
if let Some(expiry) = invoice.expires_at() {
|
||||
payment_params = payment_params.with_expiry_time(expiry.as_secs());
|
||||
}
|
||||
|
@ -83,19 +87,18 @@ fn params_from_invoice(invoice: &Bolt11Invoice, amount_msat: u64)
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{InvoiceBuilder, Currency};
|
||||
use crate::ln::types::PaymentSecret;
|
||||
use crate::routing::router::Payee;
|
||||
use bitcoin::hashes::sha256::Hash as Sha256;
|
||||
use lightning::ln::types::PaymentSecret;
|
||||
use lightning::routing::router::Payee;
|
||||
use secp256k1::{SecretKey, PublicKey, Secp256k1};
|
||||
use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
|
||||
use core::time::Duration;
|
||||
use lightning_invoice::{Currency, InvoiceBuilder};
|
||||
#[cfg(feature = "std")]
|
||||
use std::time::SystemTime;
|
||||
|
||||
fn duration_since_epoch() -> Duration {
|
||||
#[cfg(feature = "std")]
|
||||
let duration_since_epoch =
|
||||
SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
|
||||
let duration_since_epoch = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
|
||||
#[cfg(not(feature = "std"))]
|
||||
let duration_since_epoch = Duration::from_secs(1234567);
|
||||
duration_since_epoch
|
||||
|
@ -115,9 +118,7 @@ mod tests {
|
|||
.duration_since_epoch(duration_since_epoch())
|
||||
.min_final_cltv_expiry_delta(144)
|
||||
.amount_milli_satoshis(128)
|
||||
.build_signed(|hash| {
|
||||
secp_ctx.sign_ecdsa_recoverable(hash, &private_key)
|
||||
})
|
||||
.build_signed(|hash| secp_ctx.sign_ecdsa_recoverable(hash, &private_key))
|
||||
.unwrap();
|
||||
|
||||
assert!(payment_parameters_from_zero_amount_invoice(&invoice, 42).is_err());
|
||||
|
@ -147,14 +148,13 @@ mod tests {
|
|||
.payment_secret(PaymentSecret([0; 32]))
|
||||
.duration_since_epoch(duration_since_epoch())
|
||||
.min_final_cltv_expiry_delta(144)
|
||||
.build_signed(|hash| {
|
||||
secp_ctx.sign_ecdsa_recoverable(hash, &private_key)
|
||||
})
|
||||
.unwrap();
|
||||
.build_signed(|hash| secp_ctx.sign_ecdsa_recoverable(hash, &private_key))
|
||||
.unwrap();
|
||||
|
||||
assert!(payment_parameters_from_invoice(&invoice).is_err());
|
||||
|
||||
let (hash, onion, params) = payment_parameters_from_zero_amount_invoice(&invoice, 42).unwrap();
|
||||
let (hash, onion, params) =
|
||||
payment_parameters_from_zero_amount_invoice(&invoice, 42).unwrap();
|
||||
assert_eq!(&hash.0[..], &payment_hash[..]);
|
||||
assert_eq!(onion.payment_secret, Some(PaymentSecret([0; 32])));
|
||||
assert_eq!(params.final_value_msat, 42);
|
||||
|
@ -169,10 +169,10 @@ mod tests {
|
|||
#[test]
|
||||
#[cfg(feature = "std")]
|
||||
fn payment_metadata_end_to_end() {
|
||||
use lightning::events::Event;
|
||||
use lightning::ln::channelmanager::{Retry, PaymentId};
|
||||
use lightning::ln::msgs::ChannelMessageHandler;
|
||||
use lightning::ln::functional_test_utils::*;
|
||||
use crate::events::Event;
|
||||
use crate::ln::channelmanager::{PaymentId, Retry};
|
||||
use crate::ln::functional_test_utils::*;
|
||||
use crate::ln::msgs::ChannelMessageHandler;
|
||||
// Test that a payment metadata read from an invoice passed to `pay_invoice` makes it all
|
||||
// the way out through the `PaymentClaimable` event.
|
||||
let chanmon_cfgs = create_chanmon_cfgs(2);
|
||||
|
@ -186,6 +186,8 @@ mod tests {
|
|||
let (payment_hash, payment_secret) =
|
||||
nodes[1].node.create_inbound_payment(None, 7200, None).unwrap();
|
||||
|
||||
let secp_ctx = Secp256k1::new();
|
||||
let node_secret = nodes[1].keys_manager.backing.get_node_secret_key();
|
||||
let invoice = InvoiceBuilder::new(Currency::Bitcoin)
|
||||
.description("test".into())
|
||||
.payment_hash(Sha256::from_slice(&payment_hash.0).unwrap())
|
||||
|
@ -194,14 +196,14 @@ mod tests {
|
|||
.min_final_cltv_expiry_delta(144)
|
||||
.amount_milli_satoshis(50_000)
|
||||
.payment_metadata(payment_metadata.clone())
|
||||
.build_signed(|hash| {
|
||||
Secp256k1::new().sign_ecdsa_recoverable(hash,
|
||||
&nodes[1].keys_manager.backing.get_node_secret_key())
|
||||
})
|
||||
.build_signed(|hash| secp_ctx.sign_ecdsa_recoverable(hash, &node_secret))
|
||||
.unwrap();
|
||||
|
||||
let (hash, onion, params) = payment_parameters_from_invoice(&invoice).unwrap();
|
||||
nodes[0].node.send_payment(hash, onion, PaymentId(hash.0), params, Retry::Attempts(0)).unwrap();
|
||||
nodes[0]
|
||||
.node
|
||||
.send_payment(hash, onion, PaymentId(hash.0), params, Retry::Attempts(0))
|
||||
.unwrap();
|
||||
check_added_monitors(&nodes[0], 1);
|
||||
let send_event = SendEvent::from_node(&nodes[0]);
|
||||
nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &send_event.msgs[0]);
|
||||
|
@ -215,7 +217,7 @@ mod tests {
|
|||
Event::PaymentClaimable { onion_fields, .. } => {
|
||||
assert_eq!(Some(payment_metadata), onion_fields.unwrap().payment_metadata);
|
||||
},
|
||||
_ => panic!("Unexpected event")
|
||||
_ => panic!("Unexpected event"),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -772,10 +772,12 @@ pub(crate) fn legacy_deserialization_prevention_marker_for_channel_type_features
|
|||
legacy_version_bit_set.set_scid_privacy_required();
|
||||
legacy_version_bit_set.set_zero_conf_required();
|
||||
|
||||
if features.is_subset(&legacy_version_bit_set) {
|
||||
None
|
||||
} else {
|
||||
debug_assert!(!legacy_version_bit_set.supports_any_optional_bits());
|
||||
debug_assert!(!features.supports_any_optional_bits());
|
||||
if features.requires_unknown_bits_from(&legacy_version_bit_set) {
|
||||
Some(())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1877,7 +1877,8 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
|
|||
}
|
||||
|
||||
let channel_type = get_initial_channel_type(&config, their_features);
|
||||
debug_assert!(channel_type.is_subset(&channelmanager::provided_channel_type_features(&config)));
|
||||
debug_assert!(!channel_type.supports_any_optional_bits());
|
||||
debug_assert!(!channel_type.requires_unknown_bits_from(&channelmanager::provided_channel_type_features(&config)));
|
||||
|
||||
let (commitment_conf_target, anchor_outputs_value_msat) = if channel_type.supports_anchors_zero_fee_htlc_tx() {
|
||||
(ConfirmationTarget::AnchorChannelFee, ANCHOR_OUTPUT_VALUE_SATOSHI * 2 * 1000)
|
||||
|
@ -7967,7 +7968,7 @@ pub(super) fn channel_type_from_open_channel(
|
|||
return Err(ChannelError::close("Channel Type was not understood - we require static remote key".to_owned()));
|
||||
}
|
||||
// Make sure we support all of the features behind the channel type.
|
||||
if !channel_type.is_subset(our_supported_features) {
|
||||
if channel_type.requires_unknown_bits_from(&our_supported_features) {
|
||||
return Err(ChannelError::close("Channel Type contains unsupported features".to_owned()));
|
||||
}
|
||||
let announced_channel = if (common_fields.channel_flags & 1) == 1 { true } else { false };
|
||||
|
@ -9355,7 +9356,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
|
|||
}
|
||||
|
||||
let chan_features = channel_type.as_ref().unwrap();
|
||||
if !chan_features.is_subset(our_supported_features) {
|
||||
if chan_features.supports_any_optional_bits() || chan_features.requires_unknown_bits_from(&our_supported_features) {
|
||||
// If the channel was written by a new version and negotiated with features we don't
|
||||
// understand yet, refuse to read it.
|
||||
return Err(DecodeError::UnknownRequiredFeature);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,22 +1,23 @@
|
|||
//! Convenient utilities to create an invoice.
|
||||
|
||||
use crate::{Bolt11Invoice, CreationError, Currency, InvoiceBuilder, SignOrCreationError};
|
||||
use lightning_invoice::{Bolt11Invoice, CreationError, Currency, InvoiceBuilder, SignOrCreationError};
|
||||
use lightning_invoice::{Description, Bolt11InvoiceDescription, Sha256};
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
use crate::{prelude::*, Description, Bolt11InvoiceDescription, Sha256};
|
||||
use bech32::ToBase32;
|
||||
use bitcoin::hashes::Hash;
|
||||
use lightning::chain;
|
||||
use lightning::chain::chaininterface::{BroadcasterInterface, FeeEstimator};
|
||||
use lightning::sign::{Recipient, NodeSigner, SignerProvider, EntropySource};
|
||||
use lightning::ln::types::{PaymentHash, PaymentSecret};
|
||||
use lightning::ln::channel_state::ChannelDetails;
|
||||
use lightning::ln::channelmanager::{ChannelManager, MIN_FINAL_CLTV_EXPIRY_DELTA};
|
||||
use lightning::ln::channelmanager::{PhantomRouteHints, MIN_CLTV_EXPIRY_DELTA};
|
||||
use lightning::ln::inbound_payment::{create, create_from_hash, ExpandedKey};
|
||||
use lightning::routing::gossip::RoutingFees;
|
||||
use lightning::routing::router::{RouteHint, RouteHintHop, Router};
|
||||
use lightning::util::logger::{Logger, Record};
|
||||
use secp256k1::PublicKey;
|
||||
use crate::chain;
|
||||
use crate::chain::chaininterface::{BroadcasterInterface, FeeEstimator};
|
||||
use crate::sign::{Recipient, NodeSigner, SignerProvider, EntropySource};
|
||||
use crate::ln::types::{PaymentHash, PaymentSecret};
|
||||
use crate::ln::channel_state::ChannelDetails;
|
||||
use crate::ln::channelmanager::{ChannelManager, MIN_FINAL_CLTV_EXPIRY_DELTA};
|
||||
use crate::ln::channelmanager::{PhantomRouteHints, MIN_CLTV_EXPIRY_DELTA};
|
||||
use crate::ln::inbound_payment::{create, create_from_hash, ExpandedKey};
|
||||
use crate::routing::gossip::RoutingFees;
|
||||
use crate::routing::router::{RouteHint, RouteHintHop, Router};
|
||||
use crate::util::logger::{Logger, Record};
|
||||
use bitcoin::secp256k1::PublicKey;
|
||||
use alloc::collections::{btree_map, BTreeMap};
|
||||
use core::ops::Deref;
|
||||
use core::time::Duration;
|
||||
|
@ -54,12 +55,12 @@ use core::iter::Iterator;
|
|||
/// invoices in its `sign_invoice` implementation ([`PhantomKeysManager`] satisfies this
|
||||
/// requirement).
|
||||
///
|
||||
/// [`PhantomKeysManager`]: lightning::sign::PhantomKeysManager
|
||||
/// [`ChannelManager::get_phantom_route_hints`]: lightning::ln::channelmanager::ChannelManager::get_phantom_route_hints
|
||||
/// [`ChannelManager::create_inbound_payment`]: lightning::ln::channelmanager::ChannelManager::create_inbound_payment
|
||||
/// [`ChannelManager::create_inbound_payment_for_hash`]: lightning::ln::channelmanager::ChannelManager::create_inbound_payment_for_hash
|
||||
/// [`PhantomRouteHints::channels`]: lightning::ln::channelmanager::PhantomRouteHints::channels
|
||||
/// [`MIN_FINAL_CLTV_EXPIRY_DETLA`]: lightning::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY_DELTA
|
||||
/// [`PhantomKeysManager`]: crate::sign::PhantomKeysManager
|
||||
/// [`ChannelManager::get_phantom_route_hints`]: crate::ln::channelmanager::ChannelManager::get_phantom_route_hints
|
||||
/// [`ChannelManager::create_inbound_payment`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment
|
||||
/// [`ChannelManager::create_inbound_payment_for_hash`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment_for_hash
|
||||
/// [`PhantomRouteHints::channels`]: crate::ln::channelmanager::PhantomRouteHints::channels
|
||||
/// [`MIN_FINAL_CLTV_EXPIRY_DETLA`]: crate::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY_DELTA
|
||||
///
|
||||
/// This can be used in a `no_std` environment, where [`std::time::SystemTime`] is not
|
||||
/// available and the current time is supplied by the caller.
|
||||
|
@ -111,11 +112,11 @@ where
|
|||
/// invoices in its `sign_invoice` implementation ([`PhantomKeysManager`] satisfies this
|
||||
/// requirement).
|
||||
///
|
||||
/// [`PhantomKeysManager`]: lightning::sign::PhantomKeysManager
|
||||
/// [`ChannelManager::get_phantom_route_hints`]: lightning::ln::channelmanager::ChannelManager::get_phantom_route_hints
|
||||
/// [`ChannelManager::create_inbound_payment`]: lightning::ln::channelmanager::ChannelManager::create_inbound_payment
|
||||
/// [`ChannelManager::create_inbound_payment_for_hash`]: lightning::ln::channelmanager::ChannelManager::create_inbound_payment_for_hash
|
||||
/// [`PhantomRouteHints::channels`]: lightning::ln::channelmanager::PhantomRouteHints::channels
|
||||
/// [`PhantomKeysManager`]: crate::sign::PhantomKeysManager
|
||||
/// [`ChannelManager::get_phantom_route_hints`]: crate::ln::channelmanager::ChannelManager::get_phantom_route_hints
|
||||
/// [`ChannelManager::create_inbound_payment`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment
|
||||
/// [`ChannelManager::create_inbound_payment_for_hash`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment_for_hash
|
||||
/// [`PhantomRouteHints::channels`]: crate::ln::channelmanager::PhantomRouteHints::channels
|
||||
///
|
||||
/// This can be used in a `no_std` environment, where [`std::time::SystemTime`] is not
|
||||
/// available and the current time is supplied by the caller.
|
||||
|
@ -161,7 +162,7 @@ where
|
|||
|
||||
let invoice = match description {
|
||||
Bolt11InvoiceDescription::Direct(description) => {
|
||||
InvoiceBuilder::new(network).description(description.0.0.clone())
|
||||
InvoiceBuilder::new(network).description(description.as_inner().0.clone())
|
||||
}
|
||||
Bolt11InvoiceDescription::Hash(hash) => InvoiceBuilder::new(network).description_hash(hash.0),
|
||||
};
|
||||
|
@ -217,10 +218,8 @@ where
|
|||
Ok(inv) => inv,
|
||||
Err(e) => return Err(SignOrCreationError::CreationError(e))
|
||||
};
|
||||
let hrp_str = raw_invoice.hrp.to_string();
|
||||
let hrp_bytes = hrp_str.as_bytes();
|
||||
let data_without_signature = raw_invoice.data.to_base32();
|
||||
let signed_raw_invoice = raw_invoice.sign(|_| node_signer.sign_invoice(hrp_bytes, &data_without_signature, Recipient::PhantomNode));
|
||||
let signature = node_signer.sign_invoice(&raw_invoice, Recipient::PhantomNode);
|
||||
let signed_raw_invoice = raw_invoice.sign(|_| signature);
|
||||
match signed_raw_invoice {
|
||||
Ok(inv) => Ok(Bolt11Invoice::from_signed(inv).unwrap()),
|
||||
Err(e) => Err(SignOrCreationError::SignError(e))
|
||||
|
@ -234,7 +233,7 @@ where
|
|||
/// * Select up to three channels per node.
|
||||
/// * Select one hint from each node, up to three hints or until we run out of hints.
|
||||
///
|
||||
/// [`PhantomKeysManager`]: lightning::sign::PhantomKeysManager
|
||||
/// [`PhantomKeysManager`]: crate::sign::PhantomKeysManager
|
||||
fn select_phantom_hints<L: Deref>(amt_msat: Option<u64>, phantom_route_hints: Vec<PhantomRouteHints>,
|
||||
logger: L) -> impl Iterator<Item = RouteHint>
|
||||
where
|
||||
|
@ -331,7 +330,7 @@ fn rotate_through_iterators<T, I: Iterator<Item = T>>(mut vecs: Vec<I>) -> impl
|
|||
/// Note that LDK will add a buffer of 3 blocks to the delta to allow for up to a few new block
|
||||
/// confirmations during routing.
|
||||
///
|
||||
/// [`MIN_FINAL_CLTV_EXPIRY_DETLA`]: lightning::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY_DELTA
|
||||
/// [`MIN_FINAL_CLTV_EXPIRY_DETLA`]: crate::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY_DELTA
|
||||
pub fn create_invoice_from_channelmanager<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref>(
|
||||
channelmanager: &ChannelManager<M, T, ES, NS, SP, F, R, L>, node_signer: NS, logger: L,
|
||||
network: Currency, amt_msat: Option<u64>, description: String, invoice_expiry_delta_secs: u32,
|
||||
|
@ -372,7 +371,7 @@ where
|
|||
/// Note that LDK will add a buffer of 3 blocks to the delta to allow for up to a few new block
|
||||
/// confirmations during routing.
|
||||
///
|
||||
/// [`MIN_FINAL_CLTV_EXPIRY_DETLA`]: lightning::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY_DELTA
|
||||
/// [`MIN_FINAL_CLTV_EXPIRY_DETLA`]: crate::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY_DELTA
|
||||
pub fn create_invoice_from_channelmanager_with_description_hash<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref>(
|
||||
channelmanager: &ChannelManager<M, T, ES, NS, SP, F, R, L>, node_signer: NS, logger: L,
|
||||
network: Currency, amt_msat: Option<u64>, description_hash: Sha256,
|
||||
|
@ -541,7 +540,7 @@ fn _create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_has
|
|||
|
||||
let invoice = match description {
|
||||
Bolt11InvoiceDescription::Direct(description) => {
|
||||
InvoiceBuilder::new(network).description(description.0.0.clone())
|
||||
InvoiceBuilder::new(network).description(description.as_inner().0.clone())
|
||||
}
|
||||
Bolt11InvoiceDescription::Hash(hash) => InvoiceBuilder::new(network).description_hash(hash.0),
|
||||
};
|
||||
|
@ -569,10 +568,8 @@ fn _create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_has
|
|||
Ok(inv) => inv,
|
||||
Err(e) => return Err(SignOrCreationError::CreationError(e))
|
||||
};
|
||||
let hrp_str = raw_invoice.hrp.to_string();
|
||||
let hrp_bytes = hrp_str.as_bytes();
|
||||
let data_without_signature = raw_invoice.data.to_base32();
|
||||
let signed_raw_invoice = raw_invoice.sign(|_| node_signer.sign_invoice(hrp_bytes, &data_without_signature, Recipient::Node));
|
||||
let signature = node_signer.sign_invoice(&raw_invoice, Recipient::Node);
|
||||
let signed_raw_invoice = raw_invoice.sign(|_| signature);
|
||||
match signed_raw_invoice {
|
||||
Ok(inv) => Ok(Bolt11Invoice::from_signed(inv).unwrap()),
|
||||
Err(e) => Err(SignOrCreationError::SignError(e))
|
||||
|
@ -819,50 +816,49 @@ impl<'a, 'b, L: Deref> WithChannelDetails<'a, 'b, L> where L::Target: Logger {
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use core::time::Duration;
|
||||
use crate::{Currency, Description, Bolt11InvoiceDescription, SignOrCreationError, CreationError};
|
||||
use lightning_invoice::{Currency, Description, Bolt11InvoiceDescription, SignOrCreationError, CreationError};
|
||||
use bitcoin::hashes::{Hash, sha256};
|
||||
use bitcoin::hashes::sha256::Hash as Sha256;
|
||||
use lightning::sign::PhantomKeysManager;
|
||||
use lightning::events::{MessageSendEvent, MessageSendEventsProvider};
|
||||
use lightning::ln::types::PaymentHash;
|
||||
use crate::sign::PhantomKeysManager;
|
||||
use crate::events::{MessageSendEvent, MessageSendEventsProvider};
|
||||
use crate::ln::types::PaymentHash;
|
||||
#[cfg(feature = "std")]
|
||||
use lightning::ln::types::PaymentPreimage;
|
||||
use lightning::ln::channelmanager::{PhantomRouteHints, MIN_FINAL_CLTV_EXPIRY_DELTA, PaymentId, RecipientOnionFields, Retry};
|
||||
use lightning::ln::functional_test_utils::*;
|
||||
use lightning::ln::msgs::ChannelMessageHandler;
|
||||
use lightning::routing::router::{PaymentParameters, RouteParameters};
|
||||
use lightning::util::test_utils;
|
||||
use lightning::util::config::UserConfig;
|
||||
use crate::utils::{create_invoice_from_channelmanager_and_duration_since_epoch, rotate_through_iterators};
|
||||
use crate::ln::types::PaymentPreimage;
|
||||
use crate::ln::channelmanager::{PhantomRouteHints, MIN_FINAL_CLTV_EXPIRY_DELTA, PaymentId, RecipientOnionFields, Retry};
|
||||
use crate::ln::functional_test_utils::*;
|
||||
use crate::ln::msgs::ChannelMessageHandler;
|
||||
use crate::routing::router::{PaymentParameters, RouteParameters};
|
||||
use crate::util::test_utils;
|
||||
use crate::util::config::UserConfig;
|
||||
use std::collections::HashSet;
|
||||
use lightning::util::string::UntrustedString;
|
||||
|
||||
#[test]
|
||||
fn test_prefer_current_channel() {
|
||||
// No minimum, prefer larger candidate channel.
|
||||
assert_eq!(crate::utils::prefer_current_channel(None, 100, 200), false);
|
||||
assert_eq!(prefer_current_channel(None, 100, 200), false);
|
||||
|
||||
// No minimum, prefer larger current channel.
|
||||
assert_eq!(crate::utils::prefer_current_channel(None, 200, 100), true);
|
||||
assert_eq!(prefer_current_channel(None, 200, 100), true);
|
||||
|
||||
// Minimum set, prefer current channel over minimum + buffer.
|
||||
assert_eq!(crate::utils::prefer_current_channel(Some(100), 115, 100), true);
|
||||
assert_eq!(prefer_current_channel(Some(100), 115, 100), true);
|
||||
|
||||
// Minimum set, prefer candidate channel over minimum + buffer.
|
||||
assert_eq!(crate::utils::prefer_current_channel(Some(100), 105, 125), false);
|
||||
assert_eq!(prefer_current_channel(Some(100), 105, 125), false);
|
||||
|
||||
// Minimum set, both channels sufficient, prefer smaller current channel.
|
||||
assert_eq!(crate::utils::prefer_current_channel(Some(100), 115, 125), true);
|
||||
assert_eq!(prefer_current_channel(Some(100), 115, 125), true);
|
||||
|
||||
// Minimum set, both channels sufficient, prefer smaller candidate channel.
|
||||
assert_eq!(crate::utils::prefer_current_channel(Some(100), 200, 160), false);
|
||||
assert_eq!(prefer_current_channel(Some(100), 200, 160), false);
|
||||
|
||||
// Minimum set, neither sufficient, prefer larger current channel.
|
||||
assert_eq!(crate::utils::prefer_current_channel(Some(200), 100, 50), true);
|
||||
assert_eq!(prefer_current_channel(Some(200), 100, 50), true);
|
||||
|
||||
// Minimum set, neither sufficient, prefer larger candidate channel.
|
||||
assert_eq!(crate::utils::prefer_current_channel(Some(200), 100, 150), false);
|
||||
assert_eq!(prefer_current_channel(Some(200), 100, 150), false);
|
||||
}
|
||||
|
||||
|
||||
|
@ -878,10 +874,10 @@ mod test {
|
|||
nodes[1].node, nodes[1].keys_manager, nodes[1].logger, Currency::BitcoinTestnet,
|
||||
Some(10_000), "test".to_string(), Duration::from_secs(1234567),
|
||||
non_default_invoice_expiry_secs, None).unwrap();
|
||||
assert_eq!(invoice.amount_pico_btc(), Some(100_000));
|
||||
assert_eq!(invoice.amount_milli_satoshis(), Some(10_000));
|
||||
// If no `min_final_cltv_expiry_delta` is specified, then it should be `MIN_FINAL_CLTV_EXPIRY_DELTA`.
|
||||
assert_eq!(invoice.min_final_cltv_expiry_delta(), MIN_FINAL_CLTV_EXPIRY_DELTA as u64);
|
||||
assert_eq!(invoice.description(), Bolt11InvoiceDescription::Direct(&Description(UntrustedString("test".to_string()))));
|
||||
assert_eq!(invoice.description(), Bolt11InvoiceDescription::Direct(&Description::new("test".to_string()).unwrap()));
|
||||
assert_eq!(invoice.expiry_time(), Duration::from_secs(non_default_invoice_expiry_secs.into()));
|
||||
|
||||
// Invoice SCIDs should always use inbound SCID aliases over the real channel ID, if one is
|
||||
|
@ -905,20 +901,15 @@ mod test {
|
|||
nodes[0].node.send_payment(payment_hash,
|
||||
RecipientOnionFields::secret_only(*invoice.payment_secret()),
|
||||
PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
|
||||
let mut added_monitors = nodes[0].chain_monitor.added_monitors.lock().unwrap();
|
||||
assert_eq!(added_monitors.len(), 1);
|
||||
added_monitors.clear();
|
||||
check_added_monitors(&nodes[0], 1);
|
||||
|
||||
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
|
||||
assert_eq!(events.len(), 1);
|
||||
SendEvent::from_event(events.remove(0))
|
||||
|
||||
};
|
||||
nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event.msgs[0]);
|
||||
nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &payment_event.commitment_msg);
|
||||
let mut added_monitors = nodes[1].chain_monitor.added_monitors.lock().unwrap();
|
||||
assert_eq!(added_monitors.len(), 1);
|
||||
added_monitors.clear();
|
||||
check_added_monitors(&nodes[1], 1);
|
||||
let events = nodes[1].node.get_and_clear_pending_msg_events();
|
||||
assert_eq!(events.len(), 2);
|
||||
}
|
||||
|
@ -930,7 +921,7 @@ mod test {
|
|||
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
|
||||
let custom_min_final_cltv_expiry_delta = Some(50);
|
||||
|
||||
let invoice = crate::utils::create_invoice_from_channelmanager_and_duration_since_epoch(
|
||||
let invoice = create_invoice_from_channelmanager_and_duration_since_epoch(
|
||||
nodes[1].node, nodes[1].keys_manager, nodes[1].logger, Currency::BitcoinTestnet,
|
||||
Some(10_000), "".into(), Duration::from_secs(1234567), 3600,
|
||||
if with_custom_delta { custom_min_final_cltv_expiry_delta } else { None },
|
||||
|
@ -953,7 +944,7 @@ mod test {
|
|||
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
|
||||
let custom_min_final_cltv_expiry_delta = Some(21);
|
||||
|
||||
let invoice = crate::utils::create_invoice_from_channelmanager_and_duration_since_epoch(
|
||||
let invoice = create_invoice_from_channelmanager_and_duration_since_epoch(
|
||||
nodes[1].node, nodes[1].keys_manager, nodes[1].logger, Currency::BitcoinTestnet,
|
||||
Some(10_000), "".into(), Duration::from_secs(1234567), 3600,
|
||||
custom_min_final_cltv_expiry_delta,
|
||||
|
@ -967,14 +958,14 @@ mod test {
|
|||
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
|
||||
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
|
||||
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
|
||||
let description_hash = crate::Sha256(Hash::hash("Testing description_hash".as_bytes()));
|
||||
let invoice = crate::utils::create_invoice_from_channelmanager_with_description_hash_and_duration_since_epoch(
|
||||
let description_hash = Sha256(Hash::hash("Testing description_hash".as_bytes()));
|
||||
let invoice = create_invoice_from_channelmanager_with_description_hash_and_duration_since_epoch(
|
||||
nodes[1].node, nodes[1].keys_manager, nodes[1].logger, Currency::BitcoinTestnet,
|
||||
Some(10_000), description_hash, Duration::from_secs(1234567), 3600, None,
|
||||
).unwrap();
|
||||
assert_eq!(invoice.amount_pico_btc(), Some(100_000));
|
||||
assert_eq!(invoice.amount_milli_satoshis(), Some(10_000));
|
||||
assert_eq!(invoice.min_final_cltv_expiry_delta(), MIN_FINAL_CLTV_EXPIRY_DELTA as u64);
|
||||
assert_eq!(invoice.description(), Bolt11InvoiceDescription::Hash(&crate::Sha256(Sha256::hash("Testing description_hash".as_bytes()))));
|
||||
assert_eq!(invoice.description(), Bolt11InvoiceDescription::Hash(&Sha256(Sha256::hash("Testing description_hash".as_bytes()))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -984,14 +975,14 @@ mod test {
|
|||
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
|
||||
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
|
||||
let payment_hash = PaymentHash([0; 32]);
|
||||
let invoice = crate::utils::create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_hash(
|
||||
let invoice = create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_hash(
|
||||
nodes[1].node, nodes[1].keys_manager, nodes[1].logger, Currency::BitcoinTestnet,
|
||||
Some(10_000), "test".to_string(), Duration::from_secs(1234567), 3600,
|
||||
payment_hash, None,
|
||||
).unwrap();
|
||||
assert_eq!(invoice.amount_pico_btc(), Some(100_000));
|
||||
assert_eq!(invoice.amount_milli_satoshis(), Some(10_000));
|
||||
assert_eq!(invoice.min_final_cltv_expiry_delta(), MIN_FINAL_CLTV_EXPIRY_DELTA as u64);
|
||||
assert_eq!(invoice.description(), Bolt11InvoiceDescription::Direct(&Description(UntrustedString("test".to_string()))));
|
||||
assert_eq!(invoice.description(), Bolt11InvoiceDescription::Direct(&Description::new("test".to_string()).unwrap()));
|
||||
assert_eq!(invoice.payment_hash(), &sha256::Hash::from_slice(&payment_hash.0[..]).unwrap());
|
||||
}
|
||||
|
||||
|
@ -1283,7 +1274,7 @@ mod test {
|
|||
let hints = invoice.private_routes();
|
||||
|
||||
for hint in hints {
|
||||
let hint_short_chan_id = (hint.0).0[0].short_channel_id;
|
||||
let hint_short_chan_id = hint.0[0].short_channel_id;
|
||||
assert!(chan_ids_to_match.remove(&hint_short_chan_id));
|
||||
}
|
||||
assert!(chan_ids_to_match.is_empty(), "Unmatched short channel ids: {:?}", chan_ids_to_match);
|
||||
|
@ -1298,7 +1289,7 @@ mod test {
|
|||
|
||||
#[cfg(feature = "std")]
|
||||
fn do_test_multi_node_receive(user_generated_pmt_hash: bool) {
|
||||
use lightning::events::{Event, EventsProvider};
|
||||
use crate::events::{Event, EventsProvider};
|
||||
use core::cell::RefCell;
|
||||
|
||||
let mut chanmon_cfgs = create_chanmon_cfgs(3);
|
||||
|
@ -1333,7 +1324,7 @@ mod test {
|
|||
let non_default_invoice_expiry_secs = 4200;
|
||||
|
||||
let invoice =
|
||||
crate::utils::create_phantom_invoice::<&test_utils::TestKeysInterface, &test_utils::TestKeysInterface, &test_utils::TestLogger>(
|
||||
create_phantom_invoice::<&test_utils::TestKeysInterface, &test_utils::TestKeysInterface, &test_utils::TestLogger>(
|
||||
Some(payment_amt), payment_hash, "test".to_string(), non_default_invoice_expiry_secs,
|
||||
route_hints, nodes[1].keys_manager, nodes[1].keys_manager, nodes[1].logger,
|
||||
Currency::BitcoinTestnet, None, Duration::from_secs(genesis_timestamp)
|
||||
|
@ -1346,7 +1337,7 @@ mod test {
|
|||
};
|
||||
|
||||
assert_eq!(invoice.min_final_cltv_expiry_delta(), MIN_FINAL_CLTV_EXPIRY_DELTA as u64);
|
||||
assert_eq!(invoice.description(), Bolt11InvoiceDescription::Direct(&Description(UntrustedString("test".to_string()))));
|
||||
assert_eq!(invoice.description(), Bolt11InvoiceDescription::Direct(&Description::new("test".to_string()).unwrap()));
|
||||
assert_eq!(invoice.route_hints().len(), 2);
|
||||
assert_eq!(invoice.expiry_time(), Duration::from_secs(non_default_invoice_expiry_secs.into()));
|
||||
assert!(!invoice.features().unwrap().supports_basic_mpp());
|
||||
|
@ -1362,9 +1353,7 @@ mod test {
|
|||
nodes[0].node.send_payment(payment_hash,
|
||||
RecipientOnionFields::secret_only(*invoice.payment_secret()),
|
||||
PaymentId(payment_hash.0), params, Retry::Attempts(0)).unwrap();
|
||||
let mut added_monitors = nodes[0].chain_monitor.added_monitors.lock().unwrap();
|
||||
assert_eq!(added_monitors.len(), 1);
|
||||
added_monitors.clear();
|
||||
check_added_monitors(&nodes[0], 1);
|
||||
|
||||
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
|
||||
assert_eq!(events.len(), 1);
|
||||
|
@ -1428,7 +1417,7 @@ mod test {
|
|||
nodes[2].node.get_phantom_route_hints(),
|
||||
];
|
||||
|
||||
let invoice = crate::utils::create_phantom_invoice::<&test_utils::TestKeysInterface,
|
||||
let invoice = create_phantom_invoice::<&test_utils::TestKeysInterface,
|
||||
&test_utils::TestKeysInterface, &test_utils::TestLogger>(Some(payment_amt), Some(payment_hash),
|
||||
"test".to_string(), 3600, route_hints, nodes[1].keys_manager, nodes[1].keys_manager,
|
||||
nodes[1].logger, Currency::BitcoinTestnet, None, Duration::from_secs(1234567)).unwrap();
|
||||
|
@ -1444,7 +1433,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
#[cfg(feature = "std")]
|
||||
fn create_phantom_invoice_with_description_hash() {
|
||||
fn test_create_phantom_invoice_with_description_hash() {
|
||||
let chanmon_cfgs = create_chanmon_cfgs(3);
|
||||
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
|
||||
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
|
||||
|
@ -1456,9 +1445,9 @@ mod test {
|
|||
nodes[2].node.get_phantom_route_hints(),
|
||||
];
|
||||
|
||||
let description_hash = crate::Sha256(Hash::hash("Description hash phantom invoice".as_bytes()));
|
||||
let description_hash = Sha256(Hash::hash("Description hash phantom invoice".as_bytes()));
|
||||
let non_default_invoice_expiry_secs = 4200;
|
||||
let invoice = crate::utils::create_phantom_invoice_with_description_hash::<
|
||||
let invoice = create_phantom_invoice_with_description_hash::<
|
||||
&test_utils::TestKeysInterface, &test_utils::TestKeysInterface, &test_utils::TestLogger,
|
||||
>(
|
||||
Some(payment_amt), None, non_default_invoice_expiry_secs, description_hash,
|
||||
|
@ -1466,10 +1455,10 @@ mod test {
|
|||
Currency::BitcoinTestnet, None, Duration::from_secs(1234567),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(invoice.amount_pico_btc(), Some(200_000));
|
||||
assert_eq!(invoice.amount_milli_satoshis(), Some(20_000));
|
||||
assert_eq!(invoice.min_final_cltv_expiry_delta(), MIN_FINAL_CLTV_EXPIRY_DELTA as u64);
|
||||
assert_eq!(invoice.expiry_time(), Duration::from_secs(non_default_invoice_expiry_secs.into()));
|
||||
assert_eq!(invoice.description(), Bolt11InvoiceDescription::Hash(&crate::Sha256(Sha256::hash("Description hash phantom invoice".as_bytes()))));
|
||||
assert_eq!(invoice.description(), Bolt11InvoiceDescription::Hash(&Sha256(Sha256::hash("Description hash phantom invoice".as_bytes()))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1490,11 +1479,11 @@ mod test {
|
|||
let non_default_invoice_expiry_secs = 4200;
|
||||
let min_final_cltv_expiry_delta = Some(100);
|
||||
let duration_since_epoch = Duration::from_secs(1234567);
|
||||
let invoice = crate::utils::create_phantom_invoice::<&test_utils::TestKeysInterface,
|
||||
let invoice = create_phantom_invoice::<&test_utils::TestKeysInterface,
|
||||
&test_utils::TestKeysInterface, &test_utils::TestLogger>(Some(payment_amt), payment_hash,
|
||||
"".to_string(), non_default_invoice_expiry_secs, route_hints, nodes[1].keys_manager, nodes[1].keys_manager,
|
||||
nodes[1].logger, Currency::BitcoinTestnet, min_final_cltv_expiry_delta, duration_since_epoch).unwrap();
|
||||
assert_eq!(invoice.amount_pico_btc(), Some(200_000));
|
||||
assert_eq!(invoice.amount_milli_satoshis(), Some(20_000));
|
||||
assert_eq!(invoice.min_final_cltv_expiry_delta(), (min_final_cltv_expiry_delta.unwrap() + 3) as u64);
|
||||
assert_eq!(invoice.expiry_time(), Duration::from_secs(non_default_invoice_expiry_secs.into()));
|
||||
}
|
||||
|
@ -1895,7 +1884,7 @@ mod test {
|
|||
.map(|route_hint| route_hint.phantom_scid)
|
||||
.collect::<HashSet<u64>>();
|
||||
|
||||
let invoice = crate::utils::create_phantom_invoice::<&test_utils::TestKeysInterface,
|
||||
let invoice = create_phantom_invoice::<&test_utils::TestKeysInterface,
|
||||
&test_utils::TestKeysInterface, &test_utils::TestLogger>(invoice_amt, None, "test".to_string(),
|
||||
3600, phantom_route_hints, invoice_node.keys_manager, invoice_node.keys_manager,
|
||||
invoice_node.logger, Currency::BitcoinTestnet, None, Duration::from_secs(1234567)).unwrap();
|
||||
|
@ -1903,7 +1892,7 @@ mod test {
|
|||
let invoice_hints = invoice.private_routes();
|
||||
|
||||
for hint in invoice_hints {
|
||||
let hints = &(hint.0).0;
|
||||
let hints = &hint.0;
|
||||
match hints.len() {
|
||||
1 => {
|
||||
assert!(nodes_contains_public_channels);
|
||||
|
@ -1928,7 +1917,7 @@ mod test {
|
|||
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
|
||||
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
|
||||
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
|
||||
let result = crate::utils::create_invoice_from_channelmanager_and_duration_since_epoch(
|
||||
let result = create_invoice_from_channelmanager_and_duration_since_epoch(
|
||||
nodes[1].node, nodes[1].keys_manager, nodes[1].logger, Currency::BitcoinTestnet,
|
||||
Some(10_000), "Some description".into(), Duration::from_secs(1234567), 3600, Some(MIN_FINAL_CLTV_EXPIRY_DELTA - 4),
|
||||
);
|
|
@ -25,7 +25,12 @@ pub mod features;
|
|||
pub mod script;
|
||||
pub mod types;
|
||||
|
||||
pub use types::{ChannelId, PaymentHash, PaymentPreimage, PaymentSecret};
|
||||
// TODO: These modules were moved from lightning-invoice and need to be better integrated into this
|
||||
// crate now:
|
||||
pub mod invoice_utils;
|
||||
pub mod bolt11_payment;
|
||||
|
||||
pub use lightning_types::payment::{PaymentHash, PaymentPreimage, PaymentSecret};
|
||||
|
||||
#[cfg(fuzzing)]
|
||||
pub mod peer_channel_encryptor;
|
||||
|
|
|
@ -2320,11 +2320,26 @@ impl_writeable_msg!(ChannelReady, {
|
|||
(1, short_channel_id_alias, option),
|
||||
});
|
||||
|
||||
pub(crate) fn write_features_up_to_13<W: Writer>(w: &mut W, le_flags: &[u8]) -> Result<(), io::Error> {
|
||||
let len = core::cmp::min(2, le_flags.len());
|
||||
(len as u16).write(w)?;
|
||||
for i in (0..len).rev() {
|
||||
if i == 0 {
|
||||
le_flags[i].write(w)?;
|
||||
} else {
|
||||
// On byte 1, we want up-to-and-including-bit-13, 0-indexed, which is
|
||||
// up-to-and-including-bit-5, 0-indexed, on this byte:
|
||||
(le_flags[i] & 0b00_11_11_11).write(w)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl Writeable for Init {
|
||||
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
|
||||
// global_features gets the bottom 13 bits of our features, and local_features gets all of
|
||||
// our relevant feature bits. This keeps us compatible with old nodes.
|
||||
self.features.write_up_to_13(w)?;
|
||||
write_features_up_to_13(w, self.features.le_flags())?;
|
||||
self.features.write(w)?;
|
||||
encode_tlv_stream!(w, {
|
||||
(1, self.networks.as_ref().map(|n| WithoutLength(n)), option),
|
||||
|
|
|
@ -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<PaymentPreimage> 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<PaymentSecret, bech32::Error> {
|
||||
if field_data.len() != 52 {
|
||||
return Err(bech32::Error::InvalidLength)
|
||||
} else {
|
||||
let data_bytes = Vec::<u8>::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<W: WriteBase32>(&self, writer: &mut W) -> Result<(), <W as WriteBase32>::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 {
|
||||
|
|
|
@ -45,6 +45,8 @@ use core::str::FromStr;
|
|||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
use core::{cmp, fmt};
|
||||
|
||||
pub use lightning_types::routing::RoutingFees;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
|
@ -1212,16 +1214,6 @@ impl EffectiveCapacity {
|
|||
}
|
||||
}
|
||||
|
||||
/// Fees for routing via a given channel or a node
|
||||
#[derive(Eq, PartialEq, Copy, Clone, Debug, Hash, Ord, PartialOrd)]
|
||||
pub struct RoutingFees {
|
||||
/// Flat routing fee in millisatoshis.
|
||||
pub base_msat: u32,
|
||||
/// Liquidity-based routing fee in millionths of a routed amount.
|
||||
/// In other words, 10000 is 1%.
|
||||
pub proportional_millionths: u32,
|
||||
}
|
||||
|
||||
impl_writeable_tlv_based!(RoutingFees, {
|
||||
(0, base_msat, required),
|
||||
(2, proportional_millionths, required)
|
||||
|
|
|
@ -22,7 +22,7 @@ use crate::ln::msgs::{DecodeError, ErrorAction, LightningError, MAX_VALUE_MSAT};
|
|||
use crate::ln::onion_utils;
|
||||
use crate::offers::invoice::{BlindedPayInfo, Bolt12Invoice};
|
||||
use crate::onion_message::messenger::{DefaultMessageRouter, Destination, MessageRouter, OnionMessagePath};
|
||||
use crate::routing::gossip::{DirectedChannelInfo, EffectiveCapacity, ReadOnlyNetworkGraph, NetworkGraph, NodeId, RoutingFees};
|
||||
use crate::routing::gossip::{DirectedChannelInfo, EffectiveCapacity, ReadOnlyNetworkGraph, NetworkGraph, NodeId};
|
||||
use crate::routing::scoring::{ChannelUsage, LockableScore, ScoreLookUp};
|
||||
use crate::sign::EntropySource;
|
||||
use crate::util::ser::{Writeable, Readable, ReadableArgs, Writer};
|
||||
|
@ -35,6 +35,10 @@ use alloc::collections::BinaryHeap;
|
|||
use core::{cmp, fmt};
|
||||
use core::ops::Deref;
|
||||
|
||||
use lightning_types::routing::RoutingFees;
|
||||
|
||||
pub use lightning_types::routing::{RouteHint, RouteHintHop};
|
||||
|
||||
/// A [`Router`] implemented using [`find_route`].
|
||||
///
|
||||
/// # Privacy
|
||||
|
@ -1099,10 +1103,6 @@ impl ReadableArgs<bool> for Features {
|
|||
}
|
||||
}
|
||||
|
||||
/// A list of hops along a payment path terminating with a channel to the recipient.
|
||||
#[derive(Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub struct RouteHint(pub Vec<RouteHintHop>);
|
||||
|
||||
impl Writeable for RouteHint {
|
||||
fn write<W: crate::util::ser::Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
|
||||
(self.0.len() as u64).write(writer)?;
|
||||
|
@ -1124,27 +1124,6 @@ impl Readable for RouteHint {
|
|||
}
|
||||
}
|
||||
|
||||
/// A channel descriptor for a hop along a payment path.
|
||||
///
|
||||
/// While this generally comes from BOLT 11's `r` field, this struct includes more fields than are
|
||||
/// available in BOLT 11. Thus, encoding and decoding this via `lightning-invoice` is lossy, as
|
||||
/// fields not supported in BOLT 11 will be stripped.
|
||||
#[derive(Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub struct RouteHintHop {
|
||||
/// The node_id of the non-target end of the route
|
||||
pub src_node_id: PublicKey,
|
||||
/// The short_channel_id of this channel
|
||||
pub short_channel_id: u64,
|
||||
/// The fees which must be paid to use this channel
|
||||
pub fees: RoutingFees,
|
||||
/// The difference in CLTV values between this node and the next node.
|
||||
pub cltv_expiry_delta: u16,
|
||||
/// The minimum value, in msat, which must be relayed to the next hop.
|
||||
pub htlc_minimum_msat: Option<u64>,
|
||||
/// The maximum value in msat available for routing with a single HTLC.
|
||||
pub htlc_maximum_msat: Option<u64>,
|
||||
}
|
||||
|
||||
impl_writeable_tlv_based!(RouteHintHop, {
|
||||
(0, src_node_id, required),
|
||||
(1, htlc_minimum_msat, option),
|
||||
|
|
|
@ -24,7 +24,6 @@ use bitcoin::sighash::EcdsaSighashType;
|
|||
use bitcoin::transaction::Version;
|
||||
use bitcoin::transaction::{Transaction, TxIn, TxOut};
|
||||
|
||||
use bech32::u5;
|
||||
use bitcoin::hashes::sha256::Hash as Sha256;
|
||||
use bitcoin::hashes::sha256d::Hash as Sha256dHash;
|
||||
use bitcoin::hashes::{Hash, HashEngine};
|
||||
|
@ -37,6 +36,8 @@ use bitcoin::secp256k1::All;
|
|||
use bitcoin::secp256k1::{Keypair, PublicKey, Scalar, Secp256k1, SecretKey, Signing};
|
||||
use bitcoin::{secp256k1, Psbt, Sequence, Txid, WPubkeyHash, Witness};
|
||||
|
||||
use lightning_invoice::RawBolt11Invoice;
|
||||
|
||||
use crate::chain::transaction::OutPoint;
|
||||
use crate::crypto::utils::{hkdf_extract_expand_twice, sign, sign_with_aux_rand};
|
||||
use crate::ln::chan_utils;
|
||||
|
@ -69,7 +70,6 @@ use crate::sign::ecdsa::EcdsaChannelSigner;
|
|||
#[cfg(taproot)]
|
||||
use crate::sign::taproot::TaprootChannelSigner;
|
||||
use crate::util::atomic_counter::AtomicCounter;
|
||||
use crate::util::invoice::construct_invoice_preimage;
|
||||
use core::convert::TryInto;
|
||||
use core::ops::Deref;
|
||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
@ -867,7 +867,7 @@ pub trait NodeSigner {
|
|||
///
|
||||
/// Errors if the [`Recipient`] variant is not supported by the implementation.
|
||||
fn sign_invoice(
|
||||
&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient,
|
||||
&self, invoice: &RawBolt11Invoice, recipient: Recipient,
|
||||
) -> Result<RecoverableSignature, ()>;
|
||||
|
||||
/// Signs the [`TaggedHash`] of a BOLT 12 invoice request.
|
||||
|
@ -2174,17 +2174,14 @@ impl NodeSigner for KeysManager {
|
|||
}
|
||||
|
||||
fn sign_invoice(
|
||||
&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient,
|
||||
&self, invoice: &RawBolt11Invoice, recipient: Recipient,
|
||||
) -> Result<RecoverableSignature, ()> {
|
||||
let preimage = construct_invoice_preimage(&hrp_bytes, &invoice_data);
|
||||
let hash = invoice.signable_hash();
|
||||
let secret = match recipient {
|
||||
Recipient::Node => Ok(&self.node_secret),
|
||||
Recipient::PhantomNode => Err(()),
|
||||
}?;
|
||||
Ok(self.secp_ctx.sign_ecdsa_recoverable(
|
||||
&hash_to_message!(&Sha256::hash(&preimage).to_byte_array()),
|
||||
secret,
|
||||
))
|
||||
Ok(self.secp_ctx.sign_ecdsa_recoverable(&hash_to_message!(&hash), secret))
|
||||
}
|
||||
|
||||
fn sign_bolt12_invoice_request(
|
||||
|
@ -2352,17 +2349,14 @@ impl NodeSigner for PhantomKeysManager {
|
|||
}
|
||||
|
||||
fn sign_invoice(
|
||||
&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient,
|
||||
&self, invoice: &RawBolt11Invoice, recipient: Recipient,
|
||||
) -> Result<RecoverableSignature, ()> {
|
||||
let preimage = construct_invoice_preimage(&hrp_bytes, &invoice_data);
|
||||
let hash = invoice.signable_hash();
|
||||
let secret = match recipient {
|
||||
Recipient::Node => &self.inner.node_secret,
|
||||
Recipient::PhantomNode => &self.phantom_secret,
|
||||
};
|
||||
Ok(self.inner.secp_ctx.sign_ecdsa_recoverable(
|
||||
&hash_to_message!(&Sha256::hash(&preimage).to_byte_array()),
|
||||
secret,
|
||||
))
|
||||
Ok(self.inner.secp_ctx.sign_ecdsa_recoverable(&hash_to_message!(&hash), secret))
|
||||
}
|
||||
|
||||
fn sign_bolt12_invoice_request(
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
//! Low level invoice utilities.
|
||||
|
||||
use bech32::{u5, FromBase32};
|
||||
|
||||
#[allow(unused)]
|
||||
use crate::prelude::*;
|
||||
|
||||
/// Construct the invoice's HRP and signatureless data into a preimage to be hashed.
|
||||
pub fn construct_invoice_preimage(hrp_bytes: &[u8], data_without_signature: &[u5]) -> Vec<u8> {
|
||||
let mut preimage = Vec::<u8>::from(hrp_bytes);
|
||||
|
||||
let mut data_part = Vec::from(data_without_signature);
|
||||
let overhang = (data_part.len() * 5) % 8;
|
||||
if overhang > 0 {
|
||||
// add padding if data does not end at a byte boundary
|
||||
data_part.push(u5::try_from_u8(0).unwrap());
|
||||
|
||||
// if overhang is in (1..3) we need to add u5(0) padding two times
|
||||
if overhang < 3 {
|
||||
data_part.push(u5::try_from_u8(0).unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
preimage.extend_from_slice(&Vec::<u8>::from_base32(&data_part)
|
||||
.expect("No padding error may occur due to appended zero above."));
|
||||
preimage
|
||||
}
|
||||
|
|
@ -18,10 +18,8 @@ pub mod ser_macros;
|
|||
pub mod errors;
|
||||
pub mod ser;
|
||||
pub mod message_signing;
|
||||
pub mod invoice;
|
||||
pub mod persist;
|
||||
pub mod scid_utils;
|
||||
pub mod string;
|
||||
pub mod sweep;
|
||||
pub mod wakers;
|
||||
#[cfg(fuzzing)]
|
||||
|
@ -54,3 +52,7 @@ pub mod test_utils;
|
|||
#[cfg(any(test, feature = "_test_utils"))]
|
||||
pub mod test_channel_signer;
|
||||
|
||||
pub mod string {
|
||||
//! Utilities to wrap untrusted strings and handle them (more) safely
|
||||
pub use lightning_types::string::{PrintableString, UntrustedString};
|
||||
}
|
||||
|
|
|
@ -627,6 +627,18 @@ impl<'a> From<&'a String> for WithoutLength<&'a String> {
|
|||
fn from(s: &'a String) -> Self { Self(s) }
|
||||
}
|
||||
|
||||
impl Writeable for UntrustedString {
|
||||
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
|
||||
self.0.write(w)
|
||||
}
|
||||
}
|
||||
|
||||
impl Readable for UntrustedString {
|
||||
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
|
||||
let s: String = Readable::read(r)?;
|
||||
Ok(Self(s))
|
||||
}
|
||||
}
|
||||
|
||||
impl Writeable for WithoutLength<&UntrustedString> {
|
||||
#[inline]
|
||||
|
|
|
@ -65,6 +65,8 @@ use bitcoin::secp256k1::ecdh::SharedSecret;
|
|||
use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature};
|
||||
use bitcoin::secp256k1::schnorr;
|
||||
|
||||
use lightning_invoice::RawBolt11Invoice;
|
||||
|
||||
use crate::io;
|
||||
use crate::prelude::*;
|
||||
use core::cell::RefCell;
|
||||
|
@ -72,7 +74,6 @@ use core::time::Duration;
|
|||
use crate::sync::{Mutex, Arc};
|
||||
use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||
use core::mem;
|
||||
use bech32::u5;
|
||||
use crate::sign::{InMemorySigner, RandomBytes, Recipient, EntropySource, NodeSigner, SignerProvider};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
|
@ -1217,7 +1218,7 @@ impl NodeSigner for TestNodeSigner {
|
|||
Ok(SharedSecret::new(other_key, &node_secret))
|
||||
}
|
||||
|
||||
fn sign_invoice(&self, _: &[u8], _: &[bech32::u5], _: Recipient) -> Result<bitcoin::secp256k1::ecdsa::RecoverableSignature, ()> {
|
||||
fn sign_invoice(&self, _: &RawBolt11Invoice, _: Recipient) -> Result<RecoverableSignature, ()> {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
|
@ -1270,8 +1271,8 @@ impl NodeSigner for TestKeysInterface {
|
|||
self.backing.get_inbound_payment_key_material()
|
||||
}
|
||||
|
||||
fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient) -> Result<RecoverableSignature, ()> {
|
||||
self.backing.sign_invoice(hrp_bytes, invoice_data, recipient)
|
||||
fn sign_invoice(&self, invoice: &RawBolt11Invoice, recipient: Recipient) -> Result<RecoverableSignature, ()> {
|
||||
self.backing.sign_invoice(invoice, recipient)
|
||||
}
|
||||
|
||||
fn sign_bolt12_invoice_request(
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
./lightning/src/ln/functional_test_utils.rs
|
||||
./lightning/src/ln/functional_tests.rs
|
||||
./lightning/src/ln/inbound_payment.rs
|
||||
./lightning/src/ln/invoice_utils.rs
|
||||
./lightning/src/ln/max_payment_path_len_tests.rs
|
||||
./lightning/src/ln/mod.rs
|
||||
./lightning/src/ln/monitor_tests.rs
|
||||
|
|
Loading…
Add table
Reference in a new issue