From 86f73fc1a18644b889121502375bca40d59b3b23 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Tue, 10 Feb 2026 09:55:27 +0100 Subject: [PATCH 1/2] Introduce `LightningAmount` type in `lightning-types` Add a new `LightningAmount` struct wrapping `u64` millisatoshis to provide type-safe handling of Lightning Network amounts. This type will be used to replace raw `u64` values in public APIs throughout the codebase. The type provides: - Constructors: `from_msat()`, `from_sat()` (saturating on overflow) - Accessors: `to_msat()`, `to_sat_rounded()`, `to_sat_ceil()`, `to_sat_floor()` - Conversion: `From` - Arithmetic: `Add`, `Sub`, `AddAssign`, `SubAssign`, `Sum` - Display: formats as "{value} msat" - A `ZERO` constant for convenience Co-Authored-By: HAL 9000 --- lightning-types/src/amount.rs | 266 ++++++++++++++++++++++++++++++++++ lightning-types/src/lib.rs | 1 + 2 files changed, 267 insertions(+) create mode 100644 lightning-types/src/amount.rs diff --git a/lightning-types/src/amount.rs b/lightning-types/src/amount.rs new file mode 100644 index 00000000000..3097f9224e2 --- /dev/null +++ b/lightning-types/src/amount.rs @@ -0,0 +1,266 @@ +// 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. + +//! A type for representing lightning-specific amounts in millisatoshis. + +use core::fmt; +use core::iter::Sum; +use core::ops::{Add, AddAssign, Sub, SubAssign}; + +/// An amount of money denominated in millisatoshis (msat), the smallest unit used in the Lightning +/// Network. +/// +/// While the Bitcoin base layer uses satoshis as its smallest unit, Lightning Network payments +/// can be denominated in millisatoshis (1/1000 of a satoshi), allowing for finer-grained payment +/// amounts. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +pub struct LightningAmount { + msat: u64, +} + +impl LightningAmount { + /// The zero amount. + pub const ZERO: LightningAmount = LightningAmount { msat: 0 }; + + /// Constructs a new [`LightningAmount`] from the given number of millisatoshis. + pub const fn from_msat(msat: u64) -> Self { + Self { msat } + } + + /// Constructs a new [`LightningAmount`] from the given number of satoshis. + /// + /// Saturates to [`u64::MAX`] on overflow. + pub const fn from_sat(sat: u64) -> Self { + Self { msat: sat.saturating_mul(1000) } + } + + /// Returns the amount in millisatoshis. + pub const fn to_msat(&self) -> u64 { + self.msat + } + + /// Returns the amount in satoshis, rounded to the nearest satoshi. + /// + /// Ties (i.e., exactly 500 sub-satoshi millisatoshis) round up. + pub const fn to_sat_rounded(&self) -> u64 { + (self.msat + 500) / 1000 + } + + /// Returns the amount in satoshis, rounded up (ceiling). + pub const fn to_sat_ceil(&self) -> u64 { + (self.msat + 999) / 1000 + } + + /// Returns the amount in satoshis, rounded down (floor). + pub const fn to_sat_floor(&self) -> u64 { + self.msat / 1000 + } +} + +impl From for LightningAmount { + fn from(amount: bitcoin::Amount) -> Self { + Self::from_sat(amount.to_sat()) + } +} + +impl fmt::Display for LightningAmount { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{} msat", self.msat) + } +} + +impl Add for LightningAmount { + type Output = Self; + + fn add(self, rhs: Self) -> Self::Output { + Self { msat: self.msat + rhs.msat } + } +} + +impl Sub for LightningAmount { + type Output = Self; + + fn sub(self, rhs: Self) -> Self::Output { + Self { msat: self.msat - rhs.msat } + } +} + +impl AddAssign for LightningAmount { + fn add_assign(&mut self, rhs: Self) { + self.msat += rhs.msat; + } +} + +impl SubAssign for LightningAmount { + fn sub_assign(&mut self, rhs: Self) { + self.msat -= rhs.msat; + } +} + +impl Sum for LightningAmount { + fn sum>(iter: I) -> Self { + iter.fold(Self::ZERO, Add::add) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn from_msat_basic() { + assert_eq!(LightningAmount::from_msat(0).to_msat(), 0); + assert_eq!(LightningAmount::from_msat(1).to_msat(), 1); + assert_eq!(LightningAmount::from_msat(1_000).to_msat(), 1_000); + assert_eq!(LightningAmount::from_msat(u64::MAX).to_msat(), u64::MAX); + } + + #[test] + fn from_sat_basic() { + assert_eq!(LightningAmount::from_sat(0).to_msat(), 0); + assert_eq!(LightningAmount::from_sat(1).to_msat(), 1_000); + assert_eq!(LightningAmount::from_sat(100).to_msat(), 100_000); + } + + #[test] + fn from_sat_overflow_saturates() { + let large = u64::MAX / 1000 + 1; + let amount = LightningAmount::from_sat(large); + assert_eq!(amount.to_msat(), u64::MAX); + + let amount = LightningAmount::from_sat(u64::MAX); + assert_eq!(amount.to_msat(), u64::MAX); + } + + #[test] + fn to_sat_rounded() { + assert_eq!(LightningAmount::from_msat(0).to_sat_rounded(), 0); + assert_eq!(LightningAmount::from_msat(1).to_sat_rounded(), 0); + assert_eq!(LightningAmount::from_msat(499).to_sat_rounded(), 0); + assert_eq!(LightningAmount::from_msat(500).to_sat_rounded(), 1); + assert_eq!(LightningAmount::from_msat(501).to_sat_rounded(), 1); + assert_eq!(LightningAmount::from_msat(999).to_sat_rounded(), 1); + assert_eq!(LightningAmount::from_msat(1000).to_sat_rounded(), 1); + assert_eq!(LightningAmount::from_msat(1499).to_sat_rounded(), 1); + assert_eq!(LightningAmount::from_msat(1500).to_sat_rounded(), 2); + } + + #[test] + fn to_sat_ceil() { + assert_eq!(LightningAmount::from_msat(0).to_sat_ceil(), 0); + assert_eq!(LightningAmount::from_msat(1).to_sat_ceil(), 1); + assert_eq!(LightningAmount::from_msat(999).to_sat_ceil(), 1); + assert_eq!(LightningAmount::from_msat(1000).to_sat_ceil(), 1); + assert_eq!(LightningAmount::from_msat(1001).to_sat_ceil(), 2); + } + + #[test] + fn to_sat_floor() { + assert_eq!(LightningAmount::from_msat(0).to_sat_floor(), 0); + assert_eq!(LightningAmount::from_msat(999).to_sat_floor(), 0); + assert_eq!(LightningAmount::from_msat(1000).to_sat_floor(), 1); + assert_eq!(LightningAmount::from_msat(1001).to_sat_floor(), 1); + assert_eq!(LightningAmount::from_msat(1999).to_sat_floor(), 1); + } + + #[test] + fn from_bitcoin_amount() { + let btc_amount = bitcoin::Amount::from_sat(42); + let ln_amount = LightningAmount::from(btc_amount); + assert_eq!(ln_amount.to_msat(), 42_000); + } + + #[test] + fn zero_value() { + assert_eq!(LightningAmount::ZERO.to_msat(), 0); + assert_eq!(LightningAmount::ZERO, LightningAmount::from_msat(0)); + assert_eq!(LightningAmount::ZERO, LightningAmount::default()); + } + + #[test] + fn display_formatting() { + assert_eq!(format!("{}", LightningAmount::from_msat(0)), "0 msat"); + assert_eq!(format!("{}", LightningAmount::from_msat(1000)), "1000 msat"); + assert_eq!(format!("{}", LightningAmount::from_msat(42)), "42 msat"); + } + + #[test] + fn arithmetic_add() { + let a = LightningAmount::from_msat(100); + let b = LightningAmount::from_msat(200); + assert_eq!((a + b).to_msat(), 300); + } + + #[test] + fn arithmetic_sub() { + let a = LightningAmount::from_msat(300); + let b = LightningAmount::from_msat(100); + assert_eq!((a - b).to_msat(), 200); + } + + #[test] + fn arithmetic_add_assign() { + let mut a = LightningAmount::from_msat(100); + a += LightningAmount::from_msat(50); + assert_eq!(a.to_msat(), 150); + } + + #[test] + fn arithmetic_sub_assign() { + let mut a = LightningAmount::from_msat(100); + a -= LightningAmount::from_msat(30); + assert_eq!(a.to_msat(), 70); + } + + #[test] + fn sum_iterator() { + let amounts = vec![ + LightningAmount::from_msat(100), + LightningAmount::from_msat(200), + LightningAmount::from_msat(300), + ]; + let total: LightningAmount = amounts.into_iter().sum(); + assert_eq!(total.to_msat(), 600); + } + + #[test] + fn sum_empty_iterator() { + let amounts: Vec = vec![]; + let total: LightningAmount = amounts.into_iter().sum(); + assert_eq!(total, LightningAmount::ZERO); + } + + #[test] + fn ordering() { + let a = LightningAmount::from_msat(100); + let b = LightningAmount::from_msat(200); + let c = LightningAmount::from_msat(100); + assert!(a < b); + assert!(b > a); + assert_eq!(a, c); + assert!(a <= c); + assert!(a >= c); + } + + #[test] + #[should_panic] + fn sub_underflow_panics() { + let a = LightningAmount::from_msat(100); + let b = LightningAmount::from_msat(200); + let _ = a - b; + } + + #[test] + #[should_panic] + fn add_overflow_panics() { + let a = LightningAmount::from_msat(u64::MAX); + let b = LightningAmount::from_msat(1); + let _ = a + b; + } +} diff --git a/lightning-types/src/lib.rs b/lightning-types/src/lib.rs index 7f72d6d2671..47fc46c07ae 100644 --- a/lightning-types/src/lib.rs +++ b/lightning-types/src/lib.rs @@ -23,6 +23,7 @@ extern crate alloc; extern crate core; +pub mod amount; pub mod features; pub mod payment; pub mod routing; From 477f9aeb18137935a015e4b859f470e82887da29 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Tue, 10 Feb 2026 12:02:08 +0100 Subject: [PATCH 2/2] Use `LightningAmount` type in public `_msat`/`_msats` method APIs Replace raw `u64` values with the type-safe `LightningAmount` wrapper in all public method APIs dealing with millisatoshi amounts. This includes renaming methods like `as_msat()` to `as_amount()`, and `amount_milli_satoshis()` to `amount()`, ensuring callers use `LightningAmount::from_msat()` and `.to_msat()` for conversions. Internal logic, serialized struct fields, and message types remain unchanged. Co-Authored-By: HAL 9000 Signed-off-by: Elias Rohrer --- fuzz/src/bolt11_deser.rs | 2 +- lightning-background-processor/src/lib.rs | 9 +- lightning-invoice/src/lib.rs | 27 +- lightning-invoice/tests/ser_de.rs | 28 +- .../tests/lsps2_integration_tests.rs | 7 +- lightning/src/ln/accountable_tests.rs | 2 +- lightning/src/ln/async_payments_tests.rs | 4 +- lightning/src/ln/async_signer_tests.rs | 24 +- lightning/src/ln/blinded_payment_tests.rs | 21 +- lightning/src/ln/bolt11_payment_tests.rs | 3 +- lightning/src/ln/chanmon_update_fail_tests.rs | 20 +- lightning/src/ln/channel.rs | 51 +-- lightning/src/ln/channel_open_tests.rs | 213 ++++++++++--- lightning/src/ln/channel_state.rs | 12 +- lightning/src/ln/channelmanager.rs | 63 ++-- lightning/src/ln/functional_test_utils.rs | 43 ++- lightning/src/ln/functional_tests.rs | 83 ++++- lightning/src/ln/htlc_reserve_unit_tests.rs | 8 +- lightning/src/ln/invoice_utils.rs | 34 +- .../src/ln/max_payment_path_len_tests.rs | 2 +- lightning/src/ln/offers_tests.rs | 81 ++--- lightning/src/ln/onion_route_tests.rs | 12 +- lightning/src/ln/outbound_payment.rs | 66 ++-- lightning/src/ln/payment_tests.rs | 166 +++++++--- lightning/src/ln/priv_short_conf_tests.rs | 55 +++- lightning/src/ln/reload_tests.rs | 6 +- lightning/src/ln/shutdown_tests.rs | 39 ++- lightning/src/ln/splicing_tests.rs | 6 +- lightning/src/ln/update_fee_tests.rs | 7 +- lightning/src/offers/flow.rs | 4 +- lightning/src/offers/invoice.rs | 112 +++---- lightning/src/offers/invoice_request.rs | 206 ++++++------ lightning/src/offers/merkle.rs | 9 +- lightning/src/offers/offer.rs | 41 +-- lightning/src/offers/refund.rs | 8 +- lightning/src/offers/static_invoice.rs | 2 +- lightning/src/routing/gossip.rs | 11 +- lightning/src/routing/router.rs | 298 +++++++++--------- lightning/src/routing/scoring.rs | 275 ++++++++-------- 39 files changed, 1266 insertions(+), 794 deletions(-) diff --git a/fuzz/src/bolt11_deser.rs b/fuzz/src/bolt11_deser.rs index 92dde80aa66..a0423f47497 100644 --- a/fuzz/src/bolt11_deser.rs +++ b/fuzz/src/bolt11_deser.rs @@ -61,7 +61,7 @@ pub fn do_test(data: &[u8], _out: Out) { }; if let Ok(invoice) = Bolt11Invoice::from_signed(signed_raw_invoice) { - invoice.amount_milli_satoshis(); + invoice.amount(); } } } diff --git a/lightning-background-processor/src/lib.rs b/lightning-background-processor/src/lib.rs index f052f3d8d4c..e0106931e5d 100644 --- a/lightning-background-processor/src/lib.rs +++ b/lightning-background-processor/src/lib.rs @@ -2604,7 +2604,14 @@ mod tests { ($node_a: expr, $node_b: expr, $channel_value: expr) => {{ $node_a .node - .create_channel($node_b.node.get_our_node_id(), $channel_value, 100, 42, None, None) + .create_channel( + $node_b.node.get_our_node_id(), + $channel_value, + lightning::types::amount::LightningAmount::from_msat(100), + 42, + None, + None, + ) .unwrap(); let msg_a = get_event_msg!( $node_a, diff --git a/lightning-invoice/src/lib.rs b/lightning-invoice/src/lib.rs index 4ee9acb5f27..b0ed95543c3 100644 --- a/lightning-invoice/src/lib.rs +++ b/lightning-invoice/src/lib.rs @@ -53,6 +53,8 @@ use core::time::Duration; #[cfg(feature = "serde")] use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer}; +#[doc(no_inline)] +pub use lightning_types::amount::LightningAmount; #[doc(no_inline)] pub use lightning_types::payment::{PaymentHash, PaymentSecret}; #[doc(no_inline)] @@ -672,10 +674,11 @@ impl Self { + /// Sets the amount as a [`LightningAmount`]. The optimal SI prefix is chosen automatically. + pub fn amount(mut self, amount: LightningAmount) -> Self { + let amount_msat = amount.to_msat(); // Invoices are denominated in "pico BTC" - let amount = match amount_msat.checked_mul(10) { + let pico_btc = match amount_msat.checked_mul(10) { Some(amt) => amt, None => { self.error = Some(CreationError::InvalidAmount); @@ -684,9 +687,9 @@ impl Option { - self.signed_invoice.amount_pico_btc().map(|v| v / 10) + /// Returns the amount if specified in the invoice as a [`LightningAmount`]. + pub fn amount(&self) -> Option { + self.signed_invoice.amount_pico_btc().map(|v| LightningAmount::from_msat(v / 10)) } /// Returns the amount if specified in the invoice as pico BTC. @@ -2190,12 +2193,12 @@ mod test { .payment_hash(PaymentHash([0; 32])) .duration_since_epoch(Duration::from_secs(1234567)); - let invoice = builder.clone().amount_milli_satoshis(1500).build_raw().unwrap(); + let invoice = builder.clone().amount(LightningAmount::from_msat(1500)).build_raw().unwrap(); assert_eq!(invoice.hrp.si_prefix, Some(SiPrefix::Nano)); assert_eq!(invoice.hrp.raw_amount, Some(15)); - let invoice = builder.amount_milli_satoshis(150).build_raw().unwrap(); + let invoice = builder.amount(LightningAmount::from_msat(150)).build_raw().unwrap(); assert_eq!(invoice.hrp.si_prefix, Some(SiPrefix::Pico)); assert_eq!(invoice.hrp.raw_amount, Some(1500)); @@ -2304,7 +2307,7 @@ mod test { ]); let builder = InvoiceBuilder::new(Currency::BitcoinTestnet) - .amount_milli_satoshis(123) + .amount(LightningAmount::from_msat(123)) .duration_since_epoch(Duration::from_secs(1234567)) .payee_pub_key(public_key) .expiry_time(Duration::from_secs(54321)) @@ -2325,7 +2328,7 @@ mod test { assert!(invoice.check_signature().is_ok()); assert_eq!(invoice.tagged_fields().count(), 10); - assert_eq!(invoice.amount_milli_satoshis(), Some(123)); + assert_eq!(invoice.amount(), Some(LightningAmount::from_msat(123))); assert_eq!(invoice.amount_pico_btc(), Some(1230)); assert_eq!(invoice.currency(), Currency::BitcoinTestnet); #[cfg(feature = "std")] diff --git a/lightning-invoice/tests/ser_de.rs b/lightning-invoice/tests/ser_de.rs index 353878a9c52..9832ebee65e 100644 --- a/lightning-invoice/tests/ser_de.rs +++ b/lightning-invoice/tests/ser_de.rs @@ -42,7 +42,7 @@ fn get_test_tuples() -> Vec<(String, SignedRawBolt11Invoice, bool, bool)> { ( "lnbc2500u1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpu9qrsgquk0rl77nj30yxdy8j9vdx85fkpmdla2087ne0xh8nhedh8w27kyke0lp53ut353s06fv3qfegext0eh0ymjpf39tuven09sam30g4vgpfna3rh".to_owned(), InvoiceBuilder::new(Currency::Bitcoin) - .amount_milli_satoshis(250_000_000) + .amount(LightningAmount::from_msat(250_000_000)) .duration_since_epoch(Duration::from_secs(1496314658)) .payment_secret(PaymentSecret([0x11; 32])) .payment_hash(lightning_invoice::PaymentHash( @@ -70,7 +70,7 @@ fn get_test_tuples() -> Vec<(String, SignedRawBolt11Invoice, bool, bool)> { ( "lnbc2500u1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpu9qrsgqhtjpauu9ur7fw2thcl4y9vfvh4m9wlfyz2gem29g5ghe2aak2pm3ps8fdhtceqsaagty2vph7utlgj48u0ged6a337aewvraedendscp573dxr".to_owned(), InvoiceBuilder::new(Currency::Bitcoin) - .amount_milli_satoshis(250_000_000) + .amount(LightningAmount::from_msat(250_000_000)) .duration_since_epoch(Duration::from_secs(1496314658)) .payment_secret(PaymentSecret([0x11; 32])) .payment_hash(lightning_invoice::PaymentHash( @@ -98,7 +98,7 @@ fn get_test_tuples() -> Vec<(String, SignedRawBolt11Invoice, bool, bool)> { ( "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqs9qrsgq7ea976txfraylvgzuxs8kgcw23ezlrszfnh8r6qtfpr6cxga50aj6txm9rxrydzd06dfeawfk6swupvz4erwnyutnjq7x39ymw6j38gp7ynn44".to_owned(), InvoiceBuilder::new(Currency::Bitcoin) - .amount_milli_satoshis(2_000_000_000) + .amount(LightningAmount::from_msat(2_000_000_000)) .duration_since_epoch(Duration::from_secs(1496314658)) .description_hash(sha256::Hash::hash(b"One piece of chocolate cake, one icecream cone, one pickle, one slice of swiss cheese, one slice of salami, one lollypop, one piece of cherry pie, one sausage, one cupcake, and one slice of watermelon")) .payment_secret(PaymentSecret([0x11; 32])) @@ -125,7 +125,7 @@ fn get_test_tuples() -> Vec<(String, SignedRawBolt11Invoice, bool, bool)> { ( "lntb20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygshp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqfpp3x9et2e20v6pu37c5d9vax37wxq72un989qrsgqdj545axuxtnfemtpwkc45hx9d2ft7x04mt8q7y6t0k2dge9e7h8kpy9p34ytyslj3yu569aalz2xdk8xkd7ltxqld94u8h2esmsmacgpghe9k8".to_owned(), InvoiceBuilder::new(Currency::BitcoinTestnet) - .amount_milli_satoshis(2_000_000_000) + .amount(LightningAmount::from_msat(2_000_000_000)) .duration_since_epoch(Duration::from_secs(1496314658)) .description_hash(sha256::Hash::hash(b"One piece of chocolate cake, one icecream cone, one pickle, one slice of swiss cheese, one slice of salami, one lollypop, one piece of cherry pie, one sausage, one cupcake, and one slice of watermelon")) .payment_secret(PaymentSecret([0x11; 32])) @@ -153,7 +153,7 @@ fn get_test_tuples() -> Vec<(String, SignedRawBolt11Invoice, bool, bool)> { ( "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqsfpp3qjmp7lwpagxun9pygexvgpjdc4jdj85fr9yq20q82gphp2nflc7jtzrcazrra7wwgzxqc8u7754cdlpfrmccae92qgzqvzq2ps8pqqqqqqpqqqqq9qqqvpeuqafqxu92d8lr6fvg0r5gv0heeeqgcrqlnm6jhphu9y00rrhy4grqszsvpcgpy9qqqqqqgqqqqq7qqzq9qrsgqdfjcdk6w3ak5pca9hwfwfh63zrrz06wwfya0ydlzpgzxkn5xagsqz7x9j4jwe7yj7vaf2k9lqsdk45kts2fd0fkr28am0u4w95tt2nsq76cqw0".to_owned(), InvoiceBuilder::new(Currency::Bitcoin) - .amount_milli_satoshis(2_000_000_000) + .amount(LightningAmount::from_msat(2_000_000_000)) .duration_since_epoch(Duration::from_secs(1496314658)) .description_hash(sha256::Hash::hash(b"One piece of chocolate cake, one icecream cone, one pickle, one slice of swiss cheese, one slice of salami, one lollypop, one piece of cherry pie, one sausage, one cupcake, and one slice of watermelon")) .payment_secret(PaymentSecret([0x11; 32])) @@ -198,7 +198,7 @@ fn get_test_tuples() -> Vec<(String, SignedRawBolt11Invoice, bool, bool)> { ( "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygshp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqfppj3a24vwu6r8ejrss3axul8rxldph2q7z99qrsgqz6qsgww34xlatfj6e3sngrwfy3ytkt29d2qttr8qz2mnedfqysuqypgqex4haa2h8fx3wnypranf3pdwyluftwe680jjcfp438u82xqphf75ym".to_owned(), InvoiceBuilder::new(Currency::Bitcoin) - .amount_milli_satoshis(2_000_000_000) + .amount(LightningAmount::from_msat(2_000_000_000)) .duration_since_epoch(Duration::from_secs(1496314658)) .description_hash(sha256::Hash::hash(b"One piece of chocolate cake, one icecream cone, one pickle, one slice of swiss cheese, one slice of salami, one lollypop, one piece of cherry pie, one sausage, one cupcake, and one slice of watermelon")) .payment_secret(PaymentSecret([0x11; 32])) @@ -226,7 +226,7 @@ fn get_test_tuples() -> Vec<(String, SignedRawBolt11Invoice, bool, bool)> { ( "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygshp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqfppqw508d6qejxtdg4y5r3zarvary0c5xw7k9qrsgqt29a0wturnys2hhxpner2e3plp6jyj8qx7548zr2z7ptgjjc7hljm98xhjym0dg52sdrvqamxdezkmqg4gdrvwwnf0kv2jdfnl4xatsqmrnsse".to_owned(), InvoiceBuilder::new(Currency::Bitcoin) - .amount_milli_satoshis(2_000_000_000) + .amount(LightningAmount::from_msat(2_000_000_000)) .duration_since_epoch(Duration::from_secs(1496314658)) .description_hash(sha256::Hash::hash(b"One piece of chocolate cake, one icecream cone, one pickle, one slice of swiss cheese, one slice of salami, one lollypop, one piece of cherry pie, one sausage, one cupcake, and one slice of watermelon")) .payment_secret(PaymentSecret([0x11; 32])) @@ -256,7 +256,7 @@ fn get_test_tuples() -> Vec<(String, SignedRawBolt11Invoice, bool, bool)> { ( "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygshp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqfp4qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q9qrsgq9vlvyj8cqvq6ggvpwd53jncp9nwc47xlrsnenq2zp70fq83qlgesn4u3uyf4tesfkkwwfg3qs54qe426hp3tz7z6sweqdjg05axsrjqp9yrrwc".to_owned(), InvoiceBuilder::new(Currency::Bitcoin) - .amount_milli_satoshis(2_000_000_000) + .amount(LightningAmount::from_msat(2_000_000_000)) .duration_since_epoch(Duration::from_secs(1496314658)) .description_hash(sha256::Hash::hash(b"One piece of chocolate cake, one icecream cone, one pickle, one slice of swiss cheese, one slice of salami, one lollypop, one piece of cherry pie, one sausage, one cupcake, and one slice of watermelon")) .payment_secret(PaymentSecret([0x11; 32])) @@ -286,7 +286,7 @@ fn get_test_tuples() -> Vec<(String, SignedRawBolt11Invoice, bool, bool)> { ( "lnbc9678785340p1pwmna7lpp5gc3xfm08u9qy06djf8dfflhugl6p7lgza6dsjxq454gxhj9t7a0sd8dgfkx7cmtwd68yetpd5s9xar0wfjn5gpc8qhrsdfq24f5ggrxdaezqsnvda3kkum5wfjkzmfqf3jkgem9wgsyuctwdus9xgrcyqcjcgpzgfskx6eqf9hzqnteypzxz7fzypfhg6trddjhygrcyqezcgpzfysywmm5ypxxjemgw3hxjmn8yptk7untd9hxwg3q2d6xjcmtv4ezq7pqxgsxzmnyyqcjqmt0wfjjq6t5v4khxsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygsxqyjw5qcqp2rzjq0gxwkzc8w6323m55m4jyxcjwmy7stt9hwkwe2qxmy8zpsgg7jcuwz87fcqqeuqqqyqqqqlgqqqqn3qq9q9qrsgqrvgkpnmps664wgkp43l22qsgdw4ve24aca4nymnxddlnp8vh9v2sdxlu5ywdxefsfvm0fq3sesf08uf6q9a2ke0hc9j6z6wlxg5z5kqpu2v9wz".to_owned(), InvoiceBuilder::new(Currency::Bitcoin) - .amount_milli_satoshis(967878534) + .amount(LightningAmount::from_msat(967878534)) .duration_since_epoch(Duration::from_secs(1572468703)) .payment_secret(PaymentSecret([0x11; 32])) .payment_hash(lightning_invoice::PaymentHash( @@ -324,7 +324,7 @@ fn get_test_tuples() -> Vec<(String, SignedRawBolt11Invoice, bool, bool)> { ( "lnbc25m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5vdhkven9v5sxyetpdeessp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q5sqqqqqqqqqqqqqqqqsgq2a25dxl5hrntdtn6zvydt7d66hyzsyhqs4wdynavys42xgl6sgx9c4g7me86a27t07mdtfry458rtjr0v92cnmswpsjscgt2vcse3sgpz3uapa".to_owned(), InvoiceBuilder::new(Currency::Bitcoin) - .amount_milli_satoshis(2_500_000_000) + .amount(LightningAmount::from_msat(2_500_000_000)) .duration_since_epoch(Duration::from_secs(1496314658)) .payment_secret(PaymentSecret([0x11; 32])) .payment_hash(lightning_invoice::PaymentHash( @@ -351,7 +351,7 @@ fn get_test_tuples() -> Vec<(String, SignedRawBolt11Invoice, bool, bool)> { ( "LNBC25M1PVJLUEZPP5QQQSYQCYQ5RQWZQFQQQSYQCYQ5RQWZQFQQQSYQCYQ5RQWZQFQYPQDQ5VDHKVEN9V5SXYETPDEESSP5ZYG3ZYG3ZYG3ZYG3ZYG3ZYG3ZYG3ZYG3ZYG3ZYG3ZYG3ZYG3ZYGS9Q5SQQQQQQQQQQQQQQQQSGQ2A25DXL5HRNTDTN6ZVYDT7D66HYZSYHQS4WDYNAVYS42XGL6SGX9C4G7ME86A27T07MDTFRY458RTJR0V92CNMSWPSJSCGT2VCSE3SGPZ3UAPA".to_owned(), InvoiceBuilder::new(Currency::Bitcoin) - .amount_milli_satoshis(2_500_000_000) + .amount(LightningAmount::from_msat(2_500_000_000)) .duration_since_epoch(Duration::from_secs(1496314658)) .payment_secret(PaymentSecret([0x11; 32])) .payment_hash(lightning_invoice::PaymentHash( @@ -378,7 +378,7 @@ fn get_test_tuples() -> Vec<(String, SignedRawBolt11Invoice, bool, bool)> { ( "lnbc25m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5vdhkven9v5sxyetpdeessp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q5sqqqqqqqqqqqqqqqqsgq2qrqqqfppnqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqppnqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpp4qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqhpnqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqhp4qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqspnqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqsp4qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqnp5qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqnpkqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqz599y53s3ujmcfjp5xrdap68qxymkqphwsexhmhr8wdz5usdzkzrse33chw6dlp3jhuhge9ley7j2ayx36kawe7kmgg8sv5ugdyusdcqzn8z9x".to_owned(), InvoiceBuilder::new(Currency::Bitcoin) - .amount_milli_satoshis(2_500_000_000) + .amount(LightningAmount::from_msat(2_500_000_000)) .duration_since_epoch(Duration::from_secs(1496314658)) .payment_secret(PaymentSecret([0x11; 32])) .payment_hash(lightning_invoice::PaymentHash( @@ -405,7 +405,7 @@ fn get_test_tuples() -> Vec<(String, SignedRawBolt11Invoice, bool, bool)> { ( // Older version of the payment metadata test with a payment_pubkey set "lnbc10m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdp9wpshjmt9de6zqmt9w3skgct5vysxjmnnd9jx2mq8q8a04uqnp4q0n326hr8v9zprg8gsvezcch06gfaqqhde2aj730yg0durunfhv66sp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q2gqqqqqqsgqy9gw6ymamd20jumvdgpfphkhp8fzhhdhycw36egcmla5vlrtrmhs9t7psfy3hkkdqzm9eq64fjg558znccds5nhsfmxveha5xe0dykgpspdha0".to_owned(), InvoiceBuilder::new(Currency::Bitcoin) - .amount_milli_satoshis(1_000_000_000) + .amount(LightningAmount::from_msat(1_000_000_000)) .duration_since_epoch(Duration::from_secs(1496314658)) .payment_hash(lightning_invoice::PaymentHash( <[u8; 32]>::try_from( @@ -437,7 +437,7 @@ fn get_test_tuples() -> Vec<(String, SignedRawBolt11Invoice, bool, bool)> { ( "lnbc10m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdp9wpshjmt9de6zqmt9w3skgct5vysxjmnnd9jx2mq8q8a04uqsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q2gqqqqqqsgq7hf8he7ecf7n4ffphs6awl9t6676rrclv9ckg3d3ncn7fct63p6s365duk5wrk202cfy3aj5xnnp5gs3vrdvruverwwq7yzhkf5a3xqpd05wjc".to_owned(), InvoiceBuilder::new(Currency::Bitcoin) - .amount_milli_satoshis(1_000_000_000) + .amount(LightningAmount::from_msat(1_000_000_000)) .duration_since_epoch(Duration::from_secs(1496314658)) .payment_hash(lightning_invoice::PaymentHash( <[u8; 32]>::try_from( diff --git a/lightning-liquidity/tests/lsps2_integration_tests.rs b/lightning-liquidity/tests/lsps2_integration_tests.rs index 33a6dd697cf..fa674fa46df 100644 --- a/lightning-liquidity/tests/lsps2_integration_tests.rs +++ b/lightning-liquidity/tests/lsps2_integration_tests.rs @@ -42,7 +42,7 @@ use lightning::util::errors::APIError; use lightning::util::logger::Logger; use lightning::util::test_utils::{TestBroadcaster, TestStore}; -use lightning_invoice::{Bolt11Invoice, InvoiceBuilder, RoutingFees}; +use lightning_invoice::{Bolt11Invoice, InvoiceBuilder, LightningAmount, RoutingFees}; use lightning_types::payment::PaymentHash; @@ -147,7 +147,8 @@ fn create_jit_invoice( .private_route(route_hint); if let Some(amount_msat) = payment_size_msat { - invoice_builder = invoice_builder.amount_milli_satoshis(amount_msat).basic_mpp(); + invoice_builder = + invoice_builder.amount(LightningAmount::from_msat(amount_msat)).basic_mpp(); } let raw_invoice = invoice_builder.build_raw().map_err(|e| { @@ -1496,7 +1497,7 @@ fn create_channel_with_manual_broadcast( .create_channel( *client_node_id, *expected_outbound_amount_msat, - 0, + LightningAmount::from_msat(0), user_channel_id, None, None diff --git a/lightning/src/ln/accountable_tests.rs b/lightning/src/ln/accountable_tests.rs index 16ca1425817..c52ef034289 100644 --- a/lightning/src/ln/accountable_tests.rs +++ b/lightning/src/ln/accountable_tests.rs @@ -29,7 +29,7 @@ fn test_accountable_forwarding_with_override( let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[2]); let route_params = RouteParameters::from_payment_params_and_value( PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV), - 100_000, + LightningAmount::from_msat(100_000), ); let onion_fields = RecipientOnionFields::secret_only(payment_secret); let payment_id = PaymentId(payment_hash.0); diff --git a/lightning/src/ln/async_payments_tests.rs b/lightning/src/ln/async_payments_tests.rs index 8a991b1d98d..60373b183d4 100644 --- a/lightning/src/ln/async_payments_tests.rs +++ b/lightning/src/ln/async_payments_tests.rs @@ -270,7 +270,7 @@ fn pass_async_payments_oms( fn create_static_invoice_builder<'a>( recipient: &Node, offer: &'a Offer, offer_nonce: Nonce, relative_expiry: Option, ) -> StaticInvoiceBuilder<'a> { - let amount_msat = offer.amount().and_then(|amount| match amount { + let amount_msat = offer.offer_amount().and_then(|amount| match amount { Amount::Bitcoin { amount_msats } => Some(amount_msats), Amount::Currency { .. } => None, }); @@ -1473,7 +1473,7 @@ fn amount_doesnt_match_invreq() { payment_id, ) .unwrap() - .amount_msats(amt_msat + 1) + .amount(LightningAmount::from_msat(amt_msat + 1)) .unwrap() .chain_hash(ChainHash::using_genesis_block(Network::Testnet)) .unwrap() diff --git a/lightning/src/ln/async_signer_tests.rs b/lightning/src/ln/async_signer_tests.rs index 7d28a137d0a..53186f1704c 100644 --- a/lightning/src/ln/async_signer_tests.rs +++ b/lightning/src/ln/async_signer_tests.rs @@ -54,7 +54,14 @@ fn do_test_open_channel(zero_conf: bool) { nodes[0].disable_next_channel_signer_op(SignerOp::GetPerCommitmentPoint); let channel_id_0 = nodes[0] .node - .create_channel(node_b_id, channel_value_satoshis, 10001, user_channel_id, None, None) + .create_channel( + node_b_id, + channel_value_satoshis, + LightningAmount::from_msat(10001), + user_channel_id, + None, + None, + ) .unwrap(); { @@ -135,7 +142,10 @@ fn do_test_funding_created(signer_ops: Vec) { let node_a_id = nodes[0].node.get_our_node_id(); let node_b_id = nodes[1].node.get_our_node_id(); - nodes[0].node.create_channel(node_b_id, 100000, 10001, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel(node_b_id, 100000, LightningAmount::from_msat(10001), 42, None, None) + .unwrap(); // nodes[0] --- open_channel --> nodes[1] let mut open_chan_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); @@ -212,7 +222,10 @@ fn do_test_funding_signed(signer_ops: Vec) { let node_a_id = nodes[0].node.get_our_node_id(); let node_b_id = nodes[1].node.get_our_node_id(); - nodes[0].node.create_channel(node_b_id, 100000, 10001, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel(node_b_id, 100000, LightningAmount::from_msat(10001), 42, None, None) + .unwrap(); // nodes[0] --- open_channel --> nodes[1] let mut open_chan_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); @@ -382,7 +395,10 @@ fn do_test_funding_signed_0conf(signer_ops: Vec) { let node_b_id = nodes[1].node.get_our_node_id(); // nodes[0] --- open_channel --> nodes[1] - nodes[0].node.create_channel(node_b_id, 100000, 10001, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel(node_b_id, 100000, LightningAmount::from_msat(10001), 42, None, None) + .unwrap(); let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); nodes[1].node.handle_open_channel(node_a_id, &open_channel); diff --git a/lightning/src/ln/blinded_payment_tests.rs b/lightning/src/ln/blinded_payment_tests.rs index d78b9dfa4f2..3c41dc55b03 100644 --- a/lightning/src/ln/blinded_payment_tests.rs +++ b/lightning/src/ln/blinded_payment_tests.rs @@ -32,6 +32,7 @@ use crate::routing::router::{ BlindedTail, Path, Payee, PaymentParameters, Route, RouteHop, RouteParameters, TrampolineHop, }; use crate::sign::{NodeSigner, PeerStorageKey, ReceiveAuthKey, Recipient}; +use crate::types::amount::LightningAmount; use crate::types::features::{BlindedHopFeatures, ChannelFeatures, NodeFeatures}; use crate::types::payment::{PaymentHash, PaymentSecret}; use crate::util::config::{HTLCInterceptionFlags, UserConfig}; @@ -110,7 +111,7 @@ pub fn get_blinded_route_parameters( channel_upds, keys_manager, )]), - amt_msat, + LightningAmount::from_msat(amt_msat), ) } @@ -185,7 +186,7 @@ fn do_one_hop_blinded_path(success: bool) { let route_params = RouteParameters::from_payment_params_and_value( PaymentParameters::blinded(vec![blinded_path]), - amt_msat, + LightningAmount::from_msat(amt_msat), ); nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap(); @@ -237,7 +238,7 @@ fn one_hop_blinded_path_with_dummy_hops() { let route_params = RouteParameters::from_payment_params_and_value( PaymentParameters::blinded(vec![blinded_path]), - amt_msat, + LightningAmount::from_msat(amt_msat), ); nodes[0] .node @@ -305,7 +306,7 @@ fn mpp_to_one_hop_blinded_path() { channelmanager::provided_bolt12_invoice_features(&UserConfig::default()); let route_params = RouteParameters::from_payment_params_and_value( PaymentParameters::blinded(vec![blinded_path]).with_bolt12_features(bolt12_features).unwrap(), - amt_msat, + LightningAmount::from_msat(amt_msat), ); nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap(); check_added_monitors(&nodes[0], 2); @@ -396,7 +397,7 @@ fn mpp_to_three_hop_blinded_paths() { ) .with_bolt12_features(channelmanager::provided_bolt12_invoice_features(&UserConfig::default())) .unwrap(); - RouteParameters::from_payment_params_and_value(pay_params, amt_msat) + RouteParameters::from_payment_params_and_value(pay_params, LightningAmount::from_msat(amt_msat)) }; nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), @@ -1207,7 +1208,7 @@ fn blinded_path_retries() { ) .with_bolt12_features(channelmanager::provided_bolt12_invoice_features(&UserConfig::default())) .unwrap(); - RouteParameters::from_payment_params_and_value(pay_params, amt_msat) + RouteParameters::from_payment_params_and_value(pay_params, LightningAmount::from_msat(amt_msat)) }; nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params.clone(), Retry::Attempts(2)).unwrap(); @@ -1429,7 +1430,7 @@ fn custom_tlvs_to_blinded_path() { let route_params = RouteParameters::from_payment_params_and_value( PaymentParameters::blinded(vec![blinded_path]), - amt_msat, + LightningAmount::from_msat(amt_msat), ); let recipient_onion_fields = RecipientOnionFields::spontaneous_empty() @@ -1483,7 +1484,7 @@ fn fails_receive_tlvs_authentication() { let route_params = RouteParameters::from_payment_params_and_value( PaymentParameters::blinded(vec![blinded_path]), - amt_msat, + LightningAmount::from_msat(amt_msat), ); // Test authentication works normally. @@ -1514,7 +1515,7 @@ fn fails_receive_tlvs_authentication() { let route_params = RouteParameters::from_payment_params_and_value( PaymentParameters::blinded(vec![blinded_path]), - amt_msat, + LightningAmount::from_msat(amt_msat), ); nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap(); @@ -1572,7 +1573,7 @@ fn blinded_payment_path_padding() { assert!(is_padded(&blinded_path.blinded_hops(), PAYMENT_PADDING_ROUND_OFF)); - let route_params = RouteParameters::from_payment_params_and_value(PaymentParameters::blinded(vec![blinded_path]), amt_msat); + let route_params = RouteParameters::from_payment_params_and_value(PaymentParameters::blinded(vec![blinded_path]), LightningAmount::from_msat(amt_msat)); nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap(); check_added_monitors(&nodes[0], 1); diff --git a/lightning/src/ln/bolt11_payment_tests.rs b/lightning/src/ln/bolt11_payment_tests.rs index 8c2ac155ce7..bd987cf2d79 100644 --- a/lightning/src/ln/bolt11_payment_tests.rs +++ b/lightning/src/ln/bolt11_payment_tests.rs @@ -15,6 +15,7 @@ use crate::ln::functional_test_utils::*; use crate::ln::msgs::ChannelMessageHandler; use crate::ln::outbound_payment::Bolt11PaymentError; use crate::sign::{NodeSigner, Recipient}; +use crate::types::amount::LightningAmount; use lightning_invoice::{Bolt11Invoice, Currency, InvoiceBuilder}; use std::time::SystemTime; @@ -40,7 +41,7 @@ fn payment_metadata_end_to_end_for_invoice_with_amount() { .payment_secret(payment_secret) .duration_since_epoch(timestamp) .min_final_cltv_expiry_delta(144) - .amount_milli_satoshis(50_000) + .amount(LightningAmount::from_msat(50_000)) .payment_metadata(payment_metadata.clone()) .build_raw() .unwrap(); diff --git a/lightning/src/ln/chanmon_update_fail_tests.rs b/lightning/src/ln/chanmon_update_fail_tests.rs index 5a0c37bd61d..f81244cd390 100644 --- a/lightning/src/ln/chanmon_update_fail_tests.rs +++ b/lightning/src/ln/chanmon_update_fail_tests.rs @@ -2122,7 +2122,10 @@ fn do_during_funding_monitor_fail( let node_a_id = nodes[0].node.get_our_node_id(); let node_b_id = nodes[1].node.get_our_node_id(); - nodes[0].node.create_channel(node_b_id, 100000, 10001, 43, None, None).unwrap(); + nodes[0] + .node + .create_channel(node_b_id, 100000, LightningAmount::from_msat(10001), 43, None, None) + .unwrap(); let open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); handle_and_accept_open_channel(&nodes[1], node_a_id, &open_channel_msg); nodes[0].node.handle_accept_channel( @@ -3221,7 +3224,10 @@ fn do_test_outbound_reload_without_init_mon(use_0conf: bool) { let node_a_id = nodes[0].node.get_our_node_id(); let node_b_id = nodes[1].node.get_our_node_id(); - nodes[0].node.create_channel(node_b_id, 100000, 10001, 43, None, None).unwrap(); + nodes[0] + .node + .create_channel(node_b_id, 100000, LightningAmount::from_msat(10001), 43, None, None) + .unwrap(); nodes[1].node.handle_open_channel( node_a_id, &get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id), @@ -3330,7 +3336,10 @@ fn do_test_inbound_reload_without_init_mon(use_0conf: bool, lock_commitment: boo let node_a_id = nodes[0].node.get_our_node_id(); let node_b_id = nodes[1].node.get_our_node_id(); - nodes[0].node.create_channel(node_b_id, 100000, 10001, 43, None, None).unwrap(); + nodes[0] + .node + .create_channel(node_b_id, 100000, LightningAmount::from_msat(10001), 43, None, None) + .unwrap(); nodes[1].node.handle_open_channel( node_a_id, &get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id), @@ -5097,7 +5106,10 @@ fn test_mpp_claim_to_holding_cell() { let onion = RecipientOnionFields::secret_only(payment_secret_2); let id = PaymentId([42; 32]); let pay_params = PaymentParameters::from_node_id(node_d_id, TEST_FINAL_CLTV); - let route_params = RouteParameters::from_payment_params_and_value(pay_params, 400_000); + let route_params = RouteParameters::from_payment_params_and_value( + pay_params, + LightningAmount::from_msat(400_000), + ); nodes[2].node.send_payment(paymnt_hash_2, onion, id, route_params, Retry::Attempts(0)).unwrap(); check_added_monitors(&nodes[2], 1); diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index 937ca9295a5..43f2a5c5a8d 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -75,6 +75,7 @@ use crate::routing::gossip::NodeId; use crate::sign::ecdsa::EcdsaChannelSigner; use crate::sign::tx_builder::{HTLCAmountDirection, NextCommitmentStats, SpecTxBuilder, TxBuilder}; use crate::sign::{ChannelSigner, EntropySource, NodeSigner, Recipient, SignerProvider}; +use crate::types::amount::LightningAmount; use crate::types::features::{ChannelTypeFeatures, InitFeatures}; use crate::types::payment::{PaymentHash, PaymentPreimage}; use crate::util::config::{ @@ -2577,8 +2578,8 @@ impl FundingScope { self.channel_transaction_parameters.channel_value_satoshis } - pub(crate) fn get_value_to_self_msat(&self) -> u64 { - self.value_to_self_msat + pub(crate) fn get_value_to_self(&self) -> LightningAmount { + LightningAmount::from_msat(self.value_to_self_msat) } pub fn get_holder_counterparty_selected_channel_reserve_satoshis(&self) -> (u64, Option) { @@ -4077,8 +4078,8 @@ impl ChannelContext { /// Gets the fee we'd want to charge for adding an HTLC output to this Channel /// Allowed in any state (including after shutdown) - pub fn get_outbound_forwarding_fee_base_msat(&self) -> u32 { - self.config.options.forwarding_fee_base_msat + pub fn get_outbound_forwarding_fee_base(&self) -> LightningAmount { + LightningAmount::from_msat(self.config.options.forwarding_fee_base_msat as u64) } /// Returns true if we've ever received a message from the remote end for this Channel @@ -4413,23 +4414,27 @@ impl ChannelContext { } /// Allowed in any state (including after shutdown) - pub fn get_holder_htlc_minimum_msat(&self) -> u64 { - self.holder_htlc_minimum_msat + pub fn get_holder_htlc_minimum(&self) -> LightningAmount { + LightningAmount::from_msat(self.holder_htlc_minimum_msat) } /// Allowed in any state (including after shutdown), but will return none before TheirInitSent - pub fn get_holder_htlc_maximum_msat(&self, funding: &FundingScope) -> Option { - funding.get_htlc_maximum_msat(self.holder_max_htlc_value_in_flight_msat) + pub fn get_holder_htlc_maximum(&self, funding: &FundingScope) -> Option { + funding + .get_htlc_maximum_msat(self.holder_max_htlc_value_in_flight_msat) + .map(LightningAmount::from_msat) } /// Allowed in any state (including after shutdown) - pub fn get_counterparty_htlc_minimum_msat(&self) -> u64 { - self.counterparty_htlc_minimum_msat + pub fn get_counterparty_htlc_minimum(&self) -> LightningAmount { + LightningAmount::from_msat(self.counterparty_htlc_minimum_msat) } /// Allowed in any state (including after shutdown), but will return none before TheirInitSent - pub fn get_counterparty_htlc_maximum_msat(&self, funding: &FundingScope) -> Option { - funding.get_htlc_maximum_msat(self.counterparty_max_htlc_value_in_flight_msat) + pub fn get_counterparty_htlc_maximum(&self, funding: &FundingScope) -> Option { + funding + .get_htlc_maximum_msat(self.counterparty_max_htlc_value_in_flight_msat) + .map(LightningAmount::from_msat) } pub fn get_fee_proportional_millionths(&self) -> u32 { @@ -4461,13 +4466,15 @@ impl ChannelContext { /// /// Uses a default of 1 sat/vbyte if `limiting_feerate_sat_per_kw` is `None` and the dust /// exposure policy depends on fee rate. - pub fn get_max_dust_htlc_exposure_msat(&self, limiting_feerate_sat_per_kw: Option) -> u64 { - match self.config.options.max_dust_htlc_exposure { + pub fn get_max_dust_htlc_exposure( + &self, limiting_feerate_sat_per_kw: Option, + ) -> LightningAmount { + LightningAmount::from_msat(match self.config.options.max_dust_htlc_exposure { MaxDustHTLCExposure::FeeRateMultiplier(multiplier) => { (limiting_feerate_sat_per_kw.unwrap_or(250) as u64).saturating_mul(multiplier) }, MaxDustHTLCExposure::FixedLimitMsat(limit) => limit, - } + }) } /// Returns the previous [`ChannelConfig`] applied to this channel, if any. @@ -5013,7 +5020,7 @@ impl ChannelContext { })?; let max_dust_htlc_exposure_msat = - self.get_max_dust_htlc_exposure_msat(dust_exposure_limiting_feerate); + self.get_max_dust_htlc_exposure(dust_exposure_limiting_feerate).to_msat(); if next_local_commitment_stats.dust_exposure_msat > max_dust_htlc_exposure_msat { return Err(ChannelError::close( format!( @@ -5204,7 +5211,7 @@ impl ChannelContext { // Note, we evaluate pending htlc "preemptive" trimmed-to-dust threshold at the proposed // `feerate_per_kw`. let max_dust_htlc_exposure_msat = - self.get_max_dust_htlc_exposure_msat(dust_exposure_limiting_feerate); + self.get_max_dust_htlc_exposure(dust_exposure_limiting_feerate).to_msat(); if next_remote_commitment_stats.dust_exposure_msat > max_dust_htlc_exposure_msat { log_debug!( logger, @@ -5288,7 +5295,7 @@ impl ChannelContext { })?; let max_dust_htlc_exposure_msat = - self.get_max_dust_htlc_exposure_msat(dust_exposure_limiting_feerate); + self.get_max_dust_htlc_exposure(dust_exposure_limiting_feerate).to_msat(); if next_remote_commitment_stats.dust_exposure_msat > max_dust_htlc_exposure_msat { // Note that the total dust exposure includes both the dust HTLCs and the excess mining fees of // the counterparty commitment transaction @@ -5833,7 +5840,7 @@ impl ChannelContext { // send above the dust limit (as the router can always overpay to meet the dust limit). let mut remaining_msat_below_dust_exposure_limit = None; let mut dust_exposure_dust_limit_msat = 0; - let max_dust_htlc_exposure_msat = context.get_max_dust_htlc_exposure_msat(dust_exposure_limiting_feerate); + let max_dust_htlc_exposure_msat = context.get_max_dust_htlc_exposure(dust_exposure_limiting_feerate).to_msat(); let dust_buffer_feerate = self.get_dust_buffer_feerate(None); let (buffer_htlc_success_tx_fee_sat, buffer_htlc_timeout_tx_fee_sat) = second_stage_tx_fees_sat( @@ -13175,14 +13182,14 @@ where .chain(self.context.pending_outbound_htlcs.iter().map(|htlc| (&htlc.source, &htlc.payment_hash))) } - pub fn get_announced_htlc_max_msat(&self) -> u64 { - return cmp::min( + pub fn get_announced_htlc_max(&self) -> LightningAmount { + LightningAmount::from_msat(cmp::min( // Upper bound by capacity. We make it a bit less than full capacity to prevent attempts // to use full capacity. This is an effort to reduce routing failures, because in many cases // channel might have been used to route very small values (either by honest users or as DoS). self.funding.get_value_satoshis() * 1000 * 9 / 10, self.context.counterparty_max_htlc_value_in_flight_msat, - ); + )) } #[rustfmt::skip] diff --git a/lightning/src/ln/channel_open_tests.rs b/lightning/src/ln/channel_open_tests.rs index 059639330f8..182ae56b06e 100644 --- a/lightning/src/ln/channel_open_tests.rs +++ b/lightning/src/ln/channel_open_tests.rs @@ -27,6 +27,7 @@ use crate::ln::msgs::{ use crate::ln::types::ChannelId; use crate::ln::{functional_test_utils::*, msgs}; use crate::sign::EntropySource; +use crate::types::amount::LightningAmount; use crate::util::config::{ ChannelConfigOverrides, ChannelConfigUpdate, ChannelHandshakeConfigUpdate, UserConfig, }; @@ -58,7 +59,10 @@ fn test_outbound_chans_unlimited() { let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let node_a = nodes[0].node.get_our_node_id(); let node_b = nodes[1].node.get_our_node_id(); - nodes[0].node.create_channel(node_b, 100_000, 0, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel(node_b, 100_000, LightningAmount::from_msat(0), 42, None, None) + .unwrap(); let mut open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b); for _ in 0..MAX_UNFUNDED_CHANS_PER_PEER { @@ -77,7 +81,10 @@ fn test_outbound_chans_unlimited() { ); // but we can still open an outbound channel. - nodes[1].node.create_channel(node_a, 100_000, 0, 42, None, None).unwrap(); + nodes[1] + .node + .create_channel(node_a, 100_000, LightningAmount::from_msat(0), 42, None, None) + .unwrap(); get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, node_a); // but even with such an outbound channel, additional inbound channels will still fail. @@ -98,7 +105,10 @@ fn test_0conf_limiting() { // Note that create_network connects the nodes together for us let node_b = nodes[1].node.get_our_node_id(); - nodes[0].node.create_channel(node_b, 100_000, 0, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel(node_b, 100_000, LightningAmount::from_msat(0), 42, None, None) + .unwrap(); let mut open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b); let init_msg = &msgs::Init { features: nodes[0].node.init_features(), @@ -221,7 +231,10 @@ fn do_test_manual_inbound_accept_with_override( let node_a = nodes[0].node.get_our_node_id(); let node_b = nodes[1].node.get_our_node_id(); - nodes[0].node.create_channel(node_b, 100_000, 0, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel(node_b, 100_000, LightningAmount::from_msat(0), 42, None, None) + .unwrap(); let open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b); nodes[2].node.handle_open_channel(node_a, &open_channel_msg); @@ -328,7 +341,10 @@ fn do_test_channel_type_downgrade( let node_a = nodes[0].node.get_our_node_id(); let node_b = nodes[1].node.get_our_node_id(); - nodes[0].node.create_channel(node_b, 100_000, 0, 0, None, None).unwrap(); + nodes[0] + .node + .create_channel(node_b, 100_000, LightningAmount::from_msat(0), 0, None, None) + .unwrap(); let mut open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b); assert_eq!(open_channel_msg.common_fields.channel_type.as_ref().unwrap(), &start_type); @@ -379,7 +395,10 @@ fn test_no_channel_downgrade() { let node_a = nodes[0].node.get_our_node_id(); let node_b = nodes[1].node.get_our_node_id(); - nodes[0].node.create_channel(node_b, 100_000, 0, 0, None, None).unwrap(); + nodes[0] + .node + .create_channel(node_b, 100_000, LightningAmount::from_msat(0), 0, None, None) + .unwrap(); let open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b); let start_type = ChannelTypeFeatures::only_static_remote_key(); assert_eq!(open_channel_msg.common_fields.channel_type.as_ref().unwrap(), &start_type); @@ -425,7 +444,10 @@ fn test_channel_resumption_fail_post_funding() { let node_a_id = nodes[0].node.get_our_node_id(); let node_b_id = nodes[1].node.get_our_node_id(); - nodes[0].node.create_channel(node_b_id, 1_000_000, 0, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel(node_b_id, 1_000_000, LightningAmount::from_msat(0), 42, None, None) + .unwrap(); let open_chan = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); handle_and_accept_open_channel(&nodes[1], node_a_id, &open_chan); let accept_chan = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_a_id); @@ -475,7 +497,17 @@ pub fn test_insane_channel_opens() { let push_msat = (channel_value_sat - channel_reserve_satoshis) * 1000; // Have node0 initiate a channel to node1 with aforementioned parameters - nodes[0].node.create_channel(node_b_id, channel_value_sat, push_msat, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel( + node_b_id, + channel_value_sat, + LightningAmount::from_msat(push_msat), + 42, + None, + None, + ) + .unwrap(); // Extract the channel open message from node0 to node1 let open_channel_message = @@ -610,7 +642,10 @@ fn test_insane_zero_fee_channel_open() { let node_a_id = nodes[0].node.get_our_node_id(); let node_b_id = nodes[1].node.get_our_node_id(); - nodes[0].node.create_channel(node_b_id, 100_000, 0, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel(node_b_id, 100_000, LightningAmount::from_msat(0), 42, None, None) + .unwrap(); let open_channel_message = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); @@ -673,7 +708,7 @@ pub fn test_funding_exceeds_no_wumbo_limit() { match nodes[0].node.create_channel( node_b_id, MAX_FUNDING_SATOSHIS_NO_WUMBO + 1, - 0, + LightningAmount::from_msat(0), 42, None, None, @@ -713,7 +748,10 @@ fn do_test_sanity_on_in_flight_opens(steps: u8) { if steps & 0x0f == 0 { return; } - nodes[0].node.create_channel(node_b_id, 100000, 10001, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel(node_b_id, 100000, LightningAmount::from_msat(10001), 42, None, None) + .unwrap(); let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); if steps & 0x0f == 1 { @@ -832,7 +870,14 @@ pub fn bolt2_open_channel_sending_node_checks_part1() { let push_msat = 10001; nodes[0] .node - .create_channel(node_b_id, channel_value_satoshis, push_msat, 42, None, None) + .create_channel( + node_b_id, + channel_value_satoshis, + LightningAmount::from_msat(push_msat), + 42, + None, + None, + ) .unwrap(); let node0_to_1_send_open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); @@ -843,7 +888,14 @@ pub fn bolt2_open_channel_sending_node_checks_part1() { // channel_id, but now panics due to a colliding outbound SCID alias. assert!(nodes[0] .node - .create_channel(node_b_id, channel_value_satoshis, push_msat, 42, None, None) + .create_channel( + node_b_id, + channel_value_satoshis, + LightningAmount::from_msat(push_msat), + 42, + None, + None + ) .is_err()); } @@ -862,10 +914,20 @@ pub fn bolt2_open_channel_sending_node_checks_part2() { let push_msat = 1000 * channel_value_satoshis + 1; assert!(nodes[0] .node - .create_channel(node_b_id, channel_value_satoshis, push_msat, 42, None, None) + .create_channel( + node_b_id, + channel_value_satoshis, + LightningAmount::from_msat(push_msat), + 42, + None, + None + ) .is_err()); - nodes[0].node.create_channel(node_b_id, 100_000, 0, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel(node_b_id, 100_000, LightningAmount::from_msat(0), 42, None, None) + .unwrap(); let node0_to_1_send_open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); @@ -891,7 +953,17 @@ pub fn bolt2_open_channel_sane_dust_limit() { let value_sats = 1000000; let push_msat = 10001; - nodes[0].node.create_channel(node_b_id, value_sats, push_msat, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel( + node_b_id, + value_sats, + LightningAmount::from_msat(push_msat), + 42, + None, + None, + ) + .unwrap(); let mut node0_to_1_send_open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); node0_to_1_send_open_channel.common_fields.dust_limit_satoshis = 547; @@ -968,7 +1040,10 @@ pub fn test_user_configurable_csv_delay() { } // We test config.our_to_self > BREAKDOWN_TIMEOUT is enforced in InboundV1Channel::new() - nodes[1].node.create_channel(node_a_id, 1000000, 1000000, 42, None, None).unwrap(); + nodes[1] + .node + .create_channel(node_a_id, 1000000, LightningAmount::from_msat(1000000), 42, None, None) + .unwrap(); let mut open_channel = get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, node_a_id); open_channel.common_fields.to_self_delay = 200; if let Err(error) = InboundV1Channel::new( @@ -1000,7 +1075,10 @@ pub fn test_user_configurable_csv_delay() { } // We test msg.to_self_delay <= config.their_to_self_delay is enforced in Chanel::accept_channel() - nodes[0].node.create_channel(node_b_id, 1000000, 1000000, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel(node_b_id, 1000000, LightningAmount::from_msat(1000000), 42, None, None) + .unwrap(); let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); handle_and_accept_open_channel(&nodes[1], node_a_id, &open_channel); @@ -1028,7 +1106,10 @@ pub fn test_user_configurable_csv_delay() { check_closed_event(&nodes[0], 1, reason, &[node_b_id], 1000000); // We test msg.to_self_delay <= config.their_to_self_delay is enforced in InboundV1Channel::new() - nodes[1].node.create_channel(node_a_id, 1000000, 1000000, 42, None, None).unwrap(); + nodes[1] + .node + .create_channel(node_a_id, 1000000, LightningAmount::from_msat(1000000), 42, None, None) + .unwrap(); let mut open_channel = get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, node_a_id); open_channel.common_fields.to_self_delay = 200; if let Err(error) = InboundV1Channel::new( @@ -1071,7 +1152,10 @@ pub fn test_accept_inbound_channel_config_override() { let node_a_id = nodes[0].node.get_our_node_id(); let node_b_id = nodes[1].node.get_our_node_id(); - nodes[0].node.create_channel(node_b_id, 100000, 10001, 42, None, Some(conf)).unwrap(); + nodes[0] + .node + .create_channel(node_b_id, 100000, LightningAmount::from_msat(10001), 42, None, Some(conf)) + .unwrap(); let res = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); nodes[1].node.handle_open_channel(node_a_id, &res); @@ -1188,7 +1272,10 @@ pub fn test_reject_inbound_channel_request() { let node_a_id = nodes[0].node.get_our_node_id(); let node_b_id = nodes[1].node.get_our_node_id(); - nodes[0].node.create_channel(node_b_id, 100000, 10001, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel(node_b_id, 100000, LightningAmount::from_msat(10001), 42, None, None) + .unwrap(); let res = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); nodes[1].node.handle_open_channel(node_a_id, &res); @@ -1229,7 +1316,10 @@ pub fn test_can_not_accept_inbound_channel_twice() { let node_a_id = nodes[0].node.get_our_node_id(); let node_b_id = nodes[1].node.get_our_node_id(); - nodes[0].node.create_channel(node_b_id, 100000, 10001, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel(node_b_id, 100000, LightningAmount::from_msat(10001), 42, None, None) + .unwrap(); let res = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); nodes[1].node.handle_open_channel(node_a_id, &res); @@ -1300,12 +1390,18 @@ pub fn test_duplicate_temporary_channel_id_from_different_peers() { let node_c_id = nodes[2].node.get_our_node_id(); // Create an first channel channel - nodes[1].node.create_channel(node_a_id, 100000, 10001, 42, None, None).unwrap(); + nodes[1] + .node + .create_channel(node_a_id, 100000, LightningAmount::from_msat(10001), 42, None, None) + .unwrap(); let mut open_chan_msg_chan_1_0 = get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, node_a_id); // Create an second channel - nodes[2].node.create_channel(node_a_id, 100000, 10001, 43, None, None).unwrap(); + nodes[2] + .node + .create_channel(node_a_id, 100000, LightningAmount::from_msat(10001), 43, None, None) + .unwrap(); let mut open_chan_msg_chan_2_0 = get_event_msg!(nodes[2], MessageSendEvent::SendOpenChannel, node_a_id); @@ -1369,7 +1465,10 @@ pub fn test_duplicate_funding_err_in_funding() { chain::transaction::OutPoint { txid: funding_tx.compute_txid(), index: 0 }; assert_eq!(ChannelId::v1_from_funding_outpoint(real_chan_funding_txo), real_channel_id); - nodes[2].node.create_channel(node_b_id, 100_000, 0, 42, None, None).unwrap(); + nodes[2] + .node + .create_channel(node_b_id, 100_000, LightningAmount::from_msat(0), 42, None, None) + .unwrap(); let mut open_chan_msg = get_event_msg!(nodes[2], MessageSendEvent::SendOpenChannel, node_b_id); let node_c_temp_chan_id = open_chan_msg.common_fields.temporary_channel_id; open_chan_msg.common_fields.temporary_channel_id = real_channel_id; @@ -1417,7 +1516,10 @@ pub fn test_duplicate_chan_id() { let node_b_id = nodes[1].node.get_our_node_id(); // Create an initial channel - nodes[0].node.create_channel(node_b_id, 100000, 10001, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel(node_b_id, 100000, LightningAmount::from_msat(10001), 42, None, None) + .unwrap(); let mut open_chan_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); handle_and_accept_open_channel(&nodes[1], node_a_id, &open_chan_msg); nodes[0].node.handle_accept_channel( @@ -1504,7 +1606,10 @@ pub fn test_duplicate_chan_id() { } // Now try to create a second channel which has a duplicate funding output. - nodes[0].node.create_channel(node_b_id, 100000, 10001, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel(node_b_id, 100000, LightningAmount::from_msat(10001), 42, None, None) + .unwrap(); let open_chan_2_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); handle_and_accept_open_channel(&nodes[1], node_a_id, &open_chan_2_msg); nodes[0].node.handle_accept_channel( @@ -1609,7 +1714,10 @@ pub fn test_invalid_funding_tx() { let node_a_id = nodes[0].node.get_our_node_id(); let node_b_id = nodes[1].node.get_our_node_id(); - nodes[0].node.create_channel(node_b_id, 100_000, 10_000, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel(node_b_id, 100_000, LightningAmount::from_msat(10_000), 42, None, None) + .unwrap(); let open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); handle_and_accept_open_channel(&nodes[1], node_a_id, &open_channel_msg); nodes[0].node.handle_accept_channel( @@ -1723,7 +1831,10 @@ pub fn test_coinbase_funding_tx() { let node_a_id = nodes[0].node.get_our_node_id(); let node_b_id = nodes[1].node.get_our_node_id(); - nodes[0].node.create_channel(node_b_id, 100000, 10001, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel(node_b_id, 100000, LightningAmount::from_msat(10001), 42, None, None) + .unwrap(); let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); handle_and_accept_open_channel(&nodes[1], node_a_id, &open_channel); @@ -1782,8 +1893,10 @@ pub fn test_non_final_funding_tx() { let node_a_id = nodes[0].node.get_our_node_id(); let node_b_id = nodes[1].node.get_our_node_id(); - let temp_channel_id = - nodes[0].node.create_channel(node_b_id, 100_000, 0, 42, None, None).unwrap(); + let temp_channel_id = nodes[0] + .node + .create_channel(node_b_id, 100_000, LightningAmount::from_msat(0), 42, None, None) + .unwrap(); let open_channel_message = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); handle_and_accept_open_channel(&nodes[1], node_a_id, &open_channel_message); @@ -1842,8 +1955,10 @@ pub fn test_non_final_funding_tx_within_headroom() { let node_a_id = nodes[0].node.get_our_node_id(); let node_b_id = nodes[1].node.get_our_node_id(); - let temp_channel_id = - nodes[0].node.create_channel(node_b_id, 100_000, 0, 42, None, None).unwrap(); + let temp_channel_id = nodes[0] + .node + .create_channel(node_b_id, 100_000, LightningAmount::from_msat(0), 42, None, None) + .unwrap(); let open_channel_message = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); handle_and_accept_open_channel(&nodes[1], node_a_id, &open_channel_message); @@ -1897,8 +2012,10 @@ pub fn test_channel_close_when_not_timely_accepted() { // Simulate peer-disconnects mid-handshake // The channel is initiated from the node 0 side, // but the nodes disconnect before node 1 could send accept channel - let create_chan_id = - nodes[0].node.create_channel(node_b_id, 100000, 10001, 42, None, None).unwrap(); + let create_chan_id = nodes[0] + .node + .create_channel(node_b_id, 100000, LightningAmount::from_msat(10001), 42, None, None) + .unwrap(); let open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); assert_eq!(open_channel_msg.common_fields.temporary_channel_id, create_chan_id); @@ -1945,8 +2062,10 @@ pub fn test_rebroadcast_open_channel_when_reconnect_mid_handshake() { // Simulate peer-disconnects mid-handshake // The channel is initiated from the node 0 side, // but the nodes disconnect before node 1 could send accept channel - let create_chan_id = - nodes[0].node.create_channel(node_b_id, 100000, 10001, 42, None, None).unwrap(); + let create_chan_id = nodes[0] + .node + .create_channel(node_b_id, 100000, LightningAmount::from_msat(10001), 42, None, None) + .unwrap(); let open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); assert_eq!(open_channel_msg.common_fields.temporary_channel_id, create_chan_id); @@ -2330,7 +2449,10 @@ pub fn test_accept_inbound_channel_errors_queued() { let node_a_id = nodes[0].node.get_our_node_id(); let node_b_id = nodes[1].node.get_our_node_id(); - nodes[0].node.create_channel(node_b_id, 100_000, 0, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel(node_b_id, 100_000, LightningAmount::from_msat(0), 42, None, None) + .unwrap(); let open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); nodes[1].node.handle_open_channel(node_a_id, &open_channel_msg); @@ -2363,7 +2485,10 @@ pub fn test_manual_funding_abandon() { let node_a_id = nodes[0].node.get_our_node_id(); let node_b_id = nodes[1].node.get_our_node_id(); - assert!(nodes[0].node.create_channel(node_b_id, 100_000, 0, 42, None, None).is_ok()); + assert!(nodes[0] + .node + .create_channel(node_b_id, 100_000, LightningAmount::from_msat(0), 42, None, None) + .is_ok()); let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); handle_and_accept_open_channel(&nodes[1], node_a_id, &open_channel); @@ -2412,7 +2537,10 @@ pub fn test_funding_signed_event() { let node_a_id = nodes[0].node.get_our_node_id(); let node_b_id = nodes[1].node.get_our_node_id(); - assert!(nodes[0].node.create_channel(node_b_id, 100_000, 0, 42, None, None).is_ok()); + assert!(nodes[0] + .node + .create_channel(node_b_id, 100_000, LightningAmount::from_msat(0), 42, None, None) + .is_ok()); let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); handle_and_accept_open_channel(&nodes[1], node_a_id, &open_channel); @@ -2476,7 +2604,10 @@ fn test_fund_pending_channel() { let node_b_id = nodes[1].node.get_our_node_id(); - nodes[0].node.create_channel(node_b_id, 100_000, 0, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel(node_b_id, 100_000, LightningAmount::from_msat(0), 42, None, None) + .unwrap(); let open_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); let tx = Transaction { diff --git a/lightning/src/ln/channel_state.rs b/lightning/src/ln/channel_state.rs index c7277d18e3b..abde6c7466f 100644 --- a/lightning/src/ln/channel_state.rs +++ b/lightning/src/ln/channel_state.rs @@ -542,11 +542,13 @@ impl ChannelDetails { // Else `Channel::get_counterparty_htlc_minimum_msat` could return the // default `0` value set by `Channel::new_outbound`. outbound_htlc_minimum_msat: if context.have_received_message() { - Some(context.get_counterparty_htlc_minimum_msat()) + Some(context.get_counterparty_htlc_minimum().to_msat()) } else { None }, - outbound_htlc_maximum_msat: context.get_counterparty_htlc_maximum_msat(funding), + outbound_htlc_maximum_msat: context + .get_counterparty_htlc_maximum(funding) + .map(|a| a.to_msat()), }, funding_txo: funding.get_funding_txo(), funding_redeem_script: funding @@ -581,8 +583,10 @@ impl ChannelDetails { is_channel_ready: context.is_usable(), is_usable: context.is_live(), is_announced: context.should_announce(), - inbound_htlc_minimum_msat: Some(context.get_holder_htlc_minimum_msat()), - inbound_htlc_maximum_msat: context.get_holder_htlc_maximum_msat(funding), + inbound_htlc_minimum_msat: Some(context.get_holder_htlc_minimum().to_msat()), + inbound_htlc_maximum_msat: context + .get_holder_htlc_maximum(funding) + .map(|a| a.to_msat()), config: Some(context.config()), channel_shutdown_state: Some(context.shutdown_state()), pending_inbound_htlcs: context.get_pending_inbound_htlc_details(funding), diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 106cc7ccaed..628c3994b34 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -119,6 +119,7 @@ use crate::routing::router::{ }; use crate::sign::ecdsa::EcdsaChannelSigner; use crate::sign::{EntropySource, NodeSigner, Recipient, SignerProvider}; +use crate::types::amount::LightningAmount; #[cfg(any(feature = "_test_utils", test))] use crate::types::features::Bolt11InvoiceFeatures; use crate::types::features::{ @@ -2051,9 +2052,10 @@ impl< /// # /// # fn example(channel_manager: T, wallet: W, peer_id: PublicKey) { /// # let channel_manager = channel_manager.get_cm(); +/// use lightning::types::amount::LightningAmount; /// let value_sats = 1_000_000; -/// let push_msats = 10_000_000; -/// match channel_manager.create_channel(peer_id, value_sats, push_msats, 42, None, None) { +/// let push = LightningAmount::from_msat(10_000_000); +/// match channel_manager.create_channel(peer_id, value_sats, push, 42, None, None) { /// Ok(channel_id) => println!("Opening channel {}", channel_id), /// Err(e) => println!("Error opening channel: {:?}", e), /// } @@ -2322,6 +2324,7 @@ impl< /// # use lightning::ln::channelmanager::AChannelManager; /// # use lightning::offers::parse::Bolt12SemanticError; /// # use lightning::routing::router::RouteParametersConfig; +/// # use lightning_types::amount::LightningAmount; /// # /// # fn example(channel_manager: T) -> Result<(), Bolt12SemanticError> { /// # let channel_manager = channel_manager.get_cm(); @@ -2332,7 +2335,7 @@ impl< /// # let builder: lightning::offers::offer::OfferBuilder<_, _> = offer.into(); /// # let offer = builder /// .description("coffee".to_string()) -/// .amount_msats(10_000_000) +/// .amount(LightningAmount::from_msat(10_000_000)) /// .build()?; /// let bech32_offer = offer.to_string(); /// @@ -3577,7 +3580,7 @@ impl< /// randomized value for inbound channels. `user_channel_id` has no meaning inside of LDK, it /// is simply copied to events and otherwise ignored. /// - /// Raises [`APIError::APIMisuseError`] when `channel_value_satoshis` > 2**24 or `push_msat` is + /// Raises [`APIError::APIMisuseError`] when `channel_value_satoshis` > 2**24 or `push` is /// greater than `channel_value_satoshis * 1k` or `channel_value_satoshis < 1000`. /// /// Raises [`APIError::ChannelUnavailable`] if the channel cannot be opened due to failing to @@ -3602,7 +3605,8 @@ impl< /// [`Event::FundingGenerationReady::temporary_channel_id`]: events::Event::FundingGenerationReady::temporary_channel_id /// [`Event::ChannelClosed::channel_id`]: events::Event::ChannelClosed::channel_id #[rustfmt::skip] - pub fn create_channel(&self, their_network_key: PublicKey, channel_value_satoshis: u64, push_msat: u64, user_channel_id: u128, temporary_channel_id: Option, override_config: Option) -> Result { + pub fn create_channel(&self, their_network_key: PublicKey, channel_value_satoshis: u64, push: LightningAmount, user_channel_id: u128, temporary_channel_id: Option, override_config: Option) -> Result { + let push_msat = push.to_msat(); if channel_value_satoshis < 1000 { return Err(APIError::APIMisuseError { err: format!("Channel value must be at least 1000 satoshis. It was {}", channel_value_satoshis) }); } @@ -4815,7 +4819,7 @@ impl< return Err(LocalHTLCFailureReason::ChannelNotReady); } } - if next_packet.outgoing_amt_msat < chan.context.get_counterparty_htlc_minimum_msat() { + if next_packet.outgoing_amt_msat < chan.context.get_counterparty_htlc_minimum().to_msat() { return Err(LocalHTLCFailureReason::AmountBelowMinimum); } chan.htlc_satisfies_config(msg, next_packet.outgoing_amt_msat, next_packet.outgoing_cltv_value) @@ -5093,9 +5097,9 @@ impl< message_flags: 1 | if !chan.context.should_announce() { 1 << 1 } else { 0 }, // must_be_one + dont_forward channel_flags: (!were_node_one) as u8 | ((!enabled as u8) << 1), cltv_expiry_delta: chan.context.get_cltv_expiry_delta(), - htlc_minimum_msat: chan.context.get_counterparty_htlc_minimum_msat(), - htlc_maximum_msat: chan.get_announced_htlc_max_msat(), - fee_base_msat: chan.context.get_outbound_forwarding_fee_base_msat(), + htlc_minimum_msat: chan.context.get_counterparty_htlc_minimum().to_msat(), + htlc_maximum_msat: chan.get_announced_htlc_max().to_msat(), + fee_base_msat: chan.context.get_outbound_forwarding_fee_base().to_msat() as u32, fee_proportional_millionths: chan.context.get_fee_proportional_millionths(), excess_data: Vec::new(), }; @@ -5308,7 +5312,7 @@ impl< .and_then(|path| path.hops.last().map(|hop| (hop.pubkey, hop.cltv_expiry_delta as u32))) .unwrap_or_else(|| (PublicKey::from_slice(&[2; 32]).unwrap(), MIN_FINAL_CLTV_EXPIRY_DELTA as u32)); let dummy_payment_params = PaymentParameters::from_node_id(payee_node_id, cltv_delta); - RouteParameters::from_payment_params_and_value(dummy_payment_params, route.get_total_amount()) + RouteParameters::from_payment_params_and_value(dummy_payment_params, LightningAmount::from_msat(route.get_total_amount())) }); if route.route_params.is_none() { route.route_params = Some(route_params.clone()); } let router = FixedRouter::new(route); @@ -5845,8 +5849,10 @@ impl< ) -> Result, ProbeSendFailure> { let payment_params = PaymentParameters::from_node_id(node_id, final_cltv_expiry_delta); - let route_params = - RouteParameters::from_payment_params_and_value(payment_params, amount_msat); + let route_params = RouteParameters::from_payment_params_and_value( + payment_params, + LightningAmount::from_msat(amount_msat), + ); self.send_preflight_probes(route_params, liquidity_limit_multiplier) } @@ -5901,7 +5907,7 @@ impl< "Avoided sending payment probe all the way to last hop {} as it is likely unannounced.", last_path_hop.short_channel_id ); - let final_value_msat = path.final_value_msat(); + let final_value_msat = path.final_value().to_msat(); path.hops.pop(); if let Some(new_last) = path.hops.last_mut() { new_last.fee_msat += final_value_msat; @@ -5921,7 +5927,7 @@ impl< if let Some(first_hop) = first_hops.iter().find(|h| { h.get_outbound_payment_scid() == Some(first_path_hop.short_channel_id) }) { - let path_value = path.final_value_msat() + path.fee_msat(); + let path_value = path.final_value().to_msat() + path.fee().to_msat(); let used_liquidity = used_liquidity_map.entry(first_path_hop.short_channel_id).or_insert(0); @@ -8100,7 +8106,7 @@ impl< let verified_invreq = match verify_opt { Some(verified_invreq) => { if let Some(invreq_amt_msat) = - verified_invreq.amount_msats() + verified_invreq.amount().map(|a| a.to_msat()) { if payment_data.total_msat < invreq_amt_msat { fail_htlc!(claimable_htlc, payment_hash); @@ -13306,7 +13312,7 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ } if let Some(amount_msats) = amount_msats { - invoice = invoice.amount_milli_satoshis(amount_msats); + invoice = invoice.amount(LightningAmount::from_msat(amount_msats)); } let channels = self.list_channels(); @@ -13745,7 +13751,7 @@ impl< }; let builder = match amount_msats { None => builder, - Some(amount_msats) => builder.amount_msats(amount_msats)?, + Some(amount_msats) => builder.amount(LightningAmount::from_msat(amount_msats))?, }; let builder = match payer_note { None => builder, @@ -18012,7 +18018,9 @@ impl< counterparty_node_id: Some(channel.context.get_counterparty_node_id()), channel_capacity_sats: Some(channel.funding.get_value_satoshis()), channel_funding_txo: channel.funding.get_funding_txo(), - last_local_balance_msat: Some(channel.funding.get_value_to_self_msat()), + last_local_balance_msat: Some( + channel.funding.get_value_to_self().to_msat(), + ), }, None, )); @@ -18093,7 +18101,9 @@ impl< counterparty_node_id: Some(channel.context.get_counterparty_node_id()), channel_capacity_sats: Some(channel.funding.get_value_satoshis()), channel_funding_txo: channel.funding.get_funding_txo(), - last_local_balance_msat: Some(channel.funding.get_value_to_self_msat()), + last_local_balance_msat: Some( + channel.funding.get_value_to_self().to_msat(), + ), }, None, )); @@ -19478,6 +19488,7 @@ mod tests { use crate::prelude::*; use crate::routing::router::{find_route, PaymentParameters, RouteParameters}; use crate::sign::EntropySource; + use crate::types::amount::LightningAmount; use crate::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret}; use crate::util::config::{ChannelConfig, ChannelConfigUpdate}; use crate::util::errors::APIError; @@ -19714,7 +19725,7 @@ mod tests { // Next, attempt a keysend payment and make sure it fails. let route_params = RouteParameters::from_payment_params_and_value( PaymentParameters::for_keysend(expected_route.last().unwrap().node.get_our_node_id(), - TEST_FINAL_CLTV, false), 100_000); + TEST_FINAL_CLTV, false), LightningAmount::from_msat(100_000)); nodes[0].node.send_spontaneous_payment( Some(payment_preimage), RecipientOnionFields::spontaneous_empty(), PaymentId(payment_preimage.0), route_params.clone(), Retry::Attempts(0) @@ -19810,7 +19821,7 @@ mod tests { // Next, attempt a keysend payment and make sure it fails. let route_params = RouteParameters::from_payment_params_and_value( PaymentParameters::for_keysend(expected_route.last().unwrap().node.get_our_node_id(), TEST_FINAL_CLTV, false), - 100_000 + LightningAmount::from_msat(100_000) ); let payment_id_2 = PaymentId([45; 32]); nodes[0].node.send_spontaneous_payment( @@ -19859,7 +19870,7 @@ mod tests { let _chan = create_chan_between_nodes(&nodes[0], &nodes[1]); let route_params = RouteParameters::from_payment_params_and_value( - PaymentParameters::for_keysend(payee_pubkey, 40, false), 10_000); + PaymentParameters::for_keysend(payee_pubkey, 40, false), LightningAmount::from_msat(10_000)); let network_graph = nodes[0].network_graph; let first_hops = nodes[0].node.list_usable_channels(); let scorer = test_utils::TestScorer::new(); @@ -20139,7 +20150,7 @@ mod tests { let error_message = "Channel force-closed"; // Test the API functions. - check_not_connected_to_peer_error(nodes[0].node.create_channel(unkown_public_key, 1_000_000, 500_000_000, 42, None, None), unkown_public_key); + check_not_connected_to_peer_error(nodes[0].node.create_channel(unkown_public_key, 1_000_000, LightningAmount::from_msat(500_000_000), 42, None, None), unkown_public_key); check_unkown_peer_error(nodes[0].node.accept_inbound_channel(&channel_id, &unkown_public_key, 42, None), unkown_public_key); @@ -20193,7 +20204,7 @@ mod tests { // Note that create_network connects the nodes together for us - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None, None).unwrap(); + nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, LightningAmount::ZERO, 42, None, None).unwrap(); let mut open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); let mut funding_tx = None; @@ -20292,7 +20303,7 @@ mod tests { open_channel_msg.common_fields.temporary_channel_id); // Of course, however, outbound channels are always allowed - nodes[1].node.create_channel(last_random_pk, 100_000, 0, 42, None, None).unwrap(); + nodes[1].node.create_channel(last_random_pk, 100_000, LightningAmount::ZERO, 42, None, None).unwrap(); get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, last_random_pk); // If we fund the first channel, nodes[0] has a live on-chain channel with us, it is now @@ -20664,7 +20675,7 @@ pub mod bench { node_b.peer_connected(node_a.get_our_node_id(), &Init { features: node_a.init_features(), networks: None, remote_network_address: None }, false).unwrap(); - node_a.create_channel(node_b.get_our_node_id(), 8_000_000, 100_000_000, 42, None, None).unwrap(); + node_a.create_channel(node_b.get_our_node_id(), 8_000_000, LightningAmount::from_msat(100_000_000), 42, None, None).unwrap(); node_b.handle_open_channel(node_a.get_our_node_id(), &get_event_msg!(node_a_holder, MessageSendEvent::SendOpenChannel, node_b.get_our_node_id())); let events = node_b.get_and_clear_pending_events(); assert_eq!(events.len(), 1); diff --git a/lightning/src/ln/functional_test_utils.rs b/lightning/src/ln/functional_test_utils.rs index c21c62d464c..440900df62c 100644 --- a/lightning/src/ln/functional_test_utils.rs +++ b/lightning/src/ln/functional_test_utils.rs @@ -43,6 +43,7 @@ use crate::onion_message::messenger::OnionMessenger; use crate::routing::gossip::{NetworkGraph, NetworkUpdate, P2PGossipSync}; use crate::routing::router::{self, PaymentParameters, Route, RouteParameters}; use crate::sign::{EntropySource, RandomBytes}; +pub use crate::types::amount::LightningAmount; use crate::types::features::ChannelTypeFeatures; use crate::types::features::InitFeatures; use crate::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret}; @@ -1569,7 +1570,14 @@ pub fn exchange_open_accept_zero_conf_chan<'a, 'b, 'c, 'd>( initiator .node - .create_channel(receiver_node_id, channel_value_sat, push_msat, 42, None, initiator_config) + .create_channel( + receiver_node_id, + channel_value_sat, + LightningAmount::from_msat(push_msat), + 42, + None, + initiator_config, + ) .unwrap(); let open_channel = get_event_msg!(initiator, MessageSendEvent::SendOpenChannel, receiver_node_id); @@ -1681,8 +1689,17 @@ pub fn exchange_open_accept_chan<'a, 'b, 'c>( let node_a_id = node_a.node.get_our_node_id(); let node_b_id = node_b.node.get_our_node_id(); - let create_chan_id = - node_a.node.create_channel(node_b_id, channel_value, push_msat, 42, None, None).unwrap(); + let create_chan_id = node_a + .node + .create_channel( + node_b_id, + channel_value, + LightningAmount::from_msat(push_msat), + 42, + None, + None, + ) + .unwrap(); let open_channel_msg = get_event_msg!(node_a, MessageSendEvent::SendOpenChannel, node_b_id); assert_eq!(open_channel_msg.common_fields.temporary_channel_id, create_chan_id); assert_eq!( @@ -1974,7 +1991,14 @@ pub fn create_unannounced_chan_between_nodes_with_value<'a, 'b, 'c, 'd>( no_announce_cfg.channel_handshake_config.announce_for_forwarding = false; nodes[a] .node - .create_channel(node_b_id, channel_value, push_msat, 42, None, Some(no_announce_cfg)) + .create_channel( + node_b_id, + channel_value, + LightningAmount::from_msat(push_msat), + 42, + None, + Some(no_announce_cfg), + ) .unwrap(); let open_channel = get_event_msg!(nodes[a], MessageSendEvent::SendOpenChannel, node_b_id); handle_and_accept_open_channel(&nodes[b], node_a_id, &open_channel); @@ -2829,7 +2853,7 @@ macro_rules! get_route { ($send_node: expr, $payment_params: expr, $recv_value: expr) => {{ let route_params = $crate::routing::router::RouteParameters::from_payment_params_and_value( $payment_params, - $recv_value, + $crate::types::amount::LightningAmount::from_msat($recv_value), ); $crate::ln::functional_test_utils::get_route(&$send_node, &route_params) }}; @@ -2859,7 +2883,7 @@ macro_rules! get_route_and_payment_hash { let mut route_params = $crate::routing::router::RouteParameters::from_payment_params_and_value( $payment_params, - $recv_value, + $crate::types::amount::LightningAmount::from_msat($recv_value), ); route_params.max_total_routing_fee_msat = $max_total_routing_fee_msat; let (payment_preimage, payment_hash, payment_secret) = @@ -4162,7 +4186,10 @@ pub fn route_payment<'a, 'b, 'c>( ) .with_bolt11_features(expected_route.last().unwrap().node.bolt11_invoice_features()) .unwrap(); - let route_params = RouteParameters::from_payment_params_and_value(payment_params, recv_value); + let route_params = RouteParameters::from_payment_params_and_value( + payment_params, + LightningAmount::from_msat(recv_value), + ); let route = get_route(origin_node, &route_params).unwrap(); assert_eq!(route.paths.len(), 1); assert_eq!(route.paths[0].hops.len(), expected_route.len()); @@ -5553,7 +5580,7 @@ pub fn create_batch_channel_funding<'a, 'b, 'c>( .create_channel( other_node_id, *channel_value_satoshis, - *push_msat, + LightningAmount::from_msat(*push_msat), *user_channel_id, None, override_config.clone(), diff --git a/lightning/src/ln/functional_tests.rs b/lightning/src/ln/functional_tests.rs index 6fe0c83dfe8..d23ace84ae7 100644 --- a/lightning/src/ln/functional_tests.rs +++ b/lightning/src/ln/functional_tests.rs @@ -49,6 +49,7 @@ use crate::routing::router::{ get_route, Path, PaymentParameters, Route, RouteHop, RouteParameters, }; use crate::sign::{EntropySource, OutputSpender, SignerProvider}; +use crate::types::amount::LightningAmount; use crate::types::features::{ChannelFeatures, ChannelTypeFeatures, NodeFeatures}; use crate::types::payment::{PaymentHash, PaymentSecret}; use crate::types::string::UntrustedString; @@ -159,7 +160,10 @@ pub fn fake_network_test() { let payment_params = PaymentParameters::from_node_id(node_b_id, TEST_FINAL_CLTV) .with_bolt11_features(nodes[1].node.bolt11_invoice_features()) .unwrap(); - let route_params = RouteParameters::from_payment_params_and_value(payment_params, 1000000); + let route_params = RouteParameters::from_payment_params_and_value( + payment_params, + LightningAmount::from_msat(1000000), + ); let route = Route { paths: vec![Path { hops, blinded_tail: None }], route_params: Some(route_params.clone()), @@ -2550,8 +2554,17 @@ pub fn test_peer_disconnected_before_funding_broadcasted() { // Open a channel between `nodes[0]` and `nodes[1]`, for which the funding transaction is never // broadcasted, even though it's created by `nodes[0]`. - let expected_temporary_channel_id = - nodes[0].node.create_channel(node_b_id, 1_000_000, 500_000_000, 42, None, None).unwrap(); + let expected_temporary_channel_id = nodes[0] + .node + .create_channel( + node_b_id, + 1_000_000, + LightningAmount::from_msat(500_000_000), + 42, + None, + None, + ) + .unwrap(); let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); handle_and_accept_open_channel(&nodes[1], node_a_id, &open_channel); let accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_a_id); @@ -6044,7 +6057,10 @@ pub fn test_check_htlc_underpaying() { let payment_params = PaymentParameters::from_node_id(node_b_id, TEST_FINAL_CLTV) .with_bolt11_features(nodes[1].node.bolt11_invoice_features()) .unwrap(); - let route_params = RouteParameters::from_payment_params_and_value(payment_params, 10_000); + let route_params = RouteParameters::from_payment_params_and_value( + payment_params, + LightningAmount::from_msat(10_000), + ); let route = get_route( &node_a_id, &route_params, @@ -6350,7 +6366,10 @@ pub fn test_bump_penalty_txn_on_revoked_htlcs() { .unwrap(); let scorer = test_utils::TestScorer::new(); let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes(); - let route_params = RouteParameters::from_payment_params_and_value(payment_params, 3_000_000); + let route_params = RouteParameters::from_payment_params_and_value( + payment_params, + LightningAmount::from_msat(3_000_000), + ); let route = get_route( &node_a_id, &route_params, @@ -6366,7 +6385,10 @@ pub fn test_bump_penalty_txn_on_revoked_htlcs() { let payment_params = PaymentParameters::from_node_id(node_a_id, 50) .with_bolt11_features(nodes[0].node.bolt11_invoice_features()) .unwrap(); - let route_params = RouteParameters::from_payment_params_and_value(payment_params, 3_000_000); + let route_params = RouteParameters::from_payment_params_and_value( + payment_params, + LightningAmount::from_msat(3_000_000), + ); let route = get_route( &node_b_id, &route_params, @@ -6860,7 +6882,14 @@ pub fn test_override_channel_config() { nodes[0] .node - .create_channel(node_b_id, 16_000_000, 12_000_000, 42, None, Some(override_config)) + .create_channel( + node_b_id, + 16_000_000, + LightningAmount::from_msat(12_000_000), + 42, + None, + Some(override_config), + ) .unwrap(); // Assert the channel created by node0 is using the override config. @@ -6883,7 +6912,14 @@ pub fn test_override_0msat_htlc_minimum() { nodes[0] .node - .create_channel(node_b_id, 16_000_000, 12_000_000, 42, None, Some(zero_config)) + .create_channel( + node_b_id, + 16_000_000, + LightningAmount::from_msat(12_000_000), + 42, + None, + Some(zero_config), + ) .unwrap(); let res = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); assert_eq!(res.common_fields.htlc_minimum_msat, 1); @@ -7667,7 +7703,10 @@ pub fn test_pre_lockin_no_chan_closed_update() { let node_b_id = nodes[1].node.get_our_node_id(); // Create an initial channel - nodes[0].node.create_channel(node_b_id, 100000, 10001, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel(node_b_id, 100000, LightningAmount::from_msat(10001), 42, None, None) + .unwrap(); let mut open_chan_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); handle_and_accept_open_channel(&nodes[1], node_a_id, &open_chan_msg); let accept_chan_msg = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_a_id); @@ -8715,7 +8754,17 @@ fn do_test_max_dust_htlc_exposure( let node_a_id = nodes[0].node.get_our_node_id(); let node_b_id = nodes[1].node.get_our_node_id(); - nodes[0].node.create_channel(node_b_id, 1_000_000, 500_000_000, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel( + node_b_id, + 1_000_000, + LightningAmount::from_msat(500_000_000), + 42, + None, + None, + ) + .unwrap(); let mut open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); open_channel.common_fields.max_htlc_value_in_flight_msat = 50_000_000; open_channel.common_fields.max_accepted_htlcs = 60; @@ -8786,7 +8835,7 @@ fn do_test_max_dust_htlc_exposure( ); ( dust_buffer_feerate, - chan.context().get_max_dust_htlc_exposure_msat(Some(253)), + chan.context().get_max_dust_htlc_exposure(Some(253)).to_msat(), htlc_success_tx_fee_sat, htlc_timeout_tx_fee_sat, ) @@ -9680,8 +9729,10 @@ pub fn test_remove_expired_outbound_unfunded_channels() { let node_a_id = nodes[0].node.get_our_node_id(); let node_b_id = nodes[1].node.get_our_node_id(); - let temp_channel_id = - nodes[0].node.create_channel(node_b_id, 100_000, 0, 42, None, None).unwrap(); + let temp_channel_id = nodes[0] + .node + .create_channel(node_b_id, 100_000, LightningAmount::from_msat(0), 42, None, None) + .unwrap(); let open_channel_message = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); handle_and_accept_open_channel(&nodes[1], node_a_id, &open_channel_message); @@ -9744,8 +9795,10 @@ pub fn test_remove_expired_inbound_unfunded_channels() { let node_a_id = nodes[0].node.get_our_node_id(); let node_b_id = nodes[1].node.get_our_node_id(); - let temp_channel_id = - nodes[0].node.create_channel(node_b_id, 100_000, 0, 42, None, None).unwrap(); + let temp_channel_id = nodes[0] + .node + .create_channel(node_b_id, 100_000, LightningAmount::from_msat(0), 42, None, None) + .unwrap(); let open_channel_message = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); handle_and_accept_open_channel(&nodes[1], node_a_id, &open_channel_message); diff --git a/lightning/src/ln/htlc_reserve_unit_tests.rs b/lightning/src/ln/htlc_reserve_unit_tests.rs index 5b2ffca5fd4..9c380ba50a5 100644 --- a/lightning/src/ln/htlc_reserve_unit_tests.rs +++ b/lightning/src/ln/htlc_reserve_unit_tests.rs @@ -53,8 +53,10 @@ fn do_test_counterparty_no_reserve(send_from_initiator: bool) { push_amt -= get_holder_selected_channel_reserve_satoshis(100_000, &default_config) * 1000; let push = if send_from_initiator { 0 } else { push_amt }; - let temp_channel_id = - nodes[0].node.create_channel(node_b_id, 100_000, push, 42, None, None).unwrap(); + let temp_channel_id = nodes[0] + .node + .create_channel(node_b_id, 100_000, LightningAmount::from_msat(push), 42, None, None) + .unwrap(); let mut open_channel_message = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); if !send_from_initiator { @@ -1553,7 +1555,7 @@ pub fn test_update_add_htlc_bolt2_receiver_check_amount_received_more_than_min() let mut peer_state_lock; let channel = get_channel_ref!(nodes[0], nodes[1], per_peer_lock, peer_state_lock, chan.2); - channel.context().get_holder_htlc_minimum_msat() + channel.context().get_holder_htlc_minimum().to_msat() }; let (route, our_payment_hash, _, our_payment_secret) = diff --git a/lightning/src/ln/invoice_utils.rs b/lightning/src/ln/invoice_utils.rs index 1503a9a3a63..3f3750245b8 100644 --- a/lightning/src/ln/invoice_utils.rs +++ b/lightning/src/ln/invoice_utils.rs @@ -15,6 +15,7 @@ use crate::ln::inbound_payment::{create, create_from_hash}; use crate::routing::gossip::RoutingFees; use crate::routing::router::{RouteHint, RouteHintHop}; use crate::sign::{EntropySource, NodeSigner, Recipient}; +use crate::types::amount::LightningAmount; use crate::types::payment::PaymentHash; use crate::util::logger::{Logger, Record}; use alloc::collections::{btree_map, BTreeMap}; @@ -226,7 +227,7 @@ fn _create_phantom_invoice( ) .expiry_time(Duration::from_secs(invoice_expiry_delta_secs.into())); if let Some(amt) = amt_msat { - invoice = invoice.amount_milli_satoshis(amt); + invoice = invoice.amount(LightningAmount::from_msat(amt)); } for route_hint in @@ -596,6 +597,7 @@ mod test { use crate::ln::outbound_payment::{RecipientOnionFields, Retry}; use crate::routing::router::{PaymentParameters, RouteParameters, RouteParametersConfig}; use crate::sign::PhantomKeysManager; + use crate::types::amount::LightningAmount; use crate::types::payment::{PaymentHash, PaymentPreimage}; use crate::util::config::UserConfig; use crate::util::dyn_signer::{DynKeysInterface, DynPhantomKeysInterface}; @@ -656,7 +658,7 @@ mod test { ..Default::default() }; let invoice = nodes[1].node.create_bolt11_invoice(invoice_params).unwrap(); - assert_eq!(invoice.amount_milli_satoshis(), Some(amt_msat)); + assert_eq!(invoice.amount().map(|a| a.to_msat()), Some(amt_msat)); // 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!( @@ -786,7 +788,7 @@ mod test { ..Default::default() }; let invoice = nodes[1].node.create_bolt11_invoice(invoice_params).unwrap(); - assert_eq!(invoice.amount_milli_satoshis(), Some(10_000)); + assert_eq!(invoice.amount().map(|a| a.to_msat()), Some(10_000)); assert_eq!(invoice.min_final_cltv_expiry_delta(), MIN_FINAL_CLTV_EXPIRY_DELTA as u64); assert_eq!( invoice.description(), @@ -814,7 +816,7 @@ mod test { ..Default::default() }; let invoice = nodes[1].node.create_bolt11_invoice(invoice_params).unwrap(); - assert_eq!(invoice.amount_milli_satoshis(), Some(10_000)); + assert_eq!(invoice.amount().map(|a| a.to_msat()), Some(10_000)); assert_eq!(invoice.min_final_cltv_expiry_delta(), MIN_FINAL_CLTV_EXPIRY_DELTA as u64); assert_eq!( invoice.description(), @@ -1049,7 +1051,14 @@ mod test { private_chan_cfg.channel_handshake_config.announce_for_forwarding = false; let temporary_channel_id = nodes[2] .node - .create_channel(node_a_id, 1_000_000, 500_000_000, 42, None, Some(private_chan_cfg)) + .create_channel( + node_a_id, + 1_000_000, + LightningAmount::from_msat(500_000_000), + 42, + None, + Some(private_chan_cfg), + ) .unwrap(); let open_channel = get_event_msg!(nodes[2], MessageSendEvent::SendOpenChannel, node_a_id); handle_and_accept_open_channel(&nodes[0], node_c_id, &open_channel); @@ -1279,7 +1288,7 @@ mod test { .unwrap(); let params = RouteParameters::from_payment_params_and_value( payment_params, - invoice.amount_milli_satoshis().unwrap(), + invoice.amount().unwrap(), ); let payment_hash = invoice.payment_hash(); @@ -1434,7 +1443,7 @@ mod test { Duration::from_secs(1234567), ) .unwrap(); - assert_eq!(invoice.amount_milli_satoshis(), Some(20_000)); + assert_eq!(invoice.amount().map(|a| a.to_msat()), Some(20_000)); assert_eq!(invoice.min_final_cltv_expiry_delta(), MIN_FINAL_CLTV_EXPIRY_DELTA as u64); assert_eq!( invoice.expiry_time(), @@ -1482,7 +1491,7 @@ mod test { duration_since_epoch, ) .unwrap(); - assert_eq!(invoice.amount_milli_satoshis(), Some(20_000)); + assert_eq!(invoice.amount().map(|a| a.to_msat()), Some(20_000)); assert_eq!( invoice.min_final_cltv_expiry_delta(), (min_final_cltv_expiry_delta.unwrap() + 3) as u64 @@ -1581,7 +1590,14 @@ mod test { private_chan_cfg.channel_handshake_config.announce_for_forwarding = false; let temporary_channel_id = nodes[1] .node - .create_channel(node_d_id, 1_000_000, 500_000_000, 42, None, Some(private_chan_cfg)) + .create_channel( + node_d_id, + 1_000_000, + LightningAmount::from_msat(500_000_000), + 42, + None, + Some(private_chan_cfg), + ) .unwrap(); let open_channel = get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, node_d_id); handle_and_accept_open_channel(&nodes[3], node_b_id, &open_channel); diff --git a/lightning/src/ln/max_payment_path_len_tests.rs b/lightning/src/ln/max_payment_path_len_tests.rs index b947273115e..23631a94627 100644 --- a/lightning/src/ln/max_payment_path_len_tests.rs +++ b/lightning/src/ln/max_payment_path_len_tests.rs @@ -237,7 +237,7 @@ fn one_hop_blinded_path_with_custom_tlv() { .unwrap(); let route_params = RouteParameters::from_payment_params_and_value( PaymentParameters::blinded(vec![blinded_path.clone()]), - amt_msat, + LightningAmount::from_msat(amt_msat), ); // Calculate the maximum custom TLV value size where a valid onion packet is still possible. diff --git a/lightning/src/ln/offers_tests.rs b/lightning/src/ln/offers_tests.rs index 12e631b4042..e613312b31b 100644 --- a/lightning/src/ln/offers_tests.rs +++ b/lightning/src/ln/offers_tests.rs @@ -66,6 +66,7 @@ use crate::onion_message::offers::OffersMessage; use crate::routing::gossip::{NodeAlias, NodeId}; use crate::routing::router::{DEFAULT_PAYMENT_DUMMY_HOPS, PaymentParameters, RouteParameters, RouteParametersConfig}; use crate::sign::{NodeSigner, Recipient}; +use crate::types::amount::LightningAmount; use crate::util::ser::Writeable; /// This used to determine whether we built a compact path or not, but now its just a random @@ -190,7 +191,7 @@ fn route_bolt12_payment<'a, 'b, 'c>( // Use a fake payment_hash and bypass checking for the PaymentClaimable event since the // invoice contains the payment_hash but it was encrypted inside an onion message. - let amount_msats = invoice.amount_msats(); + let amount_msats = invoice.amount().to_msat(); let payment_hash = invoice.payment_hash(); let args = PassAlongPathArgs::new(node, path, amount_msats, payment_hash, ev) .without_clearing_recipient_events() @@ -320,7 +321,7 @@ fn create_offer_with_no_blinded_path() { let router = NullMessageRouter {}; let offer = alice.node .create_offer_builder_using_router(&router).unwrap() - .amount_msats(10_000_000) + .amount(LightningAmount::from_msat(10_000_000)) .build().unwrap(); assert_eq!(offer.issuer_signing_pubkey(), Some(alice_id)); assert!(offer.paths().is_empty()); @@ -347,7 +348,7 @@ fn create_refund_with_no_blinded_path() { .create_refund_builder_using_router(&router, 10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) .unwrap() .build().unwrap(); - assert_eq!(refund.amount_msats(), 10_000_000); + assert_eq!(refund.amount().to_msat(), 10_000_000); assert_eq!(refund.absolute_expiry(), Some(absolute_expiry)); assert_eq!(refund.payer_signing_pubkey(), alice_id); assert!(refund.paths().is_empty()); @@ -396,7 +397,7 @@ fn prefers_non_tor_nodes_in_blinded_paths() { let offer = bob.node .create_offer_builder().unwrap() - .amount_msats(10_000_000) + .amount(LightningAmount::from_msat(10_000_000)) .build().unwrap(); assert_ne!(offer.issuer_signing_pubkey(), Some(bob_id)); assert!(!offer.paths().is_empty()); @@ -412,7 +413,7 @@ fn prefers_non_tor_nodes_in_blinded_paths() { let offer = bob.node .create_offer_builder().unwrap() - .amount_msats(10_000_000) + .amount(LightningAmount::from_msat(10_000_000)) .build().unwrap(); assert_ne!(offer.issuer_signing_pubkey(), Some(bob_id)); assert!(!offer.paths().is_empty()); @@ -463,7 +464,7 @@ fn prefers_more_connected_nodes_in_blinded_paths() { let offer = bob.node .create_offer_builder().unwrap() - .amount_msats(10_000_000) + .amount(LightningAmount::from_msat(10_000_000)) .build().unwrap(); assert_ne!(offer.issuer_signing_pubkey(), Some(bob_id)); assert!(!offer.paths().is_empty()); @@ -498,7 +499,7 @@ fn check_dummy_hop_pattern_in_offer() { let compact_offer = alice.node .create_offer_builder_using_router(&default_router).unwrap() - .amount_msats(10_000_000) + .amount(LightningAmount::from_msat(10_000_000)) .build().unwrap(); assert!(!compact_offer.paths().is_empty()); @@ -516,7 +517,7 @@ fn check_dummy_hop_pattern_in_offer() { let onion_message = bob.onion_messenger.next_onion_message_for_peer(alice_id).unwrap(); let (invoice_request, reply_path) = extract_invoice_request(alice, &onion_message); - assert_eq!(invoice_request.amount_msats(), Some(10_000_000)); + assert_eq!(invoice_request.amount(), Some(LightningAmount::from_msat(10_000_000))); assert_ne!(invoice_request.payer_signing_pubkey(), bob_id); assert!(check_dummy_hopped_path_length(&reply_path, alice, bob_id, DUMMY_HOPS_PATH_LENGTH)); @@ -526,7 +527,7 @@ fn check_dummy_hop_pattern_in_offer() { let padded_offer = alice.node .create_offer_builder_using_router(&node_id_router).unwrap() - .amount_msats(10_000_000) + .amount(LightningAmount::from_msat(10_000_000)) .build().unwrap(); assert!(!padded_offer.paths().is_empty()); @@ -538,7 +539,7 @@ fn check_dummy_hop_pattern_in_offer() { let onion_message = bob.onion_messenger.next_onion_message_for_peer(alice_id).unwrap(); let (invoice_request, reply_path) = extract_invoice_request(alice, &onion_message); - assert_eq!(invoice_request.amount_msats(), Some(10_000_000)); + assert_eq!(invoice_request.amount(), Some(LightningAmount::from_msat(10_000_000))); assert_ne!(invoice_request.payer_signing_pubkey(), bob_id); assert!(check_dummy_hopped_path_length(&reply_path, alice, bob_id, DUMMY_HOPS_PATH_LENGTH)); } @@ -691,7 +692,7 @@ fn creates_and_pays_for_offer_using_two_hop_blinded_path() { let offer = alice.node .create_offer_builder() .unwrap() - .amount_msats(10_000_000) + .amount(LightningAmount::from_msat(10_000_000)) .build().unwrap(); assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id)); assert!(!offer.paths().is_empty()); @@ -723,7 +724,7 @@ fn creates_and_pays_for_offer_using_two_hop_blinded_path() { human_readable_name: None, }, }); - assert_eq!(invoice_request.amount_msats(), Some(10_000_000)); + assert_eq!(invoice_request.amount(), Some(LightningAmount::from_msat(10_000_000))); assert_ne!(invoice_request.payer_signing_pubkey(), david_id); assert!(check_dummy_hopped_path_length(&reply_path, bob, charlie_id, DUMMY_HOPS_PATH_LENGTH)); @@ -734,7 +735,7 @@ fn creates_and_pays_for_offer_using_two_hop_blinded_path() { david.onion_messenger.handle_onion_message(charlie_id, &onion_message); let (invoice, reply_path) = extract_invoice(david, &onion_message); - assert_eq!(invoice.amount_msats(), 10_000_000); + assert_eq!(invoice.amount().to_msat(), 10_000_000); assert_ne!(invoice.signing_pubkey(), alice_id); assert!(!invoice.payment_paths().is_empty()); for path in invoice.payment_paths() { @@ -799,7 +800,7 @@ fn creates_and_pays_for_refund_using_two_hop_blinded_path() { .create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) .unwrap() .build().unwrap(); - assert_eq!(refund.amount_msats(), 10_000_000); + assert_eq!(refund.amount().to_msat(), 10_000_000); assert_eq!(refund.absolute_expiry(), Some(absolute_expiry)); assert_ne!(refund.payer_signing_pubkey(), david_id); assert!(!refund.paths().is_empty()); @@ -822,7 +823,7 @@ fn creates_and_pays_for_refund_using_two_hop_blinded_path() { let (invoice, reply_path) = extract_invoice(david, &onion_message); assert_eq!(invoice, expected_invoice); - assert_eq!(invoice.amount_msats(), 10_000_000); + assert_eq!(invoice.amount().to_msat(), 10_000_000); assert_ne!(invoice.signing_pubkey(), alice_id); assert!(!invoice.payment_paths().is_empty()); for path in invoice.payment_paths() { @@ -856,7 +857,7 @@ fn creates_and_pays_for_offer_using_one_hop_blinded_path() { let offer = alice.node .create_offer_builder().unwrap() - .amount_msats(10_000_000) + .amount(LightningAmount::from_msat(10_000_000)) .build().unwrap(); assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id)); assert!(!offer.paths().is_empty()); @@ -881,7 +882,7 @@ fn creates_and_pays_for_offer_using_one_hop_blinded_path() { human_readable_name: None, }, }); - assert_eq!(invoice_request.amount_msats(), Some(10_000_000)); + assert_eq!(invoice_request.amount(), Some(LightningAmount::from_msat(10_000_000))); assert_ne!(invoice_request.payer_signing_pubkey(), bob_id); assert!(check_dummy_hopped_path_length(&reply_path, alice, bob_id, DUMMY_HOPS_PATH_LENGTH)); @@ -889,7 +890,7 @@ fn creates_and_pays_for_offer_using_one_hop_blinded_path() { bob.onion_messenger.handle_onion_message(alice_id, &onion_message); let (invoice, reply_path) = extract_invoice(bob, &onion_message); - assert_eq!(invoice.amount_msats(), 10_000_000); + assert_eq!(invoice.amount().to_msat(), 10_000_000); assert_ne!(invoice.signing_pubkey(), alice_id); assert!(!invoice.payment_paths().is_empty()); for path in invoice.payment_paths() { @@ -927,7 +928,7 @@ fn creates_and_pays_for_refund_using_one_hop_blinded_path() { .create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) .unwrap() .build().unwrap(); - assert_eq!(refund.amount_msats(), 10_000_000); + assert_eq!(refund.amount().to_msat(), 10_000_000); assert_eq!(refund.absolute_expiry(), Some(absolute_expiry)); assert_ne!(refund.payer_signing_pubkey(), bob_id); assert!(!refund.paths().is_empty()); @@ -945,7 +946,7 @@ fn creates_and_pays_for_refund_using_one_hop_blinded_path() { let (invoice, reply_path) = extract_invoice(bob, &onion_message); assert_eq!(invoice, expected_invoice); - assert_eq!(invoice.amount_msats(), 10_000_000); + assert_eq!(invoice.amount().to_msat(), 10_000_000); assert_ne!(invoice.signing_pubkey(), alice_id); assert!(!invoice.payment_paths().is_empty()); for path in invoice.payment_paths() { @@ -980,7 +981,7 @@ fn pays_for_offer_without_blinded_paths() { let offer = alice.node .create_offer_builder().unwrap() .clear_paths() - .amount_msats(10_000_000) + .amount(LightningAmount::from_msat(10_000_000)) .build().unwrap(); assert_eq!(offer.issuer_signing_pubkey(), Some(alice_id)); assert!(offer.paths().is_empty()); @@ -1105,7 +1106,7 @@ fn send_invoice_requests_with_distinct_reply_path() { let offer = alice.node .create_offer_builder() .unwrap() - .amount_msats(10_000_000) + .amount(LightningAmount::from_msat(10_000_000)) .build().unwrap(); assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id)); assert!(!offer.paths().is_empty()); @@ -1239,7 +1240,7 @@ fn creates_and_pays_for_offer_with_retry() { let offer = alice.node .create_offer_builder().unwrap() - .amount_msats(10_000_000) + .amount(LightningAmount::from_msat(10_000_000)) .build().unwrap(); assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id)); assert!(!offer.paths().is_empty()); @@ -1270,7 +1271,7 @@ fn creates_and_pays_for_offer_with_retry() { human_readable_name: None, }, }); - assert_eq!(invoice_request.amount_msats(), Some(10_000_000)); + assert_eq!(invoice_request.amount(), Some(LightningAmount::from_msat(10_000_000))); assert_ne!(invoice_request.payer_signing_pubkey(), bob_id); assert!(check_dummy_hopped_path_length(&reply_path, alice, bob_id, DUMMY_HOPS_PATH_LENGTH)); let onion_message = alice.onion_messenger.next_onion_message_for_peer(bob_id).unwrap(); @@ -1283,7 +1284,7 @@ fn creates_and_pays_for_offer_with_retry() { assert!(bob.onion_messenger.next_onion_message_for_peer(alice_id).is_none()); let (invoice, _) = extract_invoice(bob, &onion_message); - assert_eq!(invoice.amount_msats(), 10_000_000); + assert_eq!(invoice.amount().to_msat(), 10_000_000); assert_ne!(invoice.signing_pubkey(), alice_id); assert!(!invoice.payment_paths().is_empty()); for path in invoice.payment_paths() { @@ -1315,7 +1316,7 @@ fn pays_bolt12_invoice_asynchronously() { let offer = alice.node .create_offer_builder().unwrap() - .amount_msats(10_000_000) + .amount(LightningAmount::from_msat(10_000_000)) .build().unwrap(); let payment_id = PaymentId([1; 32]); @@ -1353,7 +1354,7 @@ fn pays_bolt12_invoice_asynchronously() { }, _ => panic!("No Event::InvoiceReceived"), }; - assert_eq!(invoice.amount_msats(), 10_000_000); + assert_eq!(invoice.amount().to_msat(), 10_000_000); assert_ne!(invoice.signing_pubkey(), alice_id); assert!(!invoice.payment_paths().is_empty()); for path in invoice.payment_paths() { @@ -1407,7 +1408,7 @@ fn creates_offer_with_blinded_path_using_unannounced_introduction_node() { let offer = alice.node .create_offer_builder().unwrap() - .amount_msats(10_000_000) + .amount(LightningAmount::from_msat(10_000_000)) .build().unwrap(); assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id)); assert!(!offer.paths().is_empty()); @@ -1551,7 +1552,7 @@ fn fails_authentication_when_handling_invoice_request() { let offer = alice.node .create_offer_builder() .unwrap() - .amount_msats(10_000_000) + .amount(LightningAmount::from_msat(10_000_000)) .build().unwrap(); assert_eq!(offer.metadata(), None); assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id)); @@ -1584,7 +1585,7 @@ fn fails_authentication_when_handling_invoice_request() { alice.onion_messenger.handle_onion_message(david_id, &onion_message); let (invoice_request, reply_path) = extract_invoice_request(alice, &onion_message); - assert_eq!(invoice_request.amount_msats(), Some(10_000_000)); + assert_eq!(invoice_request.amount(), Some(LightningAmount::from_msat(10_000_000))); assert_ne!(invoice_request.payer_signing_pubkey(), david_id); assert!(check_dummy_hopped_path_length(&reply_path, david, charlie_id, DUMMY_HOPS_PATH_LENGTH)); @@ -1613,7 +1614,7 @@ fn fails_authentication_when_handling_invoice_request() { alice.onion_messenger.handle_onion_message(bob_id, &onion_message); let (invoice_request, reply_path) = extract_invoice_request(alice, &onion_message); - assert_eq!(invoice_request.amount_msats(), Some(10_000_000)); + assert_eq!(invoice_request.amount(), Some(LightningAmount::from_msat(10_000_000))); assert_ne!(invoice_request.payer_signing_pubkey(), david_id); assert!(check_dummy_hopped_path_length(&reply_path, david, charlie_id, DUMMY_HOPS_PATH_LENGTH)); @@ -1661,7 +1662,7 @@ fn fails_authentication_when_handling_invoice_for_offer() { let offer = alice.node .create_offer_builder() .unwrap() - .amount_msats(10_000_000) + .amount(LightningAmount::from_msat(10_000_000)) .build().unwrap(); assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id)); assert!(!offer.paths().is_empty()); @@ -1713,7 +1714,7 @@ fn fails_authentication_when_handling_invoice_for_offer() { alice.onion_messenger.handle_onion_message(bob_id, &onion_message); let (invoice_request, reply_path) = extract_invoice_request(alice, &onion_message); - assert_eq!(invoice_request.amount_msats(), Some(10_000_000)); + assert_eq!(invoice_request.amount(), Some(LightningAmount::from_msat(10_000_000))); assert_ne!(invoice_request.payer_signing_pubkey(), david_id); assert!(check_dummy_hopped_path_length(&reply_path, david, charlie_id, DUMMY_HOPS_PATH_LENGTH)); @@ -1865,7 +1866,7 @@ fn fails_creating_or_paying_for_offer_without_connected_peers() { let absolute_expiry = alice.node.duration_since_epoch() + MAX_SHORT_LIVED_RELATIVE_EXPIRY; let offer = alice.node .create_offer_builder().unwrap() - .amount_msats(10_000_000) + .amount(LightningAmount::from_msat(10_000_000)) .absolute_expiry(absolute_expiry) .build().unwrap(); @@ -2023,7 +2024,7 @@ fn fails_creating_invoice_request_without_blinded_reply_path() { let offer = alice.node .create_offer_builder().unwrap() - .amount_msats(10_000_000) + .amount(LightningAmount::from_msat(10_000_000)) .build().unwrap(); match david.node.pay_for_offer(&offer, None, PaymentId([1; 32]), Default::default()) { @@ -2055,7 +2056,7 @@ fn fails_creating_invoice_request_with_duplicate_payment_id() { let offer = alice.node .create_offer_builder().unwrap() - .amount_msats(10_000_000) + .amount(LightningAmount::from_msat(10_000_000)) .build().unwrap(); let payment_id = PaymentId([1; 32]); @@ -2137,7 +2138,7 @@ fn fails_sending_invoice_without_blinded_payment_paths_for_offer() { let offer = alice.node .create_offer_builder().unwrap() - .amount_msats(10_000_000) + .amount(LightningAmount::from_msat(10_000_000)) .build().unwrap(); let payment_id = PaymentId([1; 32]); @@ -2345,7 +2346,7 @@ fn fails_paying_invoice_with_unknown_required_features() { let offer = alice.node .create_offer_builder().unwrap() - .amount_msats(10_000_000) + .amount(LightningAmount::from_msat(10_000_000)) .build().unwrap(); let payment_id = PaymentId([1; 32]); @@ -2460,7 +2461,7 @@ fn rejects_keysend_to_non_static_invoice_path() { // Pay the invoice via keysend now that we have the preimage and make sure the recipient fails it // due to incorrect payment context. let pay_params = PaymentParameters::from_bolt12_invoice(&invoice); - let route_params = RouteParameters::from_payment_params_and_value(pay_params, amt_msat); + let route_params = RouteParameters::from_payment_params_and_value(pay_params, LightningAmount::from_msat(amt_msat)); let keysend_payment_id = PaymentId([2; 32]); let payment_hash = nodes[0].node.send_spontaneous_payment( Some(payment_preimage), RecipientOnionFields::spontaneous_empty(), keysend_payment_id, @@ -2513,7 +2514,7 @@ fn no_double_pay_with_stale_channelmanager() { let offer = nodes[1].node .create_offer_builder().unwrap() .clear_paths() - .amount_msats(amt_msat) + .amount(LightningAmount::from_msat(amt_msat)) .build().unwrap(); assert_eq!(offer.issuer_signing_pubkey(), Some(bob_id)); assert!(offer.paths().is_empty()); diff --git a/lightning/src/ln/onion_route_tests.rs b/lightning/src/ln/onion_route_tests.rs index 27e0cfafade..ecd9e240cb1 100644 --- a/lightning/src/ln/onion_route_tests.rs +++ b/lightning/src/ln/onion_route_tests.rs @@ -35,6 +35,7 @@ use crate::routing::router::{ RouteParameters, TrampolineHop, }; use crate::sign::{EntropySource, NodeSigner, Recipient}; +use crate::types::amount::LightningAmount; use crate::types::features::{Bolt11InvoiceFeatures, InitFeatures}; use crate::types::payment::{PaymentHash, PaymentSecret}; use crate::util::config::{ChannelConfig, MaxDustHTLCExposure, UserConfig}; @@ -1030,7 +1031,7 @@ fn test_onion_failure() { let amt_to_forward = { let (per_peer_state, mut peer_state); let chan = get_channel_ref!(nodes[1], nodes[2], per_peer_state, peer_state, channels[1].2); - chan.context().get_counterparty_htlc_minimum_msat() - 1 + chan.context().get_counterparty_htlc_minimum().to_msat() - 1 }; let mut bogus_route = route.clone(); let route_len = bogus_route.paths[0].hops.len(); @@ -1966,8 +1967,8 @@ fn test_trampoline_onion_payload_assembly_values() { final_value_msat: amt_msat, }), }; - assert_eq!(path.fee_msat(), 156_000); - assert_eq!(path.final_value_msat(), amt_msat); + assert_eq!(path.fee().to_msat(), 156_000); + assert_eq!(path.final_value().to_msat(), amt_msat); assert_eq!(path.final_cltv_expiry_delta(), None); let payment_secret = PaymentSecret( @@ -2396,7 +2397,10 @@ macro_rules! get_phantom_route { let scorer = test_utils::TestScorer::new(); let first_hops = $nodes[0].node.list_usable_channels(); let network_graph = $nodes[0].network_graph.read_only(); - let route_params = RouteParameters::from_payment_params_and_value(payment_params, $amt); + let route_params = RouteParameters::from_payment_params_and_value( + payment_params, + LightningAmount::from_msat($amt), + ); ( get_route( &$nodes[0].node.get_our_node_id(), diff --git a/lightning/src/ln/outbound_payment.rs b/lightning/src/ln/outbound_payment.rs index 170e4e13830..be788ab3015 100644 --- a/lightning/src/ln/outbound_payment.rs +++ b/lightning/src/ln/outbound_payment.rs @@ -32,6 +32,7 @@ use crate::routing::router::{ RouteParametersConfig, Router, }; use crate::sign::{EntropySource, NodeSigner, Recipient}; +use crate::types::amount::LightningAmount; use crate::types::features::Bolt12InvoiceFeatures; use crate::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret}; use crate::util::errors::APIError; @@ -337,8 +338,8 @@ impl PendingOutboundPayment { ref mut remaining_max_total_routing_fee_msat, .. } = self { let path = path.expect("Removing a failed payment should always come with a path"); - *pending_amt_msat -= path.final_value_msat(); - let path_fee_msat = path.fee_msat(); + *pending_amt_msat -= path.final_value().to_msat(); + let path_fee_msat = path.fee().to_msat(); if let Some(fee_msat) = pending_fee_msat.as_mut() { *fee_msat -= path_fee_msat; } @@ -370,8 +371,8 @@ impl PendingOutboundPayment { ref mut pending_amt_msat, ref mut pending_fee_msat, ref mut remaining_max_total_routing_fee_msat, .. } = self { - *pending_amt_msat += path.final_value_msat(); - let path_fee_msat = path.fee_msat(); + *pending_amt_msat += path.final_value().to_msat(); + let path_fee_msat = path.fee().to_msat(); if let Some(fee_msat) = pending_fee_msat.as_mut() { *fee_msat += path_fee_msat; } @@ -953,7 +954,7 @@ impl OutboundPayments { { let payment_hash = invoice.payment_hash(); - let amount = match (invoice.amount_milli_satoshis(), amount_msats) { + let amount = match (invoice.amount().map(|a| a.to_msat()), amount_msats) { (Some(amt), None) | (None, Some(amt)) => amt, (Some(inv_amt), Some(user_amt)) if user_amt < inv_amt => return Err(Bolt11PaymentError::InvalidAmount), (Some(_), Some(user_amt)) => user_amt, @@ -967,7 +968,7 @@ impl OutboundPayments { let payment_params = PaymentParameters::from_bolt11_invoice(invoice) .with_user_config_ignoring_fee_limit(optional_params.route_params_config); - let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, amount); + let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, LightningAmount::from_msat(amount)); if let Some(max_fee_msat) = optional_params.route_params_config.max_total_routing_fee_msat { route_params.max_total_routing_fee_msat = Some(max_fee_msat); @@ -1008,7 +1009,7 @@ impl OutboundPayments { let mut route_params = RouteParameters::from_payment_params_and_value( PaymentParameters::from_bolt12_invoice(&invoice) - .with_user_config_ignoring_fee_limit(params_config), invoice.amount_msats() + .with_user_config_ignoring_fee_limit(params_config), invoice.amount() ); if let Some(max_fee_msat) = params_config.max_total_routing_fee_msat { route_params.max_total_routing_fee_msat = Some(max_fee_msat); @@ -1193,8 +1194,10 @@ impl OutboundPayments { PaymentHash(Sha256::hash(&keysend_preimage.0).to_byte_array()); let pay_params = PaymentParameters::from_static_invoice(invoice) .with_user_config_ignoring_fee_limit(*route_params_config); - let mut route_params = - RouteParameters::from_payment_params_and_value(pay_params, amount_msat); + let mut route_params = RouteParameters::from_payment_params_and_value( + pay_params, + LightningAmount::from_msat(amount_msat), + ); route_params.max_total_routing_fee_msat = route_params_config.max_total_routing_fee_msat; @@ -2105,7 +2108,7 @@ impl OutboundPayments { continue 'path_check; } } - total_value += path.final_value_msat(); + total_value += path.final_value().to_msat(); path_errs.push(Ok(())); } if path_errs.iter().any(|e| e.is_err()) { @@ -2135,8 +2138,8 @@ impl OutboundPayments { for (res, path) in results.iter().zip(route.paths.iter()) { if res.is_ok() { has_ok = true; - total_ok_fees_msat += path.fee_msat(); - total_ok_amt_sent_msat += path.final_value_msat(); + total_ok_fees_msat += path.fee().to_msat(); + total_ok_amt_sent_msat += path.final_value().to_msat(); } if res.is_err() { has_err = true; } if let &Err(APIError::MonitorUpdateInProgress) = res { @@ -2144,8 +2147,8 @@ impl OutboundPayments { // PartialFailure. has_err = true; has_ok = true; - total_ok_fees_msat += path.fee_msat(); - total_ok_amt_sent_msat += path.final_value_msat(); + total_ok_fees_msat += path.fee().to_msat(); + total_ok_amt_sent_msat += path.final_value().to_msat(); } else if res.is_err() { has_unsent = true; } @@ -2615,8 +2618,8 @@ impl OutboundPayments { &self, payment_id: PaymentId, payment_hash: PaymentHash, session_priv_bytes: [u8; 32], path: &Path, best_block_height: u32, logger: &WithContext, ) { - let path_amt = path.final_value_msat(); - let path_fee = path.fee_msat(); + let path_amt = path.final_value().to_msat(); + let path_fee = path.fee().to_msat(); macro_rules! new_retryable { () => { @@ -2741,7 +2744,7 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment, (7, route_params_config, (default_value, ( _max_total_routing_fee_msat.map_or( RouteParametersConfig::default(), - |fee_msat| RouteParametersConfig::default().with_max_total_routing_fee_msat(fee_msat) + |fee_msat| RouteParametersConfig::default().with_max_total_routing_fee(LightningAmount::from_msat(fee_msat)) ) ))), }, @@ -2757,7 +2760,7 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment, (5, route_params_config, (default_value, ( _max_total_routing_fee_msat.map_or( RouteParametersConfig::default(), - |fee_msat| RouteParametersConfig::default().with_max_total_routing_fee_msat(fee_msat) + |fee_msat| RouteParametersConfig::default().with_max_total_routing_fee(LightningAmount::from_msat(fee_msat)) ) ))), }, @@ -2788,7 +2791,7 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment, (5, route_params_config, (default_value, ( _max_total_routing_fee_msat.map_or( RouteParametersConfig::default(), - |fee_msat| RouteParametersConfig::default().with_max_total_routing_fee_msat(fee_msat) + |fee_msat| RouteParametersConfig::default().with_max_total_routing_fee(LightningAmount::from_msat(fee_msat)) ) ))), (6, amount_msats, required), @@ -2824,6 +2827,7 @@ mod tests { RouteParametersConfig, }; use crate::sync::{Arc, Mutex, RwLock}; + use crate::types::amount::LightningAmount; use crate::types::features::{Bolt12InvoiceFeatures, ChannelFeatures, NodeFeatures}; use crate::types::payment::{PaymentHash, PaymentPreimage}; use crate::util::errors::APIError; @@ -2881,7 +2885,7 @@ mod tests { PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()), 0 ).with_expiry_time(past_expiry_time); - let expired_route_params = RouteParameters::from_payment_params_and_value(payment_params, 0); + let expired_route_params = RouteParameters::from_payment_params_and_value(payment_params, LightningAmount::ZERO); let pending_events = Mutex::new(VecDeque::new()); if on_retry { outbound_payments.add_new_pending_payment(PaymentHash([0; 32]), RecipientOnionFields::spontaneous_empty(), @@ -2925,7 +2929,7 @@ mod tests { let payment_params = PaymentParameters::from_node_id( PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()), 0); - let route_params = RouteParameters::from_payment_params_and_value(payment_params, 0); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, LightningAmount::ZERO); router.expect_find_route(route_params.clone(), Err("")); let pending_events = Mutex::new(VecDeque::new()); @@ -2967,7 +2971,7 @@ mod tests { let sender_pk = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let receiver_pk = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[43; 32]).unwrap()); let payment_params = PaymentParameters::from_node_id(sender_pk, 0); - let route_params = RouteParameters::from_payment_params_and_value(payment_params.clone(), 0); + let route_params = RouteParameters::from_payment_params_and_value(payment_params.clone(), LightningAmount::ZERO); let failed_scid = 42; let route = Route { paths: vec![Path { hops: vec![RouteHop { @@ -3203,7 +3207,7 @@ mod tests { let created_at = now() - DEFAULT_RELATIVE_EXPIRY; let invoice = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build().unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() .build_and_sign().unwrap() @@ -3252,7 +3256,7 @@ mod tests { let expiration = StaleExpiration::AbsoluteTimeout(Duration::from_secs(100)); let invoice = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build().unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() .build_and_sign().unwrap() @@ -3260,7 +3264,7 @@ mod tests { .build().unwrap() .sign(recipient_sign).unwrap(); - let route_params_config = RouteParametersConfig::default().with_max_total_routing_fee_msat(invoice.amount_msats() / 100 + 50_000); + let route_params_config = RouteParametersConfig::default().with_max_total_routing_fee(LightningAmount::from_msat(invoice.amount().to_msat() / 100 + 50_000)); assert!( outbound_payments.add_new_awaiting_invoice( @@ -3272,7 +3276,7 @@ mod tests { let route_params = RouteParameters::from_payment_params_and_value( PaymentParameters::from_bolt12_invoice(&invoice), - invoice.amount_msats(), + invoice.amount(), ); router.expect_find_route(route_params, Err("")); @@ -3317,7 +3321,7 @@ mod tests { let expiration = StaleExpiration::AbsoluteTimeout(Duration::from_secs(100)); let invoice = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build().unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() .build_and_sign().unwrap() @@ -3327,7 +3331,7 @@ mod tests { let route_params = RouteParameters { payment_params: PaymentParameters::from_bolt12_invoice(&invoice), - final_value_msat: invoice.amount_msats(), + final_value_msat: invoice.amount().to_msat(), max_total_routing_fee_msat: Some(1234), }; router.expect_find_route( @@ -3341,7 +3345,7 @@ mod tests { node_features: NodeFeatures::empty(), short_channel_id: 42, channel_features: ChannelFeatures::empty(), - fee_msat: invoice.amount_msats(), + fee_msat: invoice.amount().to_msat(), cltv_expiry_delta: 0, maybe_announced_channel: true, } @@ -3365,7 +3369,7 @@ mod tests { assert!(!outbound_payments.has_pending_payments()); assert!(pending_events.lock().unwrap().is_empty()); - let route_params_config = RouteParametersConfig::default().with_max_total_routing_fee_msat(1234); + let route_params_config = RouteParametersConfig::default().with_max_total_routing_fee(LightningAmount::from_msat(1234)); assert!( outbound_payments.add_new_awaiting_invoice( @@ -3406,7 +3410,7 @@ mod tests { let payment_id = PaymentId([1; 32]); OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build().unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) .unwrap() diff --git a/lightning/src/ln/payment_tests.rs b/lightning/src/ln/payment_tests.rs index 6e47e21ca8b..38256141f0a 100644 --- a/lightning/src/ln/payment_tests.rs +++ b/lightning/src/ln/payment_tests.rs @@ -43,6 +43,7 @@ use crate::routing::router::{ }; use crate::routing::scoring::ChannelUsage; use crate::sign::EntropySource; +use crate::types::amount::LightningAmount; use crate::types::features::{Bolt11InvoiceFeatures, ChannelTypeFeatures}; use crate::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret}; use crate::types::string::UntrustedString; @@ -248,11 +249,13 @@ fn mpp_retry_overpay() { // Check we overpay on the second path which we're about to fail. assert_eq!(chan_1_update.contents.fee_proportional_millionths, 0); - let overpaid_amount_1 = route.paths[0].fee_msat() as u32 - chan_1_update.contents.fee_base_msat; + let overpaid_amount_1 = + route.paths[0].fee().to_msat() as u32 - chan_1_update.contents.fee_base_msat; assert_eq!(overpaid_amount_1, 0); assert_eq!(chan_2_update.contents.fee_proportional_millionths, 0); - let overpaid_amount_2 = route.paths[1].fee_msat() as u32 - chan_2_update.contents.fee_base_msat; + let overpaid_amount_2 = + route.paths[1].fee().to_msat() as u32 - chan_2_update.contents.fee_base_msat; let total_overpaid_amount = overpaid_amount_1 + overpaid_amount_2; @@ -301,7 +304,7 @@ fn mpp_retry_overpay() { send_payment(&nodes[3], &[&nodes[2]], 38_000_000); // Retry the second half of the payment and make sure it succeeds. - let first_path_value = route.paths[0].final_value_msat(); + let first_path_value = route.paths[0].final_value().to_msat(); assert_eq!(first_path_value, 36_000_000); route.paths.remove(0); @@ -452,7 +455,7 @@ fn do_test_keysend_payments(public_node: bool) { } let route_params = RouteParameters::from_payment_params_and_value( PaymentParameters::for_keysend(node_b_id, 40, false), - 10000, + LightningAmount::from_msat(10000), ); { @@ -502,7 +505,7 @@ fn test_mpp_keysend() { let recv_value = 15_000_000; let route_params = RouteParameters::from_payment_params_and_value( PaymentParameters::for_keysend(node_d_id, 40, true), - recv_value, + LightningAmount::from_msat(recv_value), ); let preimage = Some(PaymentPreimage([42; 32])); @@ -545,7 +548,7 @@ fn test_fulfill_hold_times() { let recv_value = 5_000_000; let route_params = RouteParameters::from_payment_params_and_value( PaymentParameters::for_keysend(node_c_id, 40, true), - recv_value, + LightningAmount::from_msat(recv_value), ); let preimage = Some(PaymentPreimage([42; 32])); @@ -1509,7 +1512,10 @@ fn get_ldk_payment_preimage() { let scorer = test_utils::TestScorer::new(); let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); - let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); + let route_params = RouteParameters::from_payment_params_and_value( + payment_params, + LightningAmount::from_msat(amt_msat), + ); let first_hops = nodes[0].node.list_usable_channels(); let route = get_route( &node_a_id, @@ -1735,7 +1741,10 @@ fn preflight_probes_yield_event_skip_private_hop() { .unwrap(); let recv_value = 50_000_000; - let route_params = RouteParameters::from_payment_params_and_value(payment_params, recv_value); + let route_params = RouteParameters::from_payment_params_and_value( + payment_params, + LightningAmount::from_msat(recv_value), + ); let res = nodes[0].node.send_preflight_probes(route_params, None).unwrap(); let expected_route: &[(&[&Node], PaymentHash)] = @@ -1786,7 +1795,10 @@ fn preflight_probes_yield_event() { .unwrap(); let recv_value = 50_000_000; - let route_params = RouteParameters::from_payment_params_and_value(payment_params, recv_value); + let route_params = RouteParameters::from_payment_params_and_value( + payment_params, + LightningAmount::from_msat(recv_value), + ); let res = nodes[0].node.send_preflight_probes(route_params, None).unwrap(); let expected_route: &[(&[&Node], PaymentHash)] = @@ -1839,7 +1851,10 @@ fn preflight_probes_yield_event_and_skip() { .unwrap(); let recv_value = 80_000_000; - let route_params = RouteParameters::from_payment_params_and_value(payment_params, recv_value); + let route_params = RouteParameters::from_payment_params_and_value( + payment_params, + LightningAmount::from_msat(recv_value), + ); let res = nodes[0].node.send_preflight_probes(route_params, None).unwrap(); let expected_route: &[(&[&Node], PaymentHash)] = @@ -2040,7 +2055,7 @@ fn test_trivial_inflight_htlc_tracking() { let channel_1 = get_channel_ref!(&nodes[0], nodes[1], per_peer_lock, peer_state_lock, chan_1_id); - let chan_1_used_liquidity = inflight_htlcs.used_liquidity_msat( + let chan_1_used_liquidity = inflight_htlcs.used_liquidity( &NodeId::from_pubkey(&node_a_id), &NodeId::from_pubkey(&node_b_id), channel_1.funding().get_short_channel_id().unwrap(), @@ -2053,7 +2068,7 @@ fn test_trivial_inflight_htlc_tracking() { let channel_2 = get_channel_ref!(&nodes[1], nodes[2], per_peer_lock, peer_state_lock, chan_2_id); - let chan_2_used_liquidity = inflight_htlcs.used_liquidity_msat( + let chan_2_used_liquidity = inflight_htlcs.used_liquidity( &NodeId::from_pubkey(&node_b_id), &NodeId::from_pubkey(&node_c_id), channel_2.funding().get_short_channel_id().unwrap(), @@ -2081,13 +2096,13 @@ fn test_trivial_inflight_htlc_tracking() { let channel_1 = get_channel_ref!(&nodes[0], nodes[1], per_peer_lock, peer_state_lock, chan_1_id); - let chan_1_used_liquidity = inflight_htlcs.used_liquidity_msat( + let chan_1_used_liquidity = inflight_htlcs.used_liquidity( &NodeId::from_pubkey(&node_a_id), &NodeId::from_pubkey(&node_b_id), channel_1.funding().get_short_channel_id().unwrap(), ); // First hop accounts for expected 1000 msat fee - assert_eq!(chan_1_used_liquidity, Some(501000)); + assert_eq!(chan_1_used_liquidity, Some(LightningAmount::from_msat(501000))); } { let mut per_peer_lock; @@ -2095,13 +2110,13 @@ fn test_trivial_inflight_htlc_tracking() { let channel_2 = get_channel_ref!(&nodes[1], nodes[2], per_peer_lock, peer_state_lock, chan_2_id); - let chan_2_used_liquidity = inflight_htlcs.used_liquidity_msat( + let chan_2_used_liquidity = inflight_htlcs.used_liquidity( &NodeId::from_pubkey(&node_b_id), &NodeId::from_pubkey(&node_c_id), channel_2.funding().get_short_channel_id().unwrap(), ); - assert_eq!(chan_2_used_liquidity, Some(500000)); + assert_eq!(chan_2_used_liquidity, Some(LightningAmount::from_msat(500000))); } let pending_payments = nodes[0].node.list_recent_payments(); assert_eq!(pending_payments.len(), 1); @@ -2123,7 +2138,7 @@ fn test_trivial_inflight_htlc_tracking() { let channel_1 = get_channel_ref!(&nodes[0], nodes[1], per_peer_lock, peer_state_lock, chan_1_id); - let chan_1_used_liquidity = inflight_htlcs.used_liquidity_msat( + let chan_1_used_liquidity = inflight_htlcs.used_liquidity( &NodeId::from_pubkey(&node_a_id), &NodeId::from_pubkey(&node_b_id), channel_1.funding().get_short_channel_id().unwrap(), @@ -2136,7 +2151,7 @@ fn test_trivial_inflight_htlc_tracking() { let channel_2 = get_channel_ref!(&nodes[1], nodes[2], per_peer_lock, peer_state_lock, chan_2_id); - let chan_2_used_liquidity = inflight_htlcs.used_liquidity_msat( + let chan_2_used_liquidity = inflight_htlcs.used_liquidity( &NodeId::from_pubkey(&node_b_id), &NodeId::from_pubkey(&node_c_id), channel_2.funding().get_short_channel_id().unwrap(), @@ -2186,13 +2201,13 @@ fn test_holding_cell_inflight_htlcs() { let channel = get_channel_ref!(&nodes[0], nodes[1], per_peer_lock, peer_state_lock, channel_id); - let used_liquidity = inflight_htlcs.used_liquidity_msat( + let used_liquidity = inflight_htlcs.used_liquidity( &NodeId::from_pubkey(&node_a_id), &NodeId::from_pubkey(&node_b_id), channel.funding().get_short_channel_id().unwrap(), ); - assert_eq!(used_liquidity, Some(2000000)); + assert_eq!(used_liquidity, Some(LightningAmount::from_msat(2000000))); } // Clear pending events so test doesn't throw a "Had excess message on node..." error @@ -2247,7 +2262,10 @@ fn do_test_intercepted_payment(test: InterceptTest) { .unwrap() .with_bolt11_features(nodes[2].node.bolt11_invoice_features()) .unwrap(); - let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); + let route_params = RouteParameters::from_payment_params_and_value( + payment_params, + LightningAmount::from_msat(amt_msat), + ); let route = get_route( &node_a_id, &route_params, @@ -2334,7 +2352,10 @@ fn do_test_intercepted_payment(test: InterceptTest) { expect_payment_failed_conditions(&nodes[0], hash, false, fail_conditions); } else if test == InterceptTest::Forward { // Check that we'll fail as expected when sending to a channel that isn't in `ChannelReady` yet. - let temp_id = nodes[1].node.create_channel(node_c_id, 100_000, 0, 42, None, None).unwrap(); + let temp_id = nodes[1] + .node + .create_channel(node_c_id, 100_000, LightningAmount::from_msat(0), 42, None, None) + .unwrap(); let unusable_chan_err = nodes[1].node.forward_intercepted_htlc(intercept_id, &temp_id, node_c_id, outbound_amt); let err = format!( @@ -2494,7 +2515,10 @@ fn do_accept_underpaying_htlcs_config(num_mpp_parts: usize) { .unwrap() .with_bolt11_features(nodes[2].node.bolt11_invoice_features()) .unwrap(); - let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); + let route_params = RouteParameters::from_payment_params_and_value( + payment_params, + LightningAmount::from_msat(amt_msat), + ); let (payment_hash, payment_secret) = nodes[2].node.create_inbound_payment(Some(amt_msat), 60 * 60, None).unwrap(); @@ -2652,7 +2676,10 @@ fn do_automatic_retries(test: AutoRetry) { .with_expiry_time(payment_expiry_secs as u64) .with_bolt11_features(invoice_features) .unwrap(); - let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); + let route_params = RouteParameters::from_payment_params_and_value( + payment_params, + LightningAmount::from_msat(amt_msat), + ); let (_, hash, preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], amt_msat); @@ -2909,7 +2936,10 @@ fn auto_retry_partial_failure() { .unwrap(); // Configure the initial send path - let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); + let mut route_params = RouteParameters::from_payment_params_and_value( + payment_params, + LightningAmount::from_msat(amt_msat), + ); route_params.max_total_routing_fee_msat = None; let send_route = Route { @@ -2946,8 +2976,10 @@ fn auto_retry_partial_failure() { // Configure the retry1 paths let mut payment_params = route_params.payment_params.clone(); payment_params.previously_failed_channels.push(chan_2_id); - let mut retry_1_params = - RouteParameters::from_payment_params_and_value(payment_params, amt_msat / 2); + let mut retry_1_params = RouteParameters::from_payment_params_and_value( + payment_params, + LightningAmount::from_msat(amt_msat / 2), + ); retry_1_params.max_total_routing_fee_msat = None; let retry_1_route = Route { @@ -2984,8 +3016,10 @@ fn auto_retry_partial_failure() { // Configure the retry2 path let mut payment_params = retry_1_params.payment_params.clone(); payment_params.previously_failed_channels.push(chan_3_id); - let mut retry_2_params = - RouteParameters::from_payment_params_and_value(payment_params, amt_msat / 4); + let mut retry_2_params = RouteParameters::from_payment_params_and_value( + payment_params, + LightningAmount::from_msat(amt_msat / 4), + ); retry_2_params.max_total_routing_fee_msat = None; let retry_2_route = Route { @@ -3148,7 +3182,10 @@ fn auto_retry_zero_attempts_send_error() { .with_expiry_time(payment_expiry_secs as u64) .with_bolt11_features(invoice_features) .unwrap(); - let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); + let route_params = RouteParameters::from_payment_params_and_value( + payment_params, + LightningAmount::from_msat(amt_msat), + ); // Override the route search to return a route, rather than failing at the route-finding step. let send_route = Route { @@ -3214,7 +3251,10 @@ fn fails_paying_after_rejected_by_payee() { .with_expiry_time(payment_expiry_secs as u64) .with_bolt11_features(invoice_features) .unwrap(); - let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); + let route_params = RouteParameters::from_payment_params_and_value( + payment_params, + LightningAmount::from_msat(amt_msat), + ); let onion = RecipientOnionFields::secret_only(payment_secret); let id = PaymentId(payment_hash.0); @@ -3265,8 +3305,10 @@ fn retry_multi_path_single_failed_payment() { .with_expiry_time(payment_expiry_secs as u64) .with_bolt11_features(invoice_features) .unwrap(); - let mut route_params = - RouteParameters::from_payment_params_and_value(payment_params.clone(), amt_msat); + let mut route_params = RouteParameters::from_payment_params_and_value( + payment_params.clone(), + LightningAmount::from_msat(amt_msat), + ); route_params.max_total_routing_fee_msat = None; let chans = nodes[0].node.list_usable_channels(); @@ -3306,7 +3348,10 @@ fn retry_multi_path_single_failed_payment() { let mut pay_params = route.route_params.clone().unwrap().payment_params; pay_params.previously_failed_channels.push(chans[1].short_channel_id.unwrap()); - let mut retry_params = RouteParameters::from_payment_params_and_value(pay_params, 100_000_000); + let mut retry_params = RouteParameters::from_payment_params_and_value( + pay_params, + LightningAmount::from_msat(100_000_000), + ); retry_params.max_total_routing_fee_msat = None; route.route_params = Some(retry_params.clone()); nodes[0].router.expect_find_route(retry_params, Ok(route.clone())); @@ -3383,7 +3428,10 @@ fn immediate_retry_on_failure() { .with_expiry_time(payment_expiry_secs as u64) .with_bolt11_features(invoice_features) .unwrap(); - let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); + let route_params = RouteParameters::from_payment_params_and_value( + payment_params, + LightningAmount::from_msat(amt_msat), + ); let chans = nodes[0].node.list_usable_channels(); let mut route = Route { @@ -3409,7 +3457,10 @@ fn immediate_retry_on_failure() { route.paths[1].hops[0].fee_msat = 50_000_001; let mut pay_params = route_params.payment_params.clone(); pay_params.previously_failed_channels.push(chans[0].short_channel_id.unwrap()); - let retry_params = RouteParameters::from_payment_params_and_value(pay_params, amt_msat); + let retry_params = RouteParameters::from_payment_params_and_value( + pay_params, + LightningAmount::from_msat(amt_msat), + ); route.route_params = Some(retry_params.clone()); nodes[0].router.expect_find_route(retry_params, Ok(route.clone())); @@ -3482,7 +3533,10 @@ fn no_extra_retries_on_back_to_back_fail() { .with_expiry_time(payment_expiry_secs as u64) .with_bolt11_features(invoice_features) .unwrap(); - let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); + let mut route_params = RouteParameters::from_payment_params_and_value( + payment_params, + LightningAmount::from_msat(amt_msat), + ); route_params.max_total_routing_fee_msat = None; let mut route = Route { @@ -3543,8 +3597,10 @@ fn no_extra_retries_on_back_to_back_fail() { // On retry, we'll only return one path route.paths.remove(1); route.paths[0].hops[1].fee_msat = amt_msat; - let mut retry_params = - RouteParameters::from_payment_params_and_value(second_payment_params, amt_msat); + let mut retry_params = RouteParameters::from_payment_params_and_value( + second_payment_params, + LightningAmount::from_msat(amt_msat), + ); retry_params.max_total_routing_fee_msat = None; route.route_params = Some(retry_params.clone()); nodes[0].router.expect_find_route(retry_params, Ok(route.clone())); @@ -3727,7 +3783,10 @@ fn test_simple_partial_retry() { .with_expiry_time(payment_expiry_secs as u64) .with_bolt11_features(invoice_features) .unwrap(); - let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); + let mut route_params = RouteParameters::from_payment_params_and_value( + payment_params, + LightningAmount::from_msat(amt_msat), + ); route_params.max_total_routing_fee_msat = None; let mut route = Route { @@ -3788,8 +3847,10 @@ fn test_simple_partial_retry() { second_payment_params.previously_failed_channels = vec![chan_2_scid]; // On retry, we'll only be asked for one path (or 100k sats) route.paths.remove(0); - let mut retry_params = - RouteParameters::from_payment_params_and_value(second_payment_params, amt_msat / 2); + let mut retry_params = RouteParameters::from_payment_params_and_value( + second_payment_params, + LightningAmount::from_msat(amt_msat / 2), + ); retry_params.max_total_routing_fee_msat = None; route.route_params = Some(retry_params.clone()); nodes[0].router.expect_find_route(retry_params, Ok(route.clone())); @@ -4290,7 +4351,10 @@ fn do_claim_from_closed_chan(fail_payment: bool) { .unwrap(); let amt_msat = 10_000_000; - let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); + let mut route_params = RouteParameters::from_payment_params_and_value( + payment_params, + LightningAmount::from_msat(amt_msat), + ); let inflight = nodes[0].node.compute_inflight_htlcs(); let mut route = nodes[0].router.find_route(&node_a_id, &route_params, None, inflight).unwrap(); @@ -4833,7 +4897,10 @@ fn do_test_payment_metadata_consistency(do_reload: bool, do_modify: bool) { let payment_params = PaymentParameters::from_node_id(node_d_id, TEST_FINAL_CLTV) .with_bolt11_features(nodes[1].node.bolt11_invoice_features()) .unwrap(); - let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); + let mut route_params = RouteParameters::from_payment_params_and_value( + payment_params, + LightningAmount::from_msat(amt_msat), + ); // Send the MPP payment, delivering the updated commitment state to nodes[1]. let onion = RecipientOnionFields { @@ -5096,7 +5163,10 @@ fn peel_payment_onion_custom_tlvs() { let amt_msat = 1000; let payment_params = PaymentParameters::for_keysend(node_b_id, TEST_FINAL_CLTV, false); - let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); + let route_params = RouteParameters::from_payment_params_and_value( + payment_params, + LightningAmount::from_msat(amt_msat), + ); let route = functional_test_utils::get_route(&nodes[0], &route_params).unwrap(); let mut recipient_onion = RecipientOnionFields::spontaneous_empty() .with_custom_tlvs(RecipientCustomTlvs::new(vec![(414141, vec![42; 1200])]).unwrap()); @@ -5185,8 +5255,10 @@ fn test_non_strict_forwarding() { let payment_params = PaymentParameters::from_node_id(node_c_id, TEST_FINAL_CLTV) .with_bolt11_features(nodes[2].node.bolt11_invoice_features()) .unwrap(); - let route_params = - RouteParameters::from_payment_params_and_value(payment_params, payment_value); + let route_params = RouteParameters::from_payment_params_and_value( + payment_params, + LightningAmount::from_msat(payment_value), + ); let route = functional_test_utils::get_route(&nodes[0], &route_params).unwrap(); // Send 4 payments over the same route. diff --git a/lightning/src/ln/priv_short_conf_tests.rs b/lightning/src/ln/priv_short_conf_tests.rs index 9d30d749aa2..90e26dce6d1 100644 --- a/lightning/src/ln/priv_short_conf_tests.rs +++ b/lightning/src/ln/priv_short_conf_tests.rs @@ -24,6 +24,7 @@ use crate::ln::outbound_payment::RecipientOnionFields; use crate::ln::types::ChannelId; use crate::routing::gossip::RoutingFees; use crate::routing::router::{PaymentParameters, RouteHint, RouteHintHop}; +use crate::types::amount::LightningAmount; use crate::types::features::ChannelTypeFeatures; use crate::util::config::{MaxDustHTLCExposure, UserConfig}; use crate::util::ser::Writeable; @@ -393,7 +394,14 @@ fn test_scid_privacy_on_pub_channel() { scid_privacy_cfg.channel_handshake_config.negotiate_scid_privacy = true; nodes[0] .node - .create_channel(node_b_id, 100000, 10001, 42, None, Some(scid_privacy_cfg)) + .create_channel( + node_b_id, + 100000, + LightningAmount::from_msat(10001), + 42, + None, + Some(scid_privacy_cfg), + ) .unwrap(); let mut open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); @@ -422,7 +430,14 @@ fn test_scid_privacy_negotiation() { scid_privacy_cfg.channel_handshake_config.negotiate_scid_privacy = true; nodes[0] .node - .create_channel(node_b_id, 100000, 10001, 42, None, Some(scid_privacy_cfg)) + .create_channel( + node_b_id, + 100000, + LightningAmount::from_msat(10001), + 42, + None, + Some(scid_privacy_cfg), + ) .unwrap(); let init_open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); @@ -495,7 +510,14 @@ fn test_inbound_scid_privacy() { no_announce_cfg.channel_handshake_config.negotiate_scid_privacy = true; nodes[1] .node - .create_channel(node_c_id, 100_000, 10_000, 42, None, Some(no_announce_cfg)) + .create_channel( + node_c_id, + 100_000, + LightningAmount::from_msat(10_000), + 42, + None, + Some(no_announce_cfg), + ) .unwrap(); let mut open_channel = get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, node_c_id); @@ -808,7 +830,17 @@ fn test_0conf_channel_with_async_monitor() { create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0); chan_config.channel_handshake_config.announce_for_forwarding = false; - nodes[0].node.create_channel(node_b_id, 100000, 10001, 42, None, Some(chan_config)).unwrap(); + nodes[0] + .node + .create_channel( + node_b_id, + 100000, + LightningAmount::from_msat(10001), + 42, + None, + Some(chan_config), + ) + .unwrap(); let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); nodes[1].node.handle_open_channel(node_a_id, &open_channel); @@ -1318,7 +1350,10 @@ fn test_zero_conf_accept_reject() { let node_b_id = nodes[1].node.get_our_node_id(); // 1. First try the non-0conf method to manually accept - nodes[0].node.create_channel(node_b_id, 100000, 10001, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel(node_b_id, 100000, LightningAmount::from_msat(10001), 42, None, None) + .unwrap(); let mut open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); @@ -1354,7 +1389,10 @@ fn test_zero_conf_accept_reject() { } // 2. Try again with the 0conf method to manually accept - nodes[0].node.create_channel(node_b_id, 100000, 10001, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel(node_b_id, 100000, LightningAmount::from_msat(10001), 42, None, None) + .unwrap(); let mut open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); @@ -1403,7 +1441,10 @@ fn test_connect_before_funding() { let node_a_id = nodes[0].node.get_our_node_id(); let node_b_id = nodes[1].node.get_our_node_id(); - nodes[0].node.create_channel(node_b_id, 100_000, 10_001, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel(node_b_id, 100_000, LightningAmount::from_msat(10_001), 42, None, None) + .unwrap(); let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); nodes[1].node.handle_open_channel(node_a_id, &open_channel); diff --git a/lightning/src/ln/reload_tests.rs b/lightning/src/ln/reload_tests.rs index 6bd190ae12c..fb585031289 100644 --- a/lightning/src/ln/reload_tests.rs +++ b/lightning/src/ln/reload_tests.rs @@ -253,7 +253,7 @@ fn test_manager_serialize_deserialize_events() { let push_msat = 10001; let node_a = nodes.remove(0); let node_b = nodes.remove(0); - node_a.node.create_channel(node_b.node.get_our_node_id(), channel_value, push_msat, 42, None, None).unwrap(); + node_a.node.create_channel(node_b.node.get_our_node_id(), channel_value, LightningAmount::from_msat(push_msat), 42, None, None).unwrap(); handle_and_accept_open_channel(&node_b, node_a.node.get_our_node_id(), &get_event_msg!(node_a, MessageSendEvent::SendOpenChannel, node_b.node.get_our_node_id())); node_a.node.handle_accept_channel(node_b.node.get_our_node_id(), &get_event_msg!(node_b, MessageSendEvent::SendAcceptChannel, node_a.node.get_our_node_id())); @@ -542,7 +542,7 @@ fn do_test_data_loss_protect(reconnect_panicing: bool, substantially_old: bool, // revoked at least two revocations ago, not the latest revocation. Here, we use // `not_stale` to test the boundary condition. let pay_params = PaymentParameters::for_keysend(nodes[1].node.get_our_node_id(), 100, false); - let route_params = RouteParameters::from_payment_params_and_value(pay_params, 40000); + let route_params = RouteParameters::from_payment_params_and_value(pay_params, LightningAmount::from_msat(40000)); nodes[0].node.send_spontaneous_payment(None, RecipientOnionFields::spontaneous_empty(), PaymentId([0; 32]), route_params, Retry::Attempts(0)).unwrap(); check_added_monitors(&nodes[0], 1); let update_add_commit = SendEvent::from_node(&nodes[0]); @@ -1405,7 +1405,7 @@ fn test_htlc_localremoved_persistence() { let _chan = create_chan_between_nodes(&nodes[0], &nodes[1]); let route_params = RouteParameters::from_payment_params_and_value( - PaymentParameters::for_keysend(payee_pubkey, 40, false), 10_000); + PaymentParameters::for_keysend(payee_pubkey, 40, false), LightningAmount::from_msat(10_000)); let route = find_route( &nodes[0], &route_params ).unwrap(); diff --git a/lightning/src/ln/shutdown_tests.rs b/lightning/src/ln/shutdown_tests.rs index 50c8f72f9be..5c74b80a4bd 100644 --- a/lightning/src/ln/shutdown_tests.rs +++ b/lightning/src/ln/shutdown_tests.rs @@ -24,6 +24,7 @@ use crate::ln::types::ChannelId; use crate::prelude::*; use crate::routing::router::{get_route, PaymentParameters, RouteParameters}; use crate::sign::{EntropySource, SignerProvider}; +use crate::types::amount::LightningAmount; use crate::types::string::UntrustedString; use crate::util::config::UserConfig; use crate::util::errors::APIError; @@ -307,7 +308,10 @@ fn shutdown_on_unfunded_channel() { let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let node_b_id = nodes[1].node.get_our_node_id(); - nodes[0].node.create_channel(node_b_id, 1_000_000, 100_000, 0, None, None).unwrap(); + nodes[0] + .node + .create_channel(node_b_id, 1_000_000, LightningAmount::from_msat(100_000), 0, None, None) + .unwrap(); let open_chan = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); // Create a dummy P2WPKH script @@ -333,8 +337,10 @@ fn close_on_unfunded_channel() { let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let node_b_id = nodes[1].node.get_our_node_id(); - let chan_id = - nodes[0].node.create_channel(node_b_id, 1_000_000, 100_000, 0, None, None).unwrap(); + let chan_id = nodes[0] + .node + .create_channel(node_b_id, 1_000_000, LightningAmount::from_msat(100_000), 0, None, None) + .unwrap(); let _open_chan = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); nodes[0].node.close_channel(&chan_id, &node_b_id).unwrap(); @@ -415,7 +421,10 @@ fn updates_shutdown_wait() { let payment_params_1 = PaymentParameters::from_node_id(node_b_id, TEST_FINAL_CLTV) .with_bolt11_features(nodes[1].node.bolt11_invoice_features()) .unwrap(); - let route_params = RouteParameters::from_payment_params_and_value(payment_params_1, 100_000); + let route_params = RouteParameters::from_payment_params_and_value( + payment_params_1, + LightningAmount::from_msat(100_000), + ); let route_1 = get_route( &node_a_id, &route_params, @@ -430,7 +439,10 @@ fn updates_shutdown_wait() { let payment_params_2 = PaymentParameters::from_node_id(node_a_id, TEST_FINAL_CLTV) .with_bolt11_features(nodes[0].node.bolt11_invoice_features()) .unwrap(); - let route_params = RouteParameters::from_payment_params_and_value(payment_params_2, 100_000); + let route_params = RouteParameters::from_payment_params_and_value( + payment_params_2, + LightningAmount::from_msat(100_000), + ); let route_2 = get_route( &node_b_id, &route_params, @@ -541,7 +553,7 @@ fn do_htlc_fail_async_shutdown(blinded_recipient: bool) { } else { RouteParameters::from_payment_params_and_value( PaymentParameters::from_node_id(node_c_id, TEST_FINAL_CLTV), - amt_msat, + LightningAmount::from_msat(amt_msat), ) }; let onion = RecipientOnionFields::secret_only(our_payment_secret); @@ -988,7 +1000,10 @@ fn test_unsupported_anysegwit_upfront_shutdown_script() { let anysegwit_shutdown_script = Builder::new().push_int(16).push_slice(&[0, 40]).into_script(); // Check script when handling an open_channel message - nodes[0].node.create_channel(node_b_id, 100000, 10001, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel(node_b_id, 100000, LightningAmount::from_msat(10001), 42, None, None) + .unwrap(); let mut open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); open_channel.common_fields.shutdown_scriptpubkey = Some(anysegwit_shutdown_script.clone()); nodes[1].node.handle_open_channel(node_a_id, &open_channel); @@ -1029,7 +1044,10 @@ fn test_unsupported_anysegwit_upfront_shutdown_script() { let node_b_id = nodes[1].node.get_our_node_id(); // Check script when handling an accept_channel message - nodes[0].node.create_channel(node_b_id, 100000, 10001, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel(node_b_id, 100000, LightningAmount::from_msat(10001), 42, None, None) + .unwrap(); let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); handle_and_accept_open_channel(&nodes[1], node_a_id, &open_channel); @@ -1063,7 +1081,10 @@ fn test_invalid_upfront_shutdown_script() { let node_a_id = nodes[0].node.get_our_node_id(); let node_b_id = nodes[1].node.get_our_node_id(); - nodes[0].node.create_channel(node_b_id, 100000, 10001, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel(node_b_id, 100000, LightningAmount::from_msat(10001), 42, None, None) + .unwrap(); // Use a segwit v0 script with an unsupported witness program let mut open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); diff --git a/lightning/src/ln/splicing_tests.rs b/lightning/src/ln/splicing_tests.rs index ace1783327d..36a15f6d1f3 100644 --- a/lightning/src/ln/splicing_tests.rs +++ b/lightning/src/ln/splicing_tests.rs @@ -2121,8 +2121,10 @@ fn do_test_splice_with_inflight_htlc_forward_and_resolution(expire_scid_pre_forw PaymentParameters::from_node_id(node_id_2, CHANNEL_ANNOUNCEMENT_PROPAGATION_DELAY * 2) .with_bolt11_features(nodes[2].node.bolt11_invoice_features()) .unwrap(); - let route_params = - RouteParameters::from_payment_params_and_value(payment_params, payment_amount); + let route_params = RouteParameters::from_payment_params_and_value( + payment_params, + LightningAmount::from_msat(payment_amount), + ); let route = get_route(&nodes[0], &route_params).unwrap(); let (_, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[2], Some(payment_amount), None); diff --git a/lightning/src/ln/update_fee_tests.rs b/lightning/src/ln/update_fee_tests.rs index 24ae8525450..999f4d782c3 100644 --- a/lightning/src/ln/update_fee_tests.rs +++ b/lightning/src/ln/update_fee_tests.rs @@ -882,13 +882,16 @@ pub fn test_chan_init_feerate_unaffordability() { MIN_AFFORDABLE_HTLC_COUNT as u64, &channel_type_features, ); - assert_eq!(nodes[0].node.create_channel(node_b_id, 100_000, push_amt + 1, 42, None, None).unwrap_err(), + assert_eq!(nodes[0].node.create_channel(node_b_id, 100_000, LightningAmount::from_msat(push_amt + 1), 42, None, None).unwrap_err(), APIError::APIMisuseError { err: "Funding amount (356) can't even pay fee for initial commitment transaction fee of 357.".to_string() }); // During open, we don't have a "counterparty channel reserve" to check against, so that // requirement only comes into play on the open_channel handling side. push_amt -= get_holder_selected_channel_reserve_satoshis(100_000, &default_config) * 1000; - nodes[0].node.create_channel(node_b_id, 100_000, push_amt, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel(node_b_id, 100_000, LightningAmount::from_msat(push_amt), 42, None, None) + .unwrap(); let mut open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id); open_channel_msg.push_msat += 1; diff --git a/lightning/src/offers/flow.rs b/lightning/src/offers/flow.rs index 0bb98777227..088760dd635 100644 --- a/lightning/src/offers/flow.rs +++ b/lightning/src/offers/flow.rs @@ -803,7 +803,7 @@ impl OffersMessageFlow { let payment_context = PaymentContext::AsyncBolt12Offer(AsyncBolt12OfferContext { offer_nonce }); - let amount_msat = offer.amount().and_then(|amount| match amount { + let amount_msat = offer.offer_amount().and_then(|amount| match amount { Amount::Bitcoin { amount_msats } => Some(amount_msats), Amount::Currency { .. } => None, }); @@ -874,7 +874,7 @@ impl OffersMessageFlow { let expanded_key = &self.inbound_payment_key; let entropy = &entropy_source; - let amount_msats = refund.amount_msats(); + let amount_msats = refund.amount().to_msat(); let relative_expiry = DEFAULT_RELATIVE_EXPIRY.as_secs() as u32; let (payment_hash, payment_secret) = get_payment_info(amount_msats, relative_expiry)?; diff --git a/lightning/src/offers/invoice.rs b/lightning/src/offers/invoice.rs index 8d83225f117..f2d3814e1d9 100644 --- a/lightning/src/offers/invoice.rs +++ b/lightning/src/offers/invoice.rs @@ -145,6 +145,7 @@ use crate::offers::refund::{ IV_BYTES_WITH_METADATA as REFUND_IV_BYTES_WITH_METADATA, }; use crate::offers::signer::{self, Metadata}; +use crate::types::amount::LightningAmount; use crate::types::features::{Bolt12InvoiceFeatures, InvoiceRequestFeatures, OfferFeatures}; use crate::types::payment::PaymentHash; use crate::types::string::PrintableString; @@ -265,7 +266,7 @@ macro_rules! invoice_explicit_signing_pubkey_builder_methods { refund: &'a Refund, payment_paths: Vec, created_at: Duration, payment_hash: PaymentHash, signing_pubkey: PublicKey, ) -> Result { - let amount_msats = refund.amount_msats(); + let amount_msats = refund.amount().to_msat(); let contents = InvoiceContents::ForRefund { refund: refund.contents.clone(), fields: Self::fields( @@ -338,7 +339,7 @@ macro_rules! invoice_derived_signing_pubkey_builder_methods { refund: &'a Refund, payment_paths: Vec, created_at: Duration, payment_hash: PaymentHash, keys: Keypair, ) -> Result { - let amount_msats = refund.amount_msats(); + let amount_msats = refund.amount().to_msat(); let signing_pubkey = keys.public_key(); let contents = InvoiceContents::ForRefund { refund: refund.contents.clone(), @@ -828,8 +829,8 @@ macro_rules! invoice_accessors { ($self: ident, $contents: expr) => { /// the [`Offer`] did not set it. /// /// [`Offer`]: crate::offers::offer::Offer - /// [`Offer::amount`]: crate::offers::offer::Offer::amount - pub fn amount(&$self) -> Option { + /// [`Offer::amount`]: crate::offers::offer::Offer::offer_amount + pub fn offer_amount(&$self) -> Option { $contents.amount() } @@ -942,8 +943,8 @@ macro_rules! invoice_accessors { ($self: ident, $contents: expr) => { } /// The minimum amount required for a successful payment of the invoice. - pub fn amount_msats(&$self) -> u64 { - $contents.amount_msats() + pub fn amount(&$self) -> LightningAmount { + LightningAmount::from_msat($contents.amount_msats()) } } } @@ -1857,6 +1858,7 @@ mod tests { use crate::offers::payer::PayerTlvStreamRef; use crate::offers::test_utils::*; use crate::prelude::*; + use crate::types::amount::LightningAmount; use crate::types::features::{Bolt12InvoiceFeatures, InvoiceRequestFeatures, OfferFeatures}; use crate::types::string::PrintableString; use crate::util::ser::{BigSize, Iterable, Writeable}; @@ -1897,7 +1899,7 @@ mod tests { let payment_hash = payment_hash(); let now = now(); let unsigned_invoice = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -1919,7 +1921,7 @@ mod tests { Some(vec![ChainHash::using_genesis_block(Network::Bitcoin)]) ); assert_eq!(unsigned_invoice.metadata(), None); - assert_eq!(unsigned_invoice.amount(), Some(Amount::Bitcoin { amount_msats: 1000 })); + assert_eq!(unsigned_invoice.offer_amount(), Some(Amount::Bitcoin { amount_msats: 1000 })); assert_eq!(unsigned_invoice.description(), Some(PrintableString(""))); assert_eq!(unsigned_invoice.offer_features(), Some(&OfferFeatures::empty())); assert_eq!(unsigned_invoice.absolute_expiry(), None); @@ -1928,7 +1930,7 @@ mod tests { assert_eq!(unsigned_invoice.supported_quantity(), Some(Quantity::One)); assert_eq!(unsigned_invoice.signing_pubkey(), recipient_pubkey()); assert_eq!(unsigned_invoice.chain(), ChainHash::using_genesis_block(Network::Bitcoin)); - assert_eq!(unsigned_invoice.amount_msats(), 1000); + assert_eq!(unsigned_invoice.amount(), LightningAmount::from_msat(1000)); assert_eq!(unsigned_invoice.invoice_request_features(), &InvoiceRequestFeatures::empty()); assert_eq!(unsigned_invoice.quantity(), None); assert_eq!(unsigned_invoice.payer_note(), None); @@ -1963,7 +1965,7 @@ mod tests { Some(vec![ChainHash::using_genesis_block(Network::Bitcoin)]) ); assert_eq!(invoice.metadata(), None); - assert_eq!(invoice.amount(), Some(Amount::Bitcoin { amount_msats: 1000 })); + assert_eq!(invoice.offer_amount(), Some(Amount::Bitcoin { amount_msats: 1000 })); assert_eq!(invoice.description(), Some(PrintableString(""))); assert_eq!(invoice.offer_features(), Some(&OfferFeatures::empty())); assert_eq!(invoice.absolute_expiry(), None); @@ -1972,7 +1974,7 @@ mod tests { assert_eq!(invoice.supported_quantity(), Some(Quantity::One)); assert_eq!(invoice.signing_pubkey(), recipient_pubkey()); assert_eq!(invoice.chain(), ChainHash::using_genesis_block(Network::Bitcoin)); - assert_eq!(invoice.amount_msats(), 1000); + assert_eq!(invoice.amount(), LightningAmount::from_msat(1000)); assert_eq!(invoice.invoice_request_features(), &InvoiceRequestFeatures::empty()); assert_eq!(invoice.quantity(), None); assert_eq!( @@ -2074,7 +2076,7 @@ mod tests { assert_eq!(invoice.payer_metadata(), &[1; 32]); assert_eq!(invoice.offer_chains(), None); assert_eq!(invoice.metadata(), None); - assert_eq!(invoice.amount(), None); + assert_eq!(invoice.offer_amount(), None); assert_eq!(invoice.description(), Some(PrintableString(""))); assert_eq!(invoice.offer_features(), None); assert_eq!(invoice.absolute_expiry(), None); @@ -2083,7 +2085,7 @@ mod tests { assert_eq!(invoice.supported_quantity(), None); assert_eq!(invoice.signing_pubkey(), recipient_pubkey()); assert_eq!(invoice.chain(), ChainHash::using_genesis_block(Network::Bitcoin)); - assert_eq!(invoice.amount_msats(), 1000); + assert_eq!(invoice.amount(), LightningAmount::from_msat(1000)); assert_eq!(invoice.invoice_request_features(), &InvoiceRequestFeatures::empty()); assert_eq!(invoice.quantity(), None); assert_eq!(invoice.payer_signing_pubkey(), payer_pubkey()); @@ -2167,7 +2169,7 @@ mod tests { let past_expiry = Duration::from_secs(0); if let Err(e) = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .absolute_expiry(future_expiry) .build() .unwrap() @@ -2183,7 +2185,7 @@ mod tests { } match OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .absolute_expiry(past_expiry) .build() .unwrap() @@ -2253,7 +2255,7 @@ mod tests { use crate::offers::offer::OfferWithDerivedMetadataBuilder as OfferBuilder; let invoice_request = OfferBuilder::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .path(blinded_path) .experimental_foo(42) .build() @@ -2366,7 +2368,7 @@ mod tests { let one_hour = Duration::from_secs(3600); let invoice = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -2387,7 +2389,7 @@ mod tests { assert_eq!(tlv_stream.relative_expiry, Some(one_hour.as_secs() as u32)); let invoice = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -2417,12 +2419,12 @@ mod tests { let payment_id = PaymentId([1; 32]); let invoice = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) .unwrap() - .amount_msats(1001) + .amount(LightningAmount::from_msat(1001)) .unwrap() .build_and_sign() .unwrap() @@ -2433,7 +2435,7 @@ mod tests { .sign(recipient_sign) .unwrap(); let (_, _, _, tlv_stream, _, _, _, _) = invoice.as_tlv_stream(); - assert_eq!(invoice.amount_msats(), 1001); + assert_eq!(invoice.amount(), LightningAmount::from_msat(1001)); assert_eq!(tlv_stream.amount, Some(1001)); } @@ -2446,7 +2448,7 @@ mod tests { let payment_id = PaymentId([1; 32]); let invoice = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .supported_quantity(Quantity::Unbounded) .build() .unwrap() @@ -2463,11 +2465,11 @@ mod tests { .sign(recipient_sign) .unwrap(); let (_, _, _, tlv_stream, _, _, _, _) = invoice.as_tlv_stream(); - assert_eq!(invoice.amount_msats(), 2000); + assert_eq!(invoice.amount(), LightningAmount::from_msat(2000)); assert_eq!(tlv_stream.amount, Some(2000)); match OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .supported_quantity(Quantity::Unbounded) .build() .unwrap() @@ -2497,7 +2499,7 @@ mod tests { let tweaked_pubkey = TweakedPublicKey::dangerous_assume_tweaked(x_only_pubkey); let invoice = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -2553,7 +2555,7 @@ mod tests { features.set_basic_mpp_optional(); let invoice = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -2581,7 +2583,7 @@ mod tests { let payment_id = PaymentId([1; 32]); match OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -2599,7 +2601,7 @@ mod tests { } match OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -2626,7 +2628,7 @@ mod tests { let payment_id = PaymentId([1; 32]); let invoice = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -2703,7 +2705,7 @@ mod tests { let payment_id = PaymentId([1; 32]); let invoice = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -2747,7 +2749,7 @@ mod tests { let payment_id = PaymentId([1; 32]); let invoice = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -2780,7 +2782,7 @@ mod tests { let payment_id = PaymentId([1; 32]); let invoice = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -2824,7 +2826,7 @@ mod tests { let payment_id = PaymentId([1; 32]); let invoice = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -2866,7 +2868,7 @@ mod tests { let payment_id = PaymentId([1; 32]); let invoice = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -2908,7 +2910,7 @@ mod tests { let tweaked_pubkey = TweakedPublicKey::dangerous_assume_tweaked(x_only_pubkey); let invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -2972,7 +2974,7 @@ mod tests { let payment_id = PaymentId([1; 32]); let invoice = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -3057,7 +3059,7 @@ mod tests { let invoice = OfferBuilder::new(recipient_pubkey()) .clear_issuer_signing_pubkey() - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .path(paths[0].clone()) .path(paths[1].clone()) .build() @@ -3087,7 +3089,7 @@ mod tests { let invoice = OfferBuilder::new(recipient_pubkey()) .clear_issuer_signing_pubkey() - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .path(paths[0].clone()) .path(paths[1].clone()) .build() @@ -3131,7 +3133,7 @@ mod tests { let payment_id = PaymentId([1; 32]); let invoice = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -3158,12 +3160,12 @@ mod tests { } let invoice = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) .unwrap() - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .unwrap() .build_and_sign() .unwrap() @@ -3224,7 +3226,7 @@ mod tests { let mut buffer = Vec::new(); OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -3257,7 +3259,7 @@ mod tests { let payment_id = PaymentId([1; 32]); let mut invoice = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -3300,7 +3302,7 @@ mod tests { let secp_ctx = Secp256k1::new(); let keys = Keypair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let mut unsigned_invoice = OfferBuilder::new(keys.public_key()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -3339,7 +3341,7 @@ mod tests { assert!(UNKNOWN_EVEN_TYPE % 2 == 0); let mut unsigned_invoice = OfferBuilder::new(keys.public_key()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -3385,7 +3387,7 @@ mod tests { let secp_ctx = Secp256k1::new(); let keys = Keypair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let invoice = OfferBuilder::new(keys.public_key()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -3411,7 +3413,7 @@ mod tests { assert!(UNKNOWN_ODD_TYPE % 2 == 1); let mut unsigned_invoice = OfferBuilder::new(keys.public_key()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -3452,7 +3454,7 @@ mod tests { assert!(UNKNOWN_EVEN_TYPE % 2 == 0); let mut unsigned_invoice = OfferBuilder::new(keys.public_key()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -3490,7 +3492,7 @@ mod tests { } let invoice = OfferBuilder::new(keys.public_key()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -3531,7 +3533,7 @@ mod tests { let payment_id = PaymentId([1; 32]); let invoice = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -3566,7 +3568,7 @@ mod tests { let payment_id = PaymentId([1; 32]); let invoice = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -3610,7 +3612,10 @@ mod tests { let secp_ctx = Secp256k1::new(); let payment_id = PaymentId([1; 32]); - let offer = OfferBuilder::new(recipient_pubkey()).amount_msats(1000).build().unwrap(); + let offer = OfferBuilder::new(recipient_pubkey()) + .amount(LightningAmount::from_msat(1000)) + .build() + .unwrap(); let offer_id = offer.id(); @@ -3658,7 +3663,8 @@ mod tests { let now = Duration::from_secs(123456); let payment_id = PaymentId([1; 32]); - let offer = OfferBuilder::new(node_id).amount_msats(1000).build().unwrap(); + let offer = + OfferBuilder::new(node_id).amount(LightningAmount::from_msat(1000)).build().unwrap(); let invoice_request = offer .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) diff --git a/lightning/src/offers/invoice_request.rs b/lightning/src/offers/invoice_request.rs index 4311d194dca..9f46906aa82 100644 --- a/lightning/src/offers/invoice_request.rs +++ b/lightning/src/offers/invoice_request.rs @@ -27,6 +27,7 @@ //! use bitcoin::secp256k1::{Keypair, PublicKey, Secp256k1, SecretKey}; //! use lightning::ln::channelmanager::PaymentId; //! use lightning::ln::inbound_payment::ExpandedKey; +//! use lightning::types::amount::LightningAmount; //! use lightning::types::features::OfferFeatures; //! use lightning::offers::invoice_request::UnsignedInvoiceRequest; //! # use lightning::offers::nonce::Nonce; @@ -55,7 +56,7 @@ //! .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id)? //! # ) //! .chain(Network::Testnet)? -//! .amount_msats(1000)? +//! .amount(LightningAmount::from_msat(1000))? //! .quantity(5)? //! .payer_note("foo".to_string()) //! .build_and_sign()? @@ -84,6 +85,7 @@ use crate::offers::parse::{Bolt12ParseError, Bolt12SemanticError, ParsedMessage} use crate::offers::payer::{PayerContents, PayerTlvStream, PayerTlvStreamRef}; use crate::offers::signer::{Metadata, MetadataMaterial}; use crate::onion_message::dns_resolution::HumanReadableName; +use crate::types::amount::LightningAmount; use crate::types::features::InvoiceRequestFeatures; use crate::types::payment::PaymentHash; use crate::types::string::{PrintableString, UntrustedString}; @@ -215,13 +217,14 @@ macro_rules! invoice_request_builder_methods { ( Ok($return_value) } - /// Sets the [`InvoiceRequest::amount_msats`] for paying an invoice. Errors if `amount_msats` is + /// Sets the [`InvoiceRequest::amount`] for paying an invoice. Errors if the amount is /// not at least the expected invoice amount (i.e., [`Offer::amount`] times [`quantity`]). /// /// Successive calls to this method will override the previous setting. /// /// [`quantity`]: Self::quantity - pub fn amount_msats($($self_mut)* $self: $self_type, amount_msats: u64) -> Result<$return_type, Bolt12SemanticError> { + pub fn amount($($self_mut)* $self: $self_type, amount: LightningAmount) -> Result<$return_type, Bolt12SemanticError> { + let amount_msats = amount.to_msat(); $self.invoice_request.offer.check_amount_msats_for_quantity( Some(amount_msats), $self.invoice_request.quantity )?; @@ -274,7 +277,7 @@ macro_rules! invoice_request_builder_methods { ( $self.invoice_request.chain = None; } - if $self.offer.amount().is_none() && $self.invoice_request.amount_msats.is_none() { + if $self.offer.offer_amount().is_none() && $self.invoice_request.amount_msats.is_none() { return Err(Bolt12SemanticError::MissingAmount); } @@ -708,16 +711,16 @@ macro_rules! invoice_request_accessors { ($self: ident, $contents: expr) => { /// must be greater than or equal to [`Offer::amount`], converted if necessary. /// /// [`chain`]: Self::chain - pub fn amount_msats(&$self) -> Option { - $contents.amount_msats() + pub fn amount(&$self) -> Option { + $contents.amount_msats().map(LightningAmount::from_msat) } - /// Returns whether an amount was set in the request; otherwise, if [`amount_msats`] is `Some` + /// Returns whether an amount was set in the request; otherwise, if [`amount`] is `Some` /// then it was inferred from the [`Offer::amount`] and [`quantity`]. /// - /// [`amount_msats`]: Self::amount_msats + /// [`amount`]: Self::amount /// [`quantity`]: Self::quantity - pub fn has_amount_msats(&$self) -> bool { + pub fn has_amount(&$self) -> bool { $contents.has_amount_msats() } @@ -1570,6 +1573,7 @@ mod tests { use crate::offers::parse::{Bolt12ParseError, Bolt12SemanticError}; use crate::offers::payer::PayerTlvStreamRef; use crate::offers::test_utils::*; + use crate::types::amount::LightningAmount; use crate::types::features::{InvoiceRequestFeatures, OfferFeatures}; use crate::types::string::{PrintableString, UntrustedString}; use crate::util::ser::{BigSize, Readable, Writeable}; @@ -1590,7 +1594,7 @@ mod tests { let encrypted_payment_id = expanded_key.crypt_for_offer(payment_id.0, nonce); let invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -1608,7 +1612,7 @@ mod tests { vec![ChainHash::using_genesis_block(Network::Bitcoin)] ); assert_eq!(invoice_request.metadata(), None); - assert_eq!(invoice_request.amount(), Some(Amount::Bitcoin { amount_msats: 1000 })); + assert_eq!(invoice_request.offer_amount(), Some(Amount::Bitcoin { amount_msats: 1000 })); assert_eq!(invoice_request.description(), Some(PrintableString(""))); assert_eq!(invoice_request.offer_features(), &OfferFeatures::empty()); assert_eq!(invoice_request.absolute_expiry(), None); @@ -1617,7 +1621,7 @@ mod tests { assert_eq!(invoice_request.supported_quantity(), Quantity::One); assert_eq!(invoice_request.issuer_signing_pubkey(), Some(recipient_pubkey())); assert_eq!(invoice_request.chain(), ChainHash::using_genesis_block(Network::Bitcoin)); - assert_eq!(invoice_request.amount_msats(), Some(1000)); + assert_eq!(invoice_request.amount(), Some(LightningAmount::from_msat(1000))); assert_eq!(invoice_request.invoice_request_features(), &InvoiceRequestFeatures::empty()); assert_eq!(invoice_request.quantity(), None); assert_eq!(invoice_request.payer_note(), None); @@ -1682,7 +1686,7 @@ mod tests { let past_expiry = Duration::from_secs(0); if let Err(e) = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .absolute_expiry(future_expiry) .build() .unwrap() @@ -1694,7 +1698,7 @@ mod tests { } match OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .absolute_expiry(past_expiry) .build() .unwrap() @@ -1716,7 +1720,7 @@ mod tests { let payment_id = PaymentId([1; 32]); let offer = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .experimental_foo(42) .build() .unwrap(); @@ -1829,7 +1833,7 @@ mod tests { let testnet = ChainHash::using_genesis_block(Network::Testnet); let invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -1843,7 +1847,7 @@ mod tests { assert_eq!(tlv_stream.chain, None); let invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .chain(Network::Testnet) .build() .unwrap() @@ -1858,7 +1862,7 @@ mod tests { assert_eq!(tlv_stream.chain, Some(&testnet)); let invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .chain(Network::Bitcoin) .chain(Network::Testnet) .build() @@ -1874,7 +1878,7 @@ mod tests { assert_eq!(tlv_stream.chain, None); let invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .chain(Network::Bitcoin) .chain(Network::Testnet) .build() @@ -1892,7 +1896,7 @@ mod tests { assert_eq!(tlv_stream.chain, Some(&testnet)); match OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .chain(Network::Testnet) .build() .unwrap() @@ -1905,7 +1909,7 @@ mod tests { } match OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .chain(Network::Testnet) .build() .unwrap() @@ -1927,66 +1931,66 @@ mod tests { let payment_id = PaymentId([1; 32]); let invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) .unwrap() - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .unwrap() .build_and_sign() .unwrap(); let (_, _, tlv_stream, _, _, _) = invoice_request.as_tlv_stream(); - assert!(invoice_request.has_amount_msats()); - assert_eq!(invoice_request.amount_msats(), Some(1000)); + assert!(invoice_request.has_amount()); + assert_eq!(invoice_request.amount(), Some(LightningAmount::from_msat(1000))); assert_eq!(tlv_stream.amount, Some(1000)); let invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) .unwrap() - .amount_msats(1001) + .amount(LightningAmount::from_msat(1001)) .unwrap() - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .unwrap() .build_and_sign() .unwrap(); let (_, _, tlv_stream, _, _, _) = invoice_request.as_tlv_stream(); - assert!(invoice_request.has_amount_msats()); - assert_eq!(invoice_request.amount_msats(), Some(1000)); + assert!(invoice_request.has_amount()); + assert_eq!(invoice_request.amount(), Some(LightningAmount::from_msat(1000))); assert_eq!(tlv_stream.amount, Some(1000)); let invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) .unwrap() - .amount_msats(1001) + .amount(LightningAmount::from_msat(1001)) .unwrap() .build_and_sign() .unwrap(); let (_, _, tlv_stream, _, _, _) = invoice_request.as_tlv_stream(); - assert!(invoice_request.has_amount_msats()); - assert_eq!(invoice_request.amount_msats(), Some(1001)); + assert!(invoice_request.has_amount()); + assert_eq!(invoice_request.amount(), Some(LightningAmount::from_msat(1001))); assert_eq!(tlv_stream.amount, Some(1001)); match OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) .unwrap() - .amount_msats(999) + .amount(LightningAmount::from_msat(999)) { Ok(_) => panic!("expected error"), Err(e) => assert_eq!(e, Bolt12SemanticError::InsufficientAmount), } match OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .supported_quantity(Quantity::Unbounded) .build() .unwrap() @@ -1994,32 +1998,32 @@ mod tests { .unwrap() .quantity(2) .unwrap() - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) { Ok(_) => panic!("expected error"), Err(e) => assert_eq!(e, Bolt12SemanticError::InsufficientAmount), } match OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) .unwrap() - .amount_msats(MAX_VALUE_MSAT + 1) + .amount(LightningAmount::from_msat(MAX_VALUE_MSAT + 1)) { Ok(_) => panic!("expected error"), Err(e) => assert_eq!(e, Bolt12SemanticError::InvalidAmount), } match OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .supported_quantity(Quantity::Unbounded) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) .unwrap() - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .unwrap() .quantity(2) .unwrap() @@ -2041,7 +2045,7 @@ mod tests { } match OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .supported_quantity(Quantity::Unbounded) .build() .unwrap() @@ -2065,7 +2069,7 @@ mod tests { let payment_id = PaymentId([1; 32]); let invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -2073,12 +2077,12 @@ mod tests { .build_and_sign() .unwrap(); let (_, _, tlv_stream, _, _, _) = invoice_request.as_tlv_stream(); - assert!(!invoice_request.has_amount_msats()); - assert_eq!(invoice_request.amount_msats(), Some(1000)); + assert!(!invoice_request.has_amount()); + assert_eq!(invoice_request.amount(), Some(LightningAmount::from_msat(1000))); assert_eq!(tlv_stream.amount, None); let invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .supported_quantity(Quantity::Unbounded) .build() .unwrap() @@ -2089,12 +2093,12 @@ mod tests { .build_and_sign() .unwrap(); let (_, _, tlv_stream, _, _, _) = invoice_request.as_tlv_stream(); - assert!(!invoice_request.has_amount_msats()); - assert_eq!(invoice_request.amount_msats(), Some(2000)); + assert!(!invoice_request.has_amount()); + assert_eq!(invoice_request.amount(), Some(LightningAmount::from_msat(2000))); assert_eq!(tlv_stream.amount, None); let invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount(Amount::Currency { + .set_amount(Amount::Currency { iso4217_code: CurrencyCode::new(*b"USD").unwrap(), amount: 10, }) @@ -2103,8 +2107,8 @@ mod tests { .unwrap() .build_unchecked_and_sign(); let (_, _, tlv_stream, _, _, _) = invoice_request.as_tlv_stream(); - assert!(!invoice_request.has_amount_msats()); - assert_eq!(invoice_request.amount_msats(), None); + assert!(!invoice_request.has_amount()); + assert_eq!(invoice_request.amount(), None); assert_eq!(tlv_stream.amount, None); } @@ -2117,7 +2121,7 @@ mod tests { let payment_id = PaymentId([1; 32]); let invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -2130,7 +2134,7 @@ mod tests { assert_eq!(tlv_stream.features, Some(&InvoiceRequestFeatures::unknown())); let invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -2156,7 +2160,7 @@ mod tests { let ten = NonZeroU64::new(10).unwrap(); let invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .supported_quantity(Quantity::One) .build() .unwrap() @@ -2169,13 +2173,13 @@ mod tests { assert_eq!(tlv_stream.quantity, None); match OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .supported_quantity(Quantity::One) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) .unwrap() - .amount_msats(2_000) + .amount(LightningAmount::from_msat(2_000)) .unwrap() .quantity(2) { @@ -2184,30 +2188,30 @@ mod tests { } let invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .supported_quantity(Quantity::Bounded(ten)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) .unwrap() - .amount_msats(10_000) + .amount(LightningAmount::from_msat(10_000)) .unwrap() .quantity(10) .unwrap() .build_and_sign() .unwrap(); let (_, _, tlv_stream, _, _, _) = invoice_request.as_tlv_stream(); - assert_eq!(invoice_request.amount_msats(), Some(10_000)); + assert_eq!(invoice_request.amount(), Some(LightningAmount::from_msat(10_000))); assert_eq!(tlv_stream.amount, Some(10_000)); match OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .supported_quantity(Quantity::Bounded(ten)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) .unwrap() - .amount_msats(11_000) + .amount(LightningAmount::from_msat(11_000)) .unwrap() .quantity(11) { @@ -2216,24 +2220,24 @@ mod tests { } let invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .supported_quantity(Quantity::Unbounded) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) .unwrap() - .amount_msats(2_000) + .amount(LightningAmount::from_msat(2_000)) .unwrap() .quantity(2) .unwrap() .build_and_sign() .unwrap(); let (_, _, tlv_stream, _, _, _) = invoice_request.as_tlv_stream(); - assert_eq!(invoice_request.amount_msats(), Some(2_000)); + assert_eq!(invoice_request.amount(), Some(LightningAmount::from_msat(2_000))); assert_eq!(tlv_stream.amount, Some(2_000)); match OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .supported_quantity(Quantity::Unbounded) .build() .unwrap() @@ -2246,7 +2250,7 @@ mod tests { } match OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .supported_quantity(Quantity::Bounded(one)) .build() .unwrap() @@ -2268,7 +2272,7 @@ mod tests { let payment_id = PaymentId([1; 32]); let invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -2281,7 +2285,7 @@ mod tests { assert_eq!(tlv_stream.payer_note, Some(&String::from("bar"))); let invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -2304,7 +2308,7 @@ mod tests { let payment_id = PaymentId([1; 32]); match OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -2328,7 +2332,7 @@ mod tests { let payment_id = PaymentId([1; 32]); let invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -2353,7 +2357,7 @@ mod tests { let payment_id = PaymentId([1; 32]); let invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -2371,7 +2375,7 @@ mod tests { } let invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -2400,7 +2404,7 @@ mod tests { let payment_id = PaymentId([1; 32]); let invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -2420,7 +2424,7 @@ mod tests { .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) .unwrap() - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .unwrap() .build_and_sign() .unwrap(); @@ -2451,7 +2455,7 @@ mod tests { } let invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -2472,7 +2476,7 @@ mod tests { let invoice_request = OfferBuilder::new(recipient_pubkey()) .description("foo".to_string()) - .amount(Amount::Currency { + .set_amount(Amount::Currency { iso4217_code: CurrencyCode::new(*b"USD").unwrap(), amount: 1000, }) @@ -2495,7 +2499,7 @@ mod tests { } let invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .supported_quantity(Quantity::Unbounded) .build() .unwrap() @@ -2529,7 +2533,7 @@ mod tests { let ten = NonZeroU64::new(10).unwrap(); let invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .supported_quantity(Quantity::One) .build() .unwrap() @@ -2546,13 +2550,13 @@ mod tests { } let invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .supported_quantity(Quantity::One) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) .unwrap() - .amount_msats(2_000) + .amount(LightningAmount::from_msat(2_000)) .unwrap() .quantity_unchecked(2) .build_unchecked_and_sign(); @@ -2571,13 +2575,13 @@ mod tests { } let invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .supported_quantity(Quantity::Bounded(ten)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) .unwrap() - .amount_msats(10_000) + .amount(LightningAmount::from_msat(10_000)) .unwrap() .quantity(10) .unwrap() @@ -2592,13 +2596,13 @@ mod tests { } let invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .supported_quantity(Quantity::Bounded(ten)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) .unwrap() - .amount_msats(11_000) + .amount(LightningAmount::from_msat(11_000)) .unwrap() .quantity_unchecked(11) .build_unchecked_and_sign(); @@ -2615,13 +2619,13 @@ mod tests { } let invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .supported_quantity(Quantity::Unbounded) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) .unwrap() - .amount_msats(2_000) + .amount(LightningAmount::from_msat(2_000)) .unwrap() .quantity(2) .unwrap() @@ -2636,7 +2640,7 @@ mod tests { } let invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .supported_quantity(Quantity::Unbounded) .build() .unwrap() @@ -2656,7 +2660,7 @@ mod tests { } let invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .supported_quantity(Quantity::Bounded(one)) .build() .unwrap() @@ -2685,7 +2689,7 @@ mod tests { let payment_id = PaymentId([1; 32]); let unsigned_invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -2717,7 +2721,7 @@ mod tests { let payment_id = PaymentId([1; 32]); let unsigned_invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -2747,7 +2751,7 @@ mod tests { let payment_id = PaymentId([1; 32]); let unsigned_invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -2782,7 +2786,7 @@ mod tests { let mut buffer = Vec::new(); OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -2810,7 +2814,7 @@ mod tests { let payment_id = PaymentId([1; 32]); let mut invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -2847,7 +2851,7 @@ mod tests { let secp_ctx = Secp256k1::new(); let keys = Keypair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let (mut unsigned_invoice_request, payer_keys, _) = OfferBuilder::new(keys.public_key()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -2882,7 +2886,7 @@ mod tests { assert!(UNKNOWN_EVEN_TYPE % 2 == 0); let (mut unsigned_invoice_request, payer_keys, _) = OfferBuilder::new(keys.public_key()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -2927,7 +2931,7 @@ mod tests { let secp_ctx = Secp256k1::new(); let keys = Keypair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let (mut unsigned_invoice_request, payer_keys, _) = OfferBuilder::new(keys.public_key()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -2965,7 +2969,7 @@ mod tests { assert!(UNKNOWN_EVEN_TYPE % 2 == 0); let (mut unsigned_invoice_request, payer_keys, _) = OfferBuilder::new(keys.public_key()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -3000,7 +3004,7 @@ mod tests { } let invoice_request = OfferBuilder::new(keys.public_key()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -3033,7 +3037,7 @@ mod tests { let payment_id = PaymentId([1; 32]); let invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -3079,7 +3083,7 @@ mod tests { use crate::offers::offer::OfferWithDerivedMetadataBuilder as OfferBuilder; let offer = OfferBuilder::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx) .chain(Network::Testnet) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .supported_quantity(Quantity::Unbounded) .build() .unwrap(); diff --git a/lightning/src/offers/merkle.rs b/lightning/src/offers/merkle.rs index 1a38fe5441f..551c55e5be6 100644 --- a/lightning/src/offers/merkle.rs +++ b/lightning/src/offers/merkle.rs @@ -292,6 +292,7 @@ mod tests { use crate::offers::parse::Bech32Encode; use crate::offers::signer::Metadata; use crate::offers::test_utils::recipient_pubkey; + use crate::types::amount::LightningAmount; use crate::util::ser::Writeable; use bitcoin::hashes::{sha256, Hash}; use bitcoin::hex::FromHex; @@ -356,7 +357,7 @@ mod tests { // BOLT 12 test vectors let invoice_request = OfferBuilder::new(recipient_pubkey) .description("A Mathematical Treatise".into()) - .amount(Amount::Currency { + .set_amount(Amount::Currency { iso4217_code: CurrencyCode::new(*b"USD").unwrap(), amount: 100, }) @@ -396,7 +397,7 @@ mod tests { let payment_id = PaymentId([1; 32]); let unsigned_invoice_request = OfferBuilder::new(recipient_pubkey()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) @@ -428,7 +429,7 @@ mod tests { }; let invoice_request = OfferBuilder::new(recipient_pubkey) - .amount_msats(100) + .amount(LightningAmount::from_msat(100)) .build_unchecked() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) .unwrap() @@ -462,7 +463,7 @@ mod tests { }; let invoice_request = OfferBuilder::new(recipient_pubkey) - .amount_msats(100) + .amount(LightningAmount::from_msat(100)) .build_unchecked() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) .unwrap() diff --git a/lightning/src/offers/offer.rs b/lightning/src/offers/offer.rs index 5592c50a264..1ecd07766cd 100644 --- a/lightning/src/offers/offer.rs +++ b/lightning/src/offers/offer.rs @@ -28,6 +28,7 @@ //! use lightning::offers::offer::{Offer, OfferBuilder, Quantity}; //! use lightning::offers::parse::Bolt12ParseError; //! use lightning::util::ser::{Readable, Writeable}; +//! use lightning::types::amount::LightningAmount; //! //! # use lightning::blinded_path::message::BlindedMessagePath; //! # #[cfg(feature = "std")] @@ -45,7 +46,7 @@ //! let expiration = SystemTime::now() + Duration::from_secs(24 * 60 * 60); //! let offer = OfferBuilder::new(pubkey) //! .description("coffee, large".to_string()) -//! .amount_msats(20_000) +//! .amount(LightningAmount::from_msat(20_000)) //! .supported_quantity(Quantity::Unbounded) //! .absolute_expiry(expiration.duration_since(SystemTime::UNIX_EPOCH).unwrap()) //! .issuer("Foo Bar".to_string()) @@ -87,6 +88,7 @@ use crate::offers::nonce::Nonce; use crate::offers::parse::{Bech32Encode, Bolt12ParseError, Bolt12SemanticError, ParsedMessage}; use crate::offers::signer::{self, Metadata, MetadataMaterial}; use crate::onion_message::dns_resolution::HumanReadableName; +use crate::types::amount::LightningAmount; use crate::types::features::OfferFeatures; use crate::types::string::PrintableString; use crate::util::ser::{ @@ -342,14 +344,14 @@ macro_rules! offer_builder_methods { ( /// Sets the [`Offer::amount`] as an [`Amount::Bitcoin`]. /// /// Successive calls to this method will override the previous setting. - pub fn amount_msats($self: $self_type, amount_msats: u64) -> $return_type { - $self.amount(Amount::Bitcoin { amount_msats }) + pub fn amount($self: $self_type, amount: LightningAmount) -> $return_type { + $self.set_amount(Amount::Bitcoin { amount_msats: amount.to_msat() }) } /// Sets the [`Offer::amount`]. /// /// Successive calls to this method will override the previous setting. - pub(super) fn amount($($self_mut)* $self: $self_type, amount: Amount) -> $return_type { + pub(super) fn set_amount($($self_mut)* $self: $self_type, amount: Amount) -> $return_type { $self.offer.amount = Some(amount); $return_value } @@ -655,7 +657,7 @@ macro_rules! offer_accessors { ($self: ident, $contents: expr) => { } /// The minimum amount required for a successful payment of a single item. - pub fn amount(&$self) -> Option<$crate::offers::offer::Amount> { + pub fn offer_amount(&$self) -> Option<$crate::offers::offer::Amount> { $contents.amount() } @@ -1398,6 +1400,7 @@ mod tests { use crate::offers::offer::CurrencyCode; use crate::offers::parse::{Bolt12ParseError, Bolt12SemanticError}; use crate::offers::test_utils::*; + use crate::types::amount::LightningAmount; use crate::types::features::OfferFeatures; use crate::types::string::PrintableString; use crate::util::ser::{BigSize, Writeable}; @@ -1418,7 +1421,7 @@ mod tests { assert_eq!(offer.chains(), vec![ChainHash::using_genesis_block(Network::Bitcoin)]); assert!(offer.supports_chain(ChainHash::using_genesis_block(Network::Bitcoin))); assert_eq!(offer.metadata(), None); - assert_eq!(offer.amount(), None); + assert_eq!(offer.offer_amount(), None); assert_eq!(offer.description(), None); assert_eq!(offer.offer_features(), &OfferFeatures::empty()); assert_eq!(offer.absolute_expiry(), None); @@ -1519,7 +1522,7 @@ mod tests { #[cfg(c_bindings)] use super::OfferWithDerivedMetadataBuilder as OfferBuilder; let offer = OfferBuilder::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .experimental_foo(42) .build() .unwrap(); @@ -1599,7 +1602,7 @@ mod tests { #[cfg(c_bindings)] use super::OfferWithDerivedMetadataBuilder as OfferBuilder; let offer = OfferBuilder::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .path(blinded_path) .experimental_foo(42) .build() @@ -1667,18 +1670,19 @@ mod tests { let currency_amount = Amount::Currency { iso4217_code: CurrencyCode::new(*b"USD").unwrap(), amount: 10 }; - let offer = OfferBuilder::new(pubkey(42)).amount_msats(1000).build().unwrap(); + let offer = + OfferBuilder::new(pubkey(42)).amount(LightningAmount::from_msat(1000)).build().unwrap(); let tlv_stream = offer.as_tlv_stream(); - assert_eq!(offer.amount(), Some(bitcoin_amount)); + assert_eq!(offer.offer_amount(), Some(bitcoin_amount)); assert_eq!(tlv_stream.0.amount, Some(1000)); assert_eq!(tlv_stream.0.currency, None); #[cfg(not(c_bindings))] - let builder = OfferBuilder::new(pubkey(42)).amount(currency_amount.clone()); + let builder = OfferBuilder::new(pubkey(42)).set_amount(currency_amount.clone()); #[cfg(c_bindings)] let mut builder = OfferBuilder::new(pubkey(42)); #[cfg(c_bindings)] - builder.amount(currency_amount.clone()); + builder.set_amount(currency_amount.clone()); let tlv_stream = builder.offer.as_tlv_stream(); assert_eq!(builder.offer.amount, Some(currency_amount.clone())); assert_eq!(tlv_stream.0.amount, Some(10)); @@ -1689,8 +1693,8 @@ mod tests { } let offer = OfferBuilder::new(pubkey(42)) - .amount(currency_amount.clone()) - .amount(bitcoin_amount.clone()) + .set_amount(currency_amount.clone()) + .set_amount(bitcoin_amount.clone()) .build() .unwrap(); let tlv_stream = offer.as_tlv_stream(); @@ -1698,7 +1702,7 @@ mod tests { assert_eq!(tlv_stream.0.currency, None); let invalid_amount = Amount::Bitcoin { amount_msats: MAX_VALUE_MSAT + 1 }; - match OfferBuilder::new(pubkey(42)).amount(invalid_amount).build() { + match OfferBuilder::new(pubkey(42)).set_amount(invalid_amount).build() { Ok(_) => panic!("expected error"), Err(e) => assert_eq!(e, Bolt12SemanticError::InvalidAmount), } @@ -1718,7 +1722,8 @@ mod tests { assert_eq!(offer.description(), Some(PrintableString("bar"))); assert_eq!(offer.as_tlv_stream().0.description, Some(&String::from("bar"))); - let offer = OfferBuilder::new(pubkey(42)).amount_msats(1000).build().unwrap(); + let offer = + OfferBuilder::new(pubkey(42)).amount(LightningAmount::from_msat(1000)).build().unwrap(); assert_eq!(offer.description(), Some(PrintableString(""))); assert_eq!(offer.as_tlv_stream().0.description, Some(&String::from(""))); } @@ -1897,7 +1902,7 @@ mod tests { #[test] fn parses_offer_with_amount() { let offer = OfferBuilder::new(pubkey(42)) - .amount(Amount::Bitcoin { amount_msats: 1000 }) + .set_amount(Amount::Bitcoin { amount_msats: 1000 }) .build() .unwrap(); if let Err(e) = offer.to_string().parse::() { @@ -1985,7 +1990,7 @@ mod tests { let offer = OfferBuilder::new(pubkey(42)) .description("foo".to_string()) - .amount_msats(1000) + .amount(LightningAmount::from_msat(1000)) .build() .unwrap(); if let Err(e) = offer.to_string().parse::() { diff --git a/lightning/src/offers/refund.rs b/lightning/src/offers/refund.rs index c0fd9dfdd3e..c14302319d4 100644 --- a/lightning/src/offers/refund.rs +++ b/lightning/src/offers/refund.rs @@ -100,6 +100,7 @@ use crate::offers::parse::{Bech32Encode, Bolt12ParseError, Bolt12SemanticError, use crate::offers::payer::{PayerContents, PayerTlvStream, PayerTlvStreamRef}; use crate::offers::signer::{self, Metadata, MetadataMaterial}; use crate::sign::EntropySource; +use crate::types::amount::LightningAmount; use crate::types::features::InvoiceRequestFeatures; use crate::types::payment::PaymentHash; use crate::types::string::PrintableString; @@ -529,8 +530,8 @@ impl Refund { /// The amount to refund in msats (i.e., the minimum lightning-payable unit for [`chain`]). /// /// [`chain`]: Self::chain - pub fn amount_msats(&self) -> u64 { - self.contents.amount_msats() + pub fn amount(&self) -> LightningAmount { + LightningAmount::from_msat(self.contents.amount_msats()) } /// Features pertaining to requesting an invoice. @@ -1047,6 +1048,7 @@ mod tests { use crate::offers::payer::PayerTlvStreamRef; use crate::offers::test_utils::*; use crate::prelude::*; + use crate::types::amount::LightningAmount; use crate::types::features::{InvoiceRequestFeatures, OfferFeatures}; use crate::types::string::PrintableString; use crate::util::ser::{BigSize, Writeable}; @@ -1080,7 +1082,7 @@ mod tests { assert_eq!(refund.paths(), &[]); assert_eq!(refund.issuer(), None); assert_eq!(refund.chain(), ChainHash::using_genesis_block(Network::Bitcoin)); - assert_eq!(refund.amount_msats(), 1000); + assert_eq!(refund.amount(), LightningAmount::from_msat(1000)); assert_eq!(refund.features(), &InvoiceRequestFeatures::empty()); assert_eq!(refund.payer_signing_pubkey(), payer_pubkey()); assert_eq!(refund.payer_note(), None); diff --git a/lightning/src/offers/static_invoice.rs b/lightning/src/offers/static_invoice.rs index 77f486a6a06..7cd5b156388 100644 --- a/lightning/src/offers/static_invoice.rs +++ b/lightning/src/offers/static_invoice.rs @@ -219,7 +219,7 @@ macro_rules! invoice_accessors { ($self: ident, $contents: expr) => { /// /// From [`Offer::amount`]. /// - /// [`Offer::amount`]: crate::offers::offer::Offer::amount + /// [`Offer::amount`]: crate::offers::offer::Offer::offer_amount pub fn amount(&$self) -> Option { $contents.amount() } diff --git a/lightning/src/routing/gossip.rs b/lightning/src/routing/gossip.rs index 3794c381817..db9b2e7c077 100644 --- a/lightning/src/routing/gossip.rs +++ b/lightning/src/routing/gossip.rs @@ -35,6 +35,7 @@ use crate::ln::msgs::{ }; use crate::ln::types::ChannelId; use crate::routing::utxo::{self, UtxoLookup, UtxoResolver}; +use crate::types::amount::LightningAmount; use crate::types::features::{ChannelFeatures, InitFeatures, NodeFeatures}; use crate::types::string::PrintableString; use crate::util::indexed_map::{ @@ -1297,7 +1298,7 @@ impl<'a> fmt::Debug for DirectedChannelInfo<'a> { /// The effective capacity of a channel for routing purposes. /// /// While this may be smaller than the actual channel capacity, amounts greater than -/// [`Self::as_msat`] should not be routed through the channel. +/// [`Self::as_amount`] should not be routed through the channel. #[derive(Clone, Copy, Debug, PartialEq)] pub enum EffectiveCapacity { /// The available liquidity in the channel known from being a channel counterparty, and thus a @@ -1337,16 +1338,16 @@ pub enum EffectiveCapacity { pub const UNKNOWN_CHANNEL_CAPACITY_MSAT: u64 = 250_000 * 1000; impl EffectiveCapacity { - /// Returns the effective capacity denominated in millisatoshi. - pub fn as_msat(&self) -> u64 { - match self { + /// Returns the effective capacity as a [`LightningAmount`]. + pub fn as_amount(&self) -> LightningAmount { + LightningAmount::from_msat(match self { EffectiveCapacity::ExactLiquidity { liquidity_msat } => *liquidity_msat, EffectiveCapacity::AdvertisedMaxHTLC { amount_msat } => *amount_msat, EffectiveCapacity::Total { capacity_msat, .. } => *capacity_msat, EffectiveCapacity::HintMaxHTLC { amount_msat } => *amount_msat, EffectiveCapacity::Infinite => u64::max_value(), EffectiveCapacity::Unknown => UNKNOWN_CHANNEL_CAPACITY_MSAT, - } + }) } } diff --git a/lightning/src/routing/router.rs b/lightning/src/routing/router.rs index b27dee1a450..81eb2e8b5f6 100644 --- a/lightning/src/routing/router.rs +++ b/lightning/src/routing/router.rs @@ -31,6 +31,7 @@ use crate::routing::gossip::{ use crate::routing::scoring::{ChannelUsage, LockableScore, ScoreLookUp}; use crate::sign::{EntropySource, ReceiveAuthKey}; use crate::sync::Mutex; +use crate::types::amount::LightningAmount; use crate::types::features::{ BlindedHopFeatures, Bolt11InvoiceFeatures, Bolt12InvoiceFeatures, ChannelFeatures, NodeFeatures, }; @@ -365,11 +366,11 @@ where #[rustfmt::skip] fn channel_penalty_msat(&self, candidate: &CandidateRouteHop, usage: ChannelUsage, score_params: &Self::ScoreParams) -> u64 { if let CandidateRouteHop::Blinded(blinded_candidate) = candidate { - if let Some(used_liquidity) = self.inflight_htlcs.used_blinded_liquidity_msat( + if let Some(used_liquidity) = self.inflight_htlcs.used_blinded_liquidity( *blinded_candidate.source_node_id, blinded_candidate.hint.blinding_point(), ) { let usage = ChannelUsage { - inflight_htlc_msat: usage.inflight_htlc_msat.saturating_add(used_liquidity), + inflight_htlc_msat: usage.inflight_htlc_msat.saturating_add(used_liquidity.to_msat()), ..usage }; @@ -385,11 +386,11 @@ where None => return self.scorer.channel_penalty_msat(candidate, usage, score_params), }; let source = candidate.source(); - if let Some(used_liquidity) = self.inflight_htlcs.used_liquidity_msat( + if let Some(used_liquidity) = self.inflight_htlcs.used_liquidity( &source, &target, short_channel_id ) { let usage = ChannelUsage { - inflight_htlc_msat: usage.inflight_htlc_msat.saturating_add(used_liquidity), + inflight_htlc_msat: usage.inflight_htlc_msat.saturating_add(used_liquidity.to_msat()), ..usage }; @@ -406,7 +407,7 @@ where pub struct InFlightHtlcs { // A map with liquidity value (in msat) keyed by a short channel id and the direction the HTLC // is traveling in. The direction boolean is determined by checking if the HTLC source's public - // key is less than its destination. See `InFlightHtlcs::used_liquidity_msat` for more + // key is less than its destination. See `InFlightHtlcs::used_liquidity` for more // details. unblinded_hops: HashMap<(u64, bool), u64>, /// A map with liquidity value (in msat) keyed by the introduction point of a blinded path and @@ -483,17 +484,21 @@ impl InFlightHtlcs { /// Returns liquidity in msat given the public key of the HTLC source, target, and short channel /// id. - pub fn used_liquidity_msat( + pub fn used_liquidity( &self, source: &NodeId, target: &NodeId, channel_scid: u64, - ) -> Option { - self.unblinded_hops.get(&(channel_scid, source < target)).map(|v| *v) + ) -> Option { + self.unblinded_hops + .get(&(channel_scid, source < target)) + .map(|v| LightningAmount::from_msat(*v)) } /// Returns liquidity in msat given the blinded path introduction point and blinding point. - pub fn used_blinded_liquidity_msat( + pub fn used_blinded_liquidity( &self, introduction_point: NodeId, blinding_point: PublicKey, - ) -> Option { - self.blinded_hops.get(&(introduction_point, blinding_point)).map(|v| *v) + ) -> Option { + self.blinded_hops + .get(&(introduction_point, blinding_point)) + .map(|v| LightningAmount::from_msat(*v)) } } @@ -613,24 +618,24 @@ pub struct Path { impl Path { /// Gets the fees for a given path, excluding any excess paid to the recipient. #[rustfmt::skip] - pub fn fee_msat(&self) -> u64 { - match &self.blinded_tail { + pub fn fee(&self) -> LightningAmount { + LightningAmount::from_msat(match &self.blinded_tail { Some(_) => self.hops.iter().map(|hop| hop.fee_msat).sum::(), None => { // Do not count last hop of each path since that's the full value of the payment self.hops.split_last().map_or(0, |(_, path_prefix)| path_prefix.iter().map(|hop| hop.fee_msat).sum()) } - } + }) } /// Gets the total amount paid on this [`Path`], excluding the fees. #[rustfmt::skip] - pub fn final_value_msat(&self) -> u64 { - match &self.blinded_tail { + pub fn final_value(&self) -> LightningAmount { + LightningAmount::from_msat(match &self.blinded_tail { Some(blinded_tail) => blinded_tail.final_value_msat, None => self.hops.last().map_or(0, |hop| hop.fee_msat) - } + }) } /// Gets the final hop's CLTV expiry delta. @@ -676,7 +681,7 @@ impl Route { pub fn get_total_fees(&self) -> u64 { let overpaid_value_msat = self.route_params.as_ref() .map_or(0, |p| self.get_total_amount().saturating_sub(p.final_value_msat)); - overpaid_value_msat + self.paths.iter().map(|path| path.fee_msat()).sum::() + overpaid_value_msat + self.paths.iter().map(|path| path.fee().to_msat()).sum::() } /// Returns the total amount paid on this [`Route`], excluding the fees. @@ -686,7 +691,7 @@ impl Route { /// /// [`htlc_minimum_msat`]: https://github.com/lightning/bolts/blob/master/07-routing-gossip.md#the-channel_update-message pub fn get_total_amount(&self) -> u64 { - self.paths.iter().map(|path| path.final_value_msat()).sum() + self.paths.iter().map(|path| path.final_value().to_msat()).sum() } } @@ -802,7 +807,8 @@ impl RouteParameters { /// /// [`Self::max_total_routing_fee_msat`] defaults to 1% of the payment amount + 50 sats #[rustfmt::skip] - pub fn from_payment_params_and_value(payment_params: PaymentParameters, final_value_msat: u64) -> Self { + pub fn from_payment_params_and_value(payment_params: PaymentParameters, final_value: LightningAmount) -> Self { + let final_value_msat = final_value.to_msat(); Self { payment_params, final_value_msat, max_total_routing_fee_msat: Some(final_value_msat / 100 + 50_000) } } @@ -1256,8 +1262,8 @@ impl RouteParametersConfig { /// Set the maximum total fees, in millisatoshi, that may accrue during route finding. /// /// This is not exported to bindings users since bindings don't support move semantics - pub fn with_max_total_routing_fee_msat(self, fee_msat: u64) -> Self { - Self { max_total_routing_fee_msat: Some(fee_msat), ..self } + pub fn with_max_total_routing_fee(self, fee: LightningAmount) -> Self { + Self { max_total_routing_fee_msat: Some(fee.to_msat()), ..self } } /// Includes a limit for the total CLTV expiry delta which is considered during routing @@ -1738,14 +1744,14 @@ impl<'a> CandidateRouteHop<'a> { /// Returns the minimum amount that can be sent over this hop, in millisatoshis. #[inline] - pub fn htlc_minimum_msat(&self) -> u64 { - match self { + pub fn htlc_minimum(&self) -> LightningAmount { + LightningAmount::from_msat(match self { CandidateRouteHop::FirstHop(hop) => hop.details.next_outbound_htlc_minimum_msat, CandidateRouteHop::PublicHop(hop) => hop.info.direction().htlc_minimum_msat, CandidateRouteHop::PrivateHop(hop) => hop.hint.htlc_minimum_msat.unwrap_or(0), CandidateRouteHop::Blinded(hop) => hop.hint.payinfo.htlc_minimum_msat, CandidateRouteHop::OneHopBlinded { .. } => 0, - } + }) } #[inline(always)] @@ -2054,7 +2060,7 @@ fn max_htlc_from_capacity(capacity: EffectiveCapacity, max_channel_saturation_po match capacity { EffectiveCapacity::ExactLiquidity { liquidity_msat } => liquidity_msat, EffectiveCapacity::Infinite => u64::max_value(), - EffectiveCapacity::Unknown => EffectiveCapacity::Unknown.as_msat(), + EffectiveCapacity::Unknown => EffectiveCapacity::Unknown.as_amount().to_msat(), EffectiveCapacity::AdvertisedMaxHTLC { amount_msat } => amount_msat.checked_shr(saturation_shift).unwrap_or(0), // Treat htlc_maximum_msat from a route hint as an exact liquidity amount, since the invoice is @@ -2245,7 +2251,7 @@ impl<'a> PaymentPath<'a> { // set it too high just to maliciously take more fees by exploiting this // match htlc_minimum_msat logic. let mut cur_hop_transferred_amount_msat = total_fee_paid_msat + value_msat; - if let Some(extra_fees_msat) = cur_hop.candidate.htlc_minimum_msat().checked_sub(cur_hop_transferred_amount_msat) { + if let Some(extra_fees_msat) = cur_hop.candidate.htlc_minimum().to_msat().checked_sub(cur_hop_transferred_amount_msat) { // Note that there is a risk that *previous hops* (those closer to us, as we go // payee->our_node here) would exceed their htlc_maximum_msat or available balance. // @@ -2858,7 +2864,7 @@ pub(crate) fn get_route( // We do this for now, but this is a subject for removal. if let Some(mut available_value_contribution_msat) = htlc_maximum_msat.checked_sub($next_hops_fee_msat) { let cltv_expiry_delta = $candidate.cltv_expiry_delta(); - let htlc_minimum_msat = $candidate.htlc_minimum_msat(); + let htlc_minimum_msat = $candidate.htlc_minimum().to_msat(); let used_liquidity_msat = used_liquidities .get(&$candidate.id()) .map_or(0, |used_liquidity_msat| { @@ -2953,7 +2959,7 @@ pub(crate) fn get_route( if should_log_candidate { log_trace!(logger, "Ignoring {} to avoid overpaying to meet htlc_minimum_msat limit ({}).", - LoggedCandidateHop(&$candidate), $candidate.htlc_minimum_msat()); + LoggedCandidateHop(&$candidate), $candidate.htlc_minimum().to_msat()); } num_ignored_avoid_overpayment += 1; hit_minimum_limit = true; @@ -3414,8 +3420,8 @@ pub(crate) fn get_route( Some(fee) => fee, None => continue }; - let path_min = candidate.htlc_minimum_msat().saturating_add( - compute_fees_saturating(candidate.htlc_minimum_msat(), candidate.fees())); + let path_min = candidate.htlc_minimum().to_msat().saturating_add( + compute_fees_saturating(candidate.htlc_minimum().to_msat(), candidate.fees())); add_entry!(&first_hop_candidate, blinded_path_fee, path_contribution_msat, path_min, 0_u64, candidate.cltv_expiry_delta(), 0); } @@ -3976,6 +3982,7 @@ mod tests { }; use crate::routing::test_utils::*; use crate::routing::utxo::UtxoResult; + use crate::types::amount::LightningAmount; use crate::types::features::{BlindedHopFeatures, ChannelFeatures, InitFeatures, NodeFeatures}; use crate::util::config::UserConfig; #[cfg(c_bindings)] @@ -4078,7 +4085,7 @@ mod tests { // Simple route to 2 via 1 let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 0); + payment_params.clone(), LightningAmount::from_msat(0)); if let Err(err) = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) { @@ -4086,7 +4093,7 @@ mod tests { } else { panic!(); } payment_params.max_path_length = 2; - let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, 100); + let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, LightningAmount::from_msat(100)); let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); assert_eq!(route.paths[0].hops.len(), 2); @@ -4123,7 +4130,7 @@ mod tests { let our_chans = [get_channel_details(Some(2), our_id, InitFeatures::from_le_bytes(vec![0b11]), 100000)]; - let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, LightningAmount::from_msat(100)); if let Err(err) = get_route(&our_id, &route_params, &network_graph.read_only(), Some(&our_chans.iter().collect::>()), Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) { @@ -4247,7 +4254,7 @@ mod tests { // Not possible to send 199_999_999, because the minimum on channel=2 is 200_000_000. let route_params = RouteParameters::from_payment_params_and_value( - payment_params, 199_999_999); + payment_params, LightningAmount::from_msat(199_999_999)); if let Err(err) = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) { @@ -4361,7 +4368,7 @@ mod tests { }); let mut route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 60_000); + payment_params.clone(), LightningAmount::from_msat(60_000)); route_params.max_total_routing_fee_msat = Some(15_000); let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); @@ -4420,7 +4427,7 @@ mod tests { let fees = route.paths[0].hops[0].fee_msat; assert_eq!(fees, 5_000); - let route_params = RouteParameters::from_payment_params_and_value(payment_params, 50_000); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, LightningAmount::from_msat(50_000)); let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); // Not fine to overpay for htlc_minimum_msat if it requires paying more than fee on @@ -4478,7 +4485,7 @@ mod tests { // what we try to find a route for, so this test only just happens to work out to exactly // the fee limit. let mut route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 5_000); + payment_params.clone(), LightningAmount::from_msat(5_000)); route_params.max_total_routing_fee_msat = Some(9_999); if let Err(err) = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, @@ -4487,7 +4494,7 @@ mod tests { } else { panic!(); } let mut route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 5_000); + payment_params.clone(), LightningAmount::from_msat(5_000)); route_params.max_total_routing_fee_msat = Some(10_000); let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); @@ -4532,7 +4539,7 @@ mod tests { }); // If all the channels require some features we don't understand, route should fail - let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, 100); + let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, LightningAmount::from_msat(100)); if let Err(err) = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) { @@ -4580,7 +4587,7 @@ mod tests { add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[7], unknown_features.clone(), 1); // If all nodes require some features we don't understand, route should fail - let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, LightningAmount::from_msat(100)); if let Err(err) = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) { @@ -4624,7 +4631,7 @@ mod tests { // Route to 1 via 2 and 3 because our channel to 1 is disabled let payment_params = PaymentParameters::from_node_id(nodes[0], 42); - let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, LightningAmount::from_msat(100)); let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); assert_eq!(route.paths[0].hops.len(), 3); @@ -4652,7 +4659,7 @@ mod tests { // If we specify a channel to node7, that overrides our local channel view and that gets used let payment_params = PaymentParameters::from_node_id(nodes[2], 42); - let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, LightningAmount::from_msat(100)); let our_chans = [get_channel_details(Some(42), nodes[7].clone(), InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)]; let route = get_route(&our_id, &route_params, &network_graph.read_only(), @@ -4783,7 +4790,7 @@ mod tests { { let payment_params = PaymentParameters::from_node_id(nodes[6], 42) .with_route_hints(invalid_last_hops).unwrap(); - let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, LightningAmount::from_msat(100)); if let Err(err) = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) { @@ -4794,7 +4801,7 @@ mod tests { let mut payment_params = PaymentParameters::from_node_id(nodes[6], 42) .with_route_hints(last_hops_multi_private_channels(&nodes)).unwrap(); payment_params.max_path_length = 5; - let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, LightningAmount::from_msat(100)); let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); assert_eq!(route.paths[0].hops.len(), 5); @@ -4872,7 +4879,7 @@ mod tests { let random_seed_bytes = [42; 32]; // Test handling of an empty RouteHint passed in Invoice. - let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, LightningAmount::from_msat(100)); let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); assert_eq!(route.paths[0].hops.len(), 5); @@ -4985,7 +4992,7 @@ mod tests { excess_data: Vec::new() }); - let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, 100); + let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, LightningAmount::from_msat(100)); route_params.payment_params.max_path_length = 4; let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); @@ -5066,7 +5073,7 @@ mod tests { excess_data: Vec::new() }); - let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, LightningAmount::from_msat(100)); let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &[42u8; 32]).unwrap(); assert_eq!(route.paths[0].hops.len(), 4); @@ -5152,7 +5159,7 @@ mod tests { // This test shows that public routes can be present in the invoice // which would be handled in the same manner. - let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, LightningAmount::from_msat(100)); let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); assert_eq!(route.paths[0].hops.len(), 5); @@ -5208,7 +5215,7 @@ mod tests { let mut last_hops = last_hops(&nodes); let payment_params = PaymentParameters::from_node_id(nodes[6], 42) .with_route_hints(last_hops.clone()).unwrap(); - let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, LightningAmount::from_msat(100)); let route = get_route(&our_id, &route_params, &network_graph.read_only(), Some(&our_chans.iter().collect::>()), Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); @@ -5234,7 +5241,7 @@ mod tests { let payment_params = PaymentParameters::from_node_id(nodes[6], 42) .with_route_hints(last_hops).unwrap(); let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 100); + payment_params.clone(), LightningAmount::from_msat(100)); let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); assert_eq!(route.paths[0].hops.len(), 4); @@ -5270,7 +5277,7 @@ mod tests { assert_eq!(route.paths[0].hops[3].channel_features.le_flags(), &Vec::::new()); // We can't learn any flags from invoices, sadly // ...but still use 8 for larger payments as 6 has a variable feerate - let route_params = RouteParameters::from_payment_params_and_value(payment_params, 2000); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, LightningAmount::from_msat(2000)); let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); assert_eq!(route.paths[0].hops.len(), 5); @@ -5337,7 +5344,7 @@ mod tests { let random_seed_bytes = [42; 32]; let logger = ln_test_utils::TestLogger::new(); let network_graph = NetworkGraph::new(Network::Testnet, &logger); - let route_params = RouteParameters::from_payment_params_and_value(payment_params, route_val); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, LightningAmount::from_msat(route_val)); let route = get_route(&source_node_id, &route_params, &network_graph.read_only(), Some(&our_chans.iter().collect::>()), &logger, &scorer, &Default::default(), &random_seed_bytes); @@ -5471,7 +5478,7 @@ mod tests { { // Attempt to route more than available results in a failure. let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 250_000_001); + payment_params.clone(), LightningAmount::from_msat(250_000_001)); if let Err(err) = get_route( &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) { @@ -5482,14 +5489,14 @@ mod tests { { // Now, attempt to route an exact amount we have should be fine. let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 250_000_000); + payment_params.clone(), LightningAmount::from_msat(250_000_000)); let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 1); let path = route.paths.last().unwrap(); assert_eq!(path.hops.len(), 2); assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]); - assert_eq!(path.final_value_msat(), 250_000_000); + assert_eq!(path.final_value().to_msat(), 250_000_000); } // Check that setting next_outbound_htlc_limit_msat in first_hops limits the channels. @@ -5514,7 +5521,7 @@ mod tests { { // Attempt to route more than available results in a failure. let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 200_000_001); + payment_params.clone(), LightningAmount::from_msat(200_000_001)); if let Err(err) = get_route( &our_id, &route_params, &network_graph.read_only(), Some(&our_chans.iter().collect::>()), Arc::clone(&logger), &scorer, @@ -5526,7 +5533,7 @@ mod tests { { // Now, attempt to route an exact amount we have should be fine. let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 200_000_000); + payment_params.clone(), LightningAmount::from_msat(200_000_000)); let route = get_route(&our_id, &route_params, &network_graph.read_only(), Some(&our_chans.iter().collect::>()), Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); @@ -5534,7 +5541,7 @@ mod tests { let path = route.paths.last().unwrap(); assert_eq!(path.hops.len(), 2); assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]); - assert_eq!(path.final_value_msat(), 200_000_000); + assert_eq!(path.final_value().to_msat(), 200_000_000); } // Enable channel #1 back. @@ -5571,7 +5578,7 @@ mod tests { { // Attempt to route more than available results in a failure. let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 15_001); + payment_params.clone(), LightningAmount::from_msat(15_001)); if let Err(err) = get_route( &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) { @@ -5582,14 +5589,14 @@ mod tests { { // Now, attempt to route an exact amount we have should be fine. let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 15_000); + payment_params.clone(), LightningAmount::from_msat(15_000)); let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 1); let path = route.paths.last().unwrap(); assert_eq!(path.hops.len(), 2); assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]); - assert_eq!(path.final_value_msat(), 15_000); + assert_eq!(path.final_value().to_msat(), 15_000); } // Now let's see if routing works if we know only capacity from the UTXO. @@ -5650,7 +5657,7 @@ mod tests { { // Attempt to route more than available results in a failure. let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 15_001); + payment_params.clone(), LightningAmount::from_msat(15_001)); if let Err(err) = get_route( &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) { @@ -5661,14 +5668,14 @@ mod tests { { // Now, attempt to route an exact amount we have should be fine. let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 15_000); + payment_params.clone(), LightningAmount::from_msat(15_000)); let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 1); let path = route.paths.last().unwrap(); assert_eq!(path.hops.len(), 2); assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]); - assert_eq!(path.final_value_msat(), 15_000); + assert_eq!(path.final_value().to_msat(), 15_000); } // Now let's see if routing chooses htlc_maximum_msat over UTXO capacity. @@ -5689,7 +5696,7 @@ mod tests { { // Attempt to route more than available results in a failure. let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 10_001); + payment_params.clone(), LightningAmount::from_msat(10_001)); if let Err(err) = get_route( &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) { @@ -5700,14 +5707,14 @@ mod tests { { // Now, attempt to route an exact amount we have should be fine. let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 10_000); + payment_params.clone(), LightningAmount::from_msat(10_000)); let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 1); let path = route.paths.last().unwrap(); assert_eq!(path.hops.len(), 2); assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]); - assert_eq!(path.final_value_msat(), 10_000); + assert_eq!(path.final_value().to_msat(), 10_000); } } @@ -5815,7 +5822,7 @@ mod tests { { // Attempt to route more than available results in a failure. let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 60_000); + payment_params.clone(), LightningAmount::from_msat(60_000)); if let Err(err) = get_route( &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) { @@ -5826,7 +5833,7 @@ mod tests { { // Now, attempt to route 49 sats (just a bit below the capacity). let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 49_000); + payment_params.clone(), LightningAmount::from_msat(49_000)); let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 1); @@ -5834,7 +5841,7 @@ mod tests { for path in &route.paths { assert_eq!(path.hops.len(), 4); assert_eq!(path.hops.last().unwrap().pubkey, nodes[3]); - total_amount_paid_msat += path.final_value_msat(); + total_amount_paid_msat += path.final_value().to_msat(); } assert_eq!(total_amount_paid_msat, 49_000); } @@ -5842,7 +5849,7 @@ mod tests { { // Attempt to route an exact amount is also fine let route_params = RouteParameters::from_payment_params_and_value( - payment_params, 50_000); + payment_params, LightningAmount::from_msat(50_000)); let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 1); @@ -5850,7 +5857,7 @@ mod tests { for path in &route.paths { assert_eq!(path.hops.len(), 4); assert_eq!(path.hops.last().unwrap().pubkey, nodes[3]); - total_amount_paid_msat += path.final_value_msat(); + total_amount_paid_msat += path.final_value().to_msat(); } assert_eq!(total_amount_paid_msat, 50_000); } @@ -5895,7 +5902,7 @@ mod tests { { let route_params = RouteParameters::from_payment_params_and_value( - payment_params, 50_000); + payment_params, LightningAmount::from_msat(50_000)); let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 1); @@ -5903,7 +5910,7 @@ mod tests { for path in &route.paths { assert_eq!(path.hops.len(), 2); assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]); - total_amount_paid_msat += path.final_value_msat(); + total_amount_paid_msat += path.final_value().to_msat(); } assert_eq!(total_amount_paid_msat, 50_000); } @@ -6058,7 +6065,7 @@ mod tests { { // Attempt to route more than available results in a failure. let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 300_000); + payment_params.clone(), LightningAmount::from_msat(300_000)); if let Err(err) = get_route( &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) { @@ -6070,7 +6077,7 @@ mod tests { // Attempt to route while setting max_path_count to 0 results in a failure. let zero_payment_params = payment_params.clone().with_max_path_count(0); let route_params = RouteParameters::from_payment_params_and_value( - zero_payment_params, 100); + zero_payment_params, LightningAmount::from_msat(100)); if let Err(err) = get_route( &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) { @@ -6084,7 +6091,7 @@ mod tests { // to account for 1/3 of the total value, which is violated by 2 out of 3 paths. let fail_payment_params = payment_params.clone().with_max_path_count(3); let route_params = RouteParameters::from_payment_params_and_value( - fail_payment_params, 250_000); + fail_payment_params, LightningAmount::from_msat(250_000)); if let Err(err) = get_route( &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) { @@ -6096,7 +6103,7 @@ mod tests { // Now, attempt to route 250 sats (just a bit below the capacity). // Our algorithm should provide us with these 3 paths. let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 250_000); + payment_params.clone(), LightningAmount::from_msat(250_000)); let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 3); @@ -6108,7 +6115,7 @@ mod tests { assert_eq!(path.hops.len(), 2); assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]); } - total_amount_paid_msat += path.final_value_msat(); + total_amount_paid_msat += path.final_value().to_msat(); } assert_eq!(total_amount_paid_msat, 250_000); } @@ -6116,7 +6123,7 @@ mod tests { { // Attempt to route an exact amount is also fine let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 290_000); + payment_params.clone(), LightningAmount::from_msat(290_000)); let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 3); @@ -6131,7 +6138,7 @@ mod tests { assert_eq!( NodeId::from_pubkey(&path.hops.last().unwrap().pubkey), payment_params.payee.blinded_route_hints().iter() - .find(|p| p.payinfo.htlc_maximum_msat == path.final_value_msat()) + .find(|p| p.payinfo.htlc_maximum_msat == path.final_value().to_msat()) .and_then(|p| p.public_introduction_node_id(&network_graph)) .copied() .unwrap() @@ -6143,7 +6150,7 @@ mod tests { assert_eq!(path.hops.len(), 2); assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]); } - total_amount_paid_msat += path.final_value_msat(); + total_amount_paid_msat += path.final_value().to_msat(); } assert_eq!(total_amount_paid_msat, 290_000); } @@ -6163,7 +6170,7 @@ mod tests { let mut total_paid_msat = 0; for path in &route.paths { assert_eq!(path.hops.last().unwrap().pubkey, nodes[3]); - total_value_transferred_msat += path.final_value_msat(); + total_value_transferred_msat += path.final_value().to_msat(); for hop in &path.hops { total_paid_msat += hop.fee_msat; } @@ -6182,7 +6189,7 @@ mod tests { let mut total_amount_paid_msat = 0; for path in &route.paths { assert_eq!(path.hops.last().unwrap().pubkey, nodes[3]); - total_amount_paid_msat += path.final_value_msat(); + total_amount_paid_msat += path.final_value().to_msat(); } assert_eq!(total_amount_paid_msat, 300_000); } @@ -6354,7 +6361,7 @@ mod tests { // Nothing to do here. let route_params = RouteParameters::from_payment_params_and_value( - payment_params, amt); + payment_params, LightningAmount::from_msat(amt)); let res = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes); res @@ -6536,7 +6543,7 @@ mod tests { { // Attempt to route more than available results in a failure. let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 210_000); + payment_params.clone(), LightningAmount::from_msat(210_000)); if let Err(err) = get_route( &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) { @@ -6566,7 +6573,7 @@ mod tests { let mut total_amount_paid_msat = 0; for path in &route.paths { assert_eq!(path.hops.last().unwrap().pubkey, nodes[3]); - total_amount_paid_msat += path.final_value_msat(); + total_amount_paid_msat += path.final_value().to_msat(); } assert_eq!(total_amount_paid_msat, 200_000); assert_eq!(route.get_total_fees(), 150_000); @@ -6666,7 +6673,7 @@ mod tests { // Get a route for 100 sats and check that we found the MPP route no problem and didn't // overpay at all. let route_params = RouteParameters::from_payment_params_and_value( - payment_params, 100_000); + payment_params, LightningAmount::from_msat(100_000)); let mut route = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 2); @@ -6795,7 +6802,7 @@ mod tests { { // Attempt to route more than available results in a failure. let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 150_000); + payment_params.clone(), LightningAmount::from_msat(150_000)); if let Err(err) = get_route( &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) { @@ -6807,7 +6814,7 @@ mod tests { // Now, attempt to route 125 sats (just a bit below the capacity of 3 channels). // Our algorithm should provide us with these 3 paths. let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 125_000); + payment_params.clone(), LightningAmount::from_msat(125_000)); let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 3); @@ -6815,7 +6822,7 @@ mod tests { for path in &route.paths { assert_eq!(path.hops.len(), 2); assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]); - total_amount_paid_msat += path.final_value_msat(); + total_amount_paid_msat += path.final_value().to_msat(); } assert_eq!(total_amount_paid_msat, 125_000); } @@ -6823,7 +6830,7 @@ mod tests { { // Attempt to route without the last small cheap channel let route_params = RouteParameters::from_payment_params_and_value( - payment_params, 90_000); + payment_params, LightningAmount::from_msat(90_000)); let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 2); @@ -6831,7 +6838,7 @@ mod tests { for path in &route.paths { assert_eq!(path.hops.len(), 2); assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]); - total_amount_paid_msat += path.final_value_msat(); + total_amount_paid_msat += path.final_value().to_msat(); } assert_eq!(total_amount_paid_msat, 90_000); } @@ -6983,7 +6990,7 @@ mod tests { { // Now ensure the route flows simply over nodes 1 and 4 to 6. let route_params = RouteParameters::from_payment_params_and_value( - payment_params, 10_000); + payment_params, LightningAmount::from_msat(10_000)); let route = get_route(&our_id, &route_params, &network.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 1); @@ -7058,7 +7065,7 @@ mod tests { // Now, attempt to route 90 sats, which is exactly 90 sats at the last hop, plus the // 200% fee charged channel 13 in the 1-to-2 direction. let mut route_params = RouteParameters::from_payment_params_and_value( - payment_params, 90_000); + payment_params, LightningAmount::from_msat(90_000)); route_params.max_total_routing_fee_msat = Some(90_000*2); let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); @@ -7132,7 +7139,7 @@ mod tests { // overshooting the htlc_maximum on channel 2. Thus, we should pick the (absurdly // expensive) channels 12-13 path. let mut route_params = RouteParameters::from_payment_params_and_value( - payment_params, 90_000); + payment_params, LightningAmount::from_msat(90_000)); route_params.max_total_routing_fee_msat = Some(90_000*2); let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); @@ -7177,7 +7184,7 @@ mod tests { { let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 100_000); + payment_params.clone(), LightningAmount::from_msat(100_000)); let route = get_route(&our_id, &route_params, &network_graph.read_only(), Some(&[ &get_channel_details(Some(3), nodes[0], channelmanager::provided_init_features(&config), 200_000), &get_channel_details(Some(2), nodes[0], channelmanager::provided_init_features(&config), 10_000), @@ -7191,7 +7198,7 @@ mod tests { } { let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 100_000); + payment_params.clone(), LightningAmount::from_msat(100_000)); let route = get_route(&our_id, &route_params, &network_graph.read_only(), Some(&[ &get_channel_details(Some(3), nodes[0], channelmanager::provided_init_features(&config), 50_000), &get_channel_details(Some(2), nodes[0], channelmanager::provided_init_features(&config), 50_000), @@ -7219,7 +7226,7 @@ mod tests { // smallest of them, avoiding further fragmenting our available outbound balance to // this node. let route_params = RouteParameters::from_payment_params_and_value( - payment_params, 100_000); + payment_params, LightningAmount::from_msat(100_000)); let route = get_route(&our_id, &route_params, &network_graph.read_only(), Some(&[ &get_channel_details(Some(2), nodes[0], channelmanager::provided_init_features(&config), 50_000), &get_channel_details(Some(3), nodes[0], channelmanager::provided_init_features(&config), 50_000), @@ -7250,7 +7257,7 @@ mod tests { let scorer = ln_test_utils::TestScorer::new(); let random_seed_bytes = [42; 32]; let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 100); + payment_params.clone(), LightningAmount::from_msat(100)); let route = get_route( &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::>(); @@ -7261,9 +7268,9 @@ mod tests { // Applying a 100 msat penalty to each hop results in taking channels 7 and 10 to nodes[6] // from nodes[2] rather than channel 6, 11, and 8, even though the longer path is cheaper. - let scorer = FixedPenaltyScorer::with_penalty(100); + let scorer = FixedPenaltyScorer::with_penalty(LightningAmount::from_msat(100)); let route_params = RouteParameters::from_payment_params_and_value( - payment_params, 100); + payment_params, LightningAmount::from_msat(100)); let route = get_route( &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::>(); @@ -7320,7 +7327,7 @@ mod tests { let scorer = ln_test_utils::TestScorer::new(); let random_seed_bytes = [42; 32]; let route_params = RouteParameters::from_payment_params_and_value( - payment_params, 100); + payment_params, LightningAmount::from_msat(100)); let route = get_route( &our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::>(); @@ -7436,7 +7443,7 @@ mod tests { .with_max_total_cltv_expiry_delta(feasible_max_total_cltv_delta); let random_seed_bytes = [42; 32]; let route_params = RouteParameters::from_payment_params_and_value( - feasible_payment_params, 100); + feasible_payment_params, LightningAmount::from_msat(100)); let route = get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::>(); @@ -7447,7 +7454,7 @@ mod tests { let fail_payment_params = PaymentParameters::from_node_id(nodes[6], 0).with_route_hints(last_hops(&nodes)).unwrap() .with_max_total_cltv_expiry_delta(fail_max_total_cltv_delta); let route_params = RouteParameters::from_payment_params_and_value( - fail_payment_params, 100); + fail_payment_params, LightningAmount::from_msat(100)); match get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) { @@ -7475,12 +7482,12 @@ mod tests { // We should be able to find a route initially, and then after we fail a few random // channels eventually we won't be able to any longer. let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 100); + payment_params.clone(), LightningAmount::from_msat(100)); assert!(get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).is_ok()); loop { let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 100); + payment_params.clone(), LightningAmount::from_msat(100)); if let Ok(route) = get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) { @@ -7507,7 +7514,7 @@ mod tests { // First check we can actually create a long route on this graph. let feasible_payment_params = PaymentParameters::from_node_id(nodes[18], 0); let route_params = RouteParameters::from_payment_params_and_value( - feasible_payment_params, 100); + feasible_payment_params, LightningAmount::from_msat(100)); let route = get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::>(); @@ -7516,7 +7523,7 @@ mod tests { // But we can't create a path surpassing the MAX_PATH_LENGTH_ESTIMATE limit. let fail_payment_params = PaymentParameters::from_node_id(nodes[19], 0); let route_params = RouteParameters::from_payment_params_and_value( - fail_payment_params, 100); + fail_payment_params, LightningAmount::from_msat(100)); match get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) { @@ -7538,7 +7545,7 @@ mod tests { let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops(&nodes)).unwrap(); let random_seed_bytes = [42; 32]; let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 100); + payment_params.clone(), LightningAmount::from_msat(100)); let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 1); @@ -7575,7 +7582,7 @@ mod tests { let random_seed_bytes = [42; 32]; let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 100); + payment_params.clone(), LightningAmount::from_msat(100)); let mut route = get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); add_random_cltv_offset(&mut route, &payment_params, &network_graph, &random_seed_bytes); @@ -7640,7 +7647,7 @@ mod tests { let random_seed_bytes = [42; 32]; let payment_params = PaymentParameters::from_node_id(nodes[3], 0); let hops = [nodes[1], nodes[2], nodes[4], nodes[3]]; - let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, LightningAmount::from_msat(100)); let route = build_route_from_hops_internal(&our_id, &hops, &route_params, &network_graph, Arc::clone(&logger), &random_seed_bytes).unwrap(); let route_hop_pubkeys = route.paths[0].hops.iter().map(|hop| hop.pubkey).collect::>(); @@ -7698,7 +7705,7 @@ mod tests { // considered when applying max_channel_saturation_power_of_half is less than the cost of // those when it is not applied. let route_params = RouteParameters::from_payment_params_and_value( - payment_params, 75_000_000); + payment_params, LightningAmount::from_msat(75_000_000)); let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &ProbabilisticScoringFeeParameters::default(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 2); @@ -7805,7 +7812,7 @@ mod tests { // Then check we can get a normal route let payment_params = PaymentParameters::from_node_id(nodes[10], 42); let route_params = RouteParameters::from_payment_params_and_value( - payment_params, 100); + payment_params, LightningAmount::from_msat(100)); let route = get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer, &scorer_params, &random_seed_bytes); assert!(route.is_ok()); @@ -7854,7 +7861,7 @@ mod tests { // Make sure we'll error if our route hints don't have enough liquidity according to their // htlc_maximum_msat. let mut route_params = RouteParameters::from_payment_params_and_value( - payment_params, max_htlc_msat + 1); + payment_params, LightningAmount::from_msat(max_htlc_msat + 1)); route_params.max_total_routing_fee_msat = None; if let Err(err) = get_route(&our_id, &route_params, &netgraph, None, Arc::clone(&logger), &scorer, &Default::default(), @@ -7871,7 +7878,7 @@ mod tests { .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config)) .unwrap(); let mut route_params = RouteParameters::from_payment_params_and_value( - payment_params, max_htlc_msat + 1); + payment_params, LightningAmount::from_msat(max_htlc_msat + 1)); route_params.max_total_routing_fee_msat = Some(max_htlc_msat * 2); let route = get_route(&our_id, &route_params, &netgraph, None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); @@ -7929,7 +7936,7 @@ mod tests { .unwrap(); let route_params = RouteParameters::from_payment_params_and_value( - payment_params, amt_msat); + payment_params, LightningAmount::from_msat(amt_msat)); let route = get_route(&our_node_id, &route_params, &network_graph.read_only(), Some(&first_hop.iter().collect::>()), Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); @@ -7967,7 +7974,7 @@ mod tests { blinded_path.clone(), blinded_path.clone() ]).with_bolt12_features(bolt12_features).unwrap(); let route_params = RouteParameters::from_payment_params_and_value( - payment_params, amt_msat); + payment_params, LightningAmount::from_msat(amt_msat)); let route = get_route(&our_node_id, &route_params, &network_graph.read_only(), Some(&first_hops.iter().collect::>()), Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); @@ -8259,7 +8266,7 @@ mod tests { assert_eq!(payment_params, decoded_params); let route_params = RouteParameters::from_payment_params_and_value( - payment_params, 1001); + payment_params, LightningAmount::from_msat(1001)); let route = get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 1); @@ -8309,7 +8316,7 @@ mod tests { let invalid_blinded_path_3 = dummy_one_hop_blinded_path(nodes[3], blinded_payinfo.clone()); let payment_params = PaymentParameters::blinded(vec![ invalid_blinded_path_2, invalid_blinded_path_3]); - let route_params = RouteParameters::from_payment_params_and_value(payment_params, 1001); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, LightningAmount::from_msat(1001)); match get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) { @@ -8321,7 +8328,7 @@ mod tests { let invalid_blinded_path = dummy_blinded_path(our_id, blinded_payinfo.clone()); let payment_params = PaymentParameters::blinded(vec![invalid_blinded_path]); - let route_params = RouteParameters::from_payment_params_and_value(payment_params, 1001); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, LightningAmount::from_msat(1001)); match get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) { @@ -8334,7 +8341,7 @@ mod tests { let mut invalid_blinded_path = dummy_one_hop_blinded_path(ln_test_utils::pubkey(46), blinded_payinfo); invalid_blinded_path.clear_blinded_hops(); let payment_params = PaymentParameters::blinded(vec![invalid_blinded_path]); - let route_params = RouteParameters::from_payment_params_and_value(payment_params, 1001); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, LightningAmount::from_msat(1001)); match get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) { @@ -8385,7 +8392,7 @@ mod tests { let payment_params = PaymentParameters::blinded(blinded_hints.clone()) .with_bolt12_features(bolt12_features).unwrap(); - let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, 100_000); + let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, LightningAmount::from_msat(100_000)); route_params.max_total_routing_fee_msat = Some(100_000); let route = get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); @@ -8395,10 +8402,10 @@ mod tests { assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]); if let Some(bt) = &path.blinded_tail { assert_eq!(bt.blinding_point, - blinded_hints.iter().find(|p| p.payinfo.htlc_maximum_msat == path.final_value_msat()) + blinded_hints.iter().find(|p| p.payinfo.htlc_maximum_msat == path.final_value().to_msat()) .map(|bp| bp.blinding_point()).unwrap()); } else { panic!(); } - total_amount_paid_msat += path.final_value_msat(); + total_amount_paid_msat += path.final_value().to_msat(); } assert_eq!(total_amount_paid_msat, 100_000); } @@ -8471,7 +8478,7 @@ mod tests { let netgraph = network_graph.read_only(); let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), amt_msat); + payment_params.clone(), LightningAmount::from_msat(amt_msat)); if let Err(err) = get_route(&nodes[0], &route_params, &netgraph, Some(&first_hops.iter().collect::>()), Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) { @@ -8481,7 +8488,7 @@ mod tests { // Sending an exact amount accounting for the blinded path fee works. let amt_minus_blinded_path_fee = amt_msat - blinded_payinfo.fee_base_msat as u64; let route_params = RouteParameters::from_payment_params_and_value( - payment_params, amt_minus_blinded_path_fee); + payment_params, LightningAmount::from_msat(amt_minus_blinded_path_fee)); let route = get_route(&nodes[0], &route_params, &netgraph, Some(&first_hops.iter().collect::>()), Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); @@ -8541,7 +8548,7 @@ mod tests { let netgraph = network_graph.read_only(); let route_params = RouteParameters::from_payment_params_and_value( - payment_params, amt_msat); + payment_params, LightningAmount::from_msat(amt_msat)); let route = get_route(&nodes[0], &route_params, &netgraph, Some(&first_hops.iter().collect::>()), Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); @@ -8583,7 +8590,7 @@ mod tests { let netgraph = network_graph.read_only(); let route_params = RouteParameters::from_payment_params_and_value( - payment_params, amt_msat); + payment_params, LightningAmount::from_msat(amt_msat)); if let Err(err) = get_route( &our_id, &route_params, &netgraph, None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes ) { @@ -8631,7 +8638,7 @@ mod tests { let netgraph = network_graph.read_only(); let route_params = RouteParameters::from_payment_params_and_value( - payment_params, amt_msat); + payment_params, LightningAmount::from_msat(amt_msat)); if let Err(err) = get_route( &our_id, &route_params, &netgraph, None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes ) { @@ -8701,7 +8708,7 @@ mod tests { let netgraph = network_graph.read_only(); let route_params = RouteParameters::from_payment_params_and_value( - payment_params, amt_msat); + payment_params, LightningAmount::from_msat(amt_msat)); if let Err(err) = get_route( &our_id, &route_params, &netgraph, Some(&first_hops.iter().collect::>()), Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes @@ -8780,7 +8787,7 @@ mod tests { let netgraph = network_graph.read_only(); let route_params = RouteParameters::from_payment_params_and_value( - payment_params, amt_msat); + payment_params, LightningAmount::from_msat(amt_msat)); let route = get_route( &our_id, &route_params, &netgraph, Some(&first_hops.iter().collect::>()), @@ -8844,7 +8851,7 @@ mod tests { let payment_params = PaymentParameters::blinded(blinded_hints.clone()) .with_bolt12_features(bolt12_features.clone()).unwrap(); let route_params = RouteParameters::from_payment_params_and_value( - payment_params, amt_msat); + payment_params, LightningAmount::from_msat(amt_msat)); let netgraph = network_graph.read_only(); if let Err(err) = get_route( @@ -8900,7 +8907,7 @@ mod tests { let netgraph = network_graph.read_only(); let route_params = RouteParameters::from_payment_params_and_value( - payment_params, amt_msat); + payment_params, LightningAmount::from_msat(amt_msat)); let route = get_route( &our_id, &route_params, &netgraph, Some(&first_hops.iter().collect::>()), Arc::clone(&logger), &scorer, &ProbabilisticScoringFeeParameters::default(), @@ -9013,7 +9020,7 @@ mod tests { .with_route_hints(vec![route_hint]).unwrap() .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config)).unwrap(); let route_params = RouteParameters::from_payment_params_and_value( - payment_params, amt_msat); + payment_params, LightningAmount::from_msat(amt_msat)); // First create an insufficient first hop for channel with SCID 1 and check we'd use the // route hint. @@ -9124,7 +9131,7 @@ mod tests { let payment_params = PaymentParameters::from_node_id(nodes[4], 42) .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config)) .unwrap(); - let route_params = RouteParameters::from_payment_params_and_value(payment_params, 1_000_000); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, LightningAmount::from_msat(1_000_000)); get_route(&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap_err(); @@ -9190,7 +9197,7 @@ mod tests { .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config)).unwrap(); let route_params = RouteParameters::from_payment_params_and_value( - payment_params, amt_msat); + payment_params, LightningAmount::from_msat(amt_msat)); let route = get_route(&our_node_id, &route_params, &network_graph.read_only(), @@ -9334,8 +9341,10 @@ mod tests { .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config)) .unwrap(); payment_params.max_channel_saturation_power_of_half = 0; - let route_params = - RouteParameters::from_payment_params_and_value(payment_params, 3_000_000); + let route_params = RouteParameters::from_payment_params_and_value( + payment_params, + LightningAmount::from_msat(3_000_000), + ); let route = get_route( &our_id, &route_params, @@ -9571,7 +9580,7 @@ pub(crate) mod bench_utils { let first_hop = first_hop(src); let amt_msat = starting_amount + seed % 1_000_000; let route_params = RouteParameters::from_payment_params_and_value( - params.clone(), amt_msat); + params.clone(), LightningAmount::from_msat(amt_msat)); let path_exists = get_route(&payer, &route_params, &graph.read_only(), Some(&[&first_hop]), &TestLogger::new(), scorer, score_params, &random_seed_bytes).is_ok(); @@ -9593,6 +9602,7 @@ pub mod benches { use crate::routing::gossip::NetworkGraph; use crate::routing::scoring::{FixedPenaltyScorer, ProbabilisticScoringFeeParameters}; use crate::routing::scoring::{ScoreLookUp, ScoreUpdate}; + use crate::types::amount::LightningAmount; use crate::types::features::Bolt11InvoiceFeatures; use crate::util::config::UserConfig; use crate::util::logger::{Logger, Record}; @@ -9609,7 +9619,7 @@ pub mod benches { pub fn generate_routes_with_zero_penalty_scorer(bench: &mut Criterion) { let logger = TestLogger::new(); let (network_graph, _) = bench_utils::read_graph_scorer(&logger).unwrap(); - let scorer = FixedPenaltyScorer::with_penalty(0); + let scorer = FixedPenaltyScorer::with_penalty(LightningAmount::from_msat(0)); generate_routes(bench, &network_graph, scorer, &Default::default(), Bolt11InvoiceFeatures::empty(), 0, "generate_routes_with_zero_penalty_scorer"); } @@ -9618,7 +9628,7 @@ pub mod benches { pub fn generate_mpp_routes_with_zero_penalty_scorer(bench: &mut Criterion) { let logger = TestLogger::new(); let (network_graph, _) = bench_utils::read_graph_scorer(&logger).unwrap(); - let scorer = FixedPenaltyScorer::with_penalty(0); + let scorer = FixedPenaltyScorer::with_penalty(LightningAmount::from_msat(0)); generate_routes(bench, &network_graph, scorer, &Default::default(), channelmanager::provided_bolt11_invoice_features(&UserConfig::default()), 0, "generate_mpp_routes_with_zero_penalty_scorer"); @@ -9712,7 +9722,7 @@ pub mod benches { let mut idx = 0; bench.bench_function(bench_name, |b| b.iter(|| { let (first_hop, params, amt) = &route_endpoints[idx % route_endpoints.len()]; - let route_params = RouteParameters::from_payment_params_and_value(params.clone(), *amt); + let route_params = RouteParameters::from_payment_params_and_value(params.clone(), LightningAmount::from_msat(*amt)); assert!(get_route(&payer, &route_params, &graph.read_only(), Some(&[first_hop]), &DummyLogger{}, &scorer, score_params, &random_seed_bytes).is_ok()); idx += 1; diff --git a/lightning/src/routing/scoring.rs b/lightning/src/routing/scoring.rs index 47621e37380..31e2393de81 100644 --- a/lightning/src/routing/scoring.rs +++ b/lightning/src/routing/scoring.rs @@ -20,6 +20,7 @@ //! # use lightning::routing::gossip::NetworkGraph; //! # use lightning::routing::router::{RouteParameters, find_route}; //! # use lightning::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringFeeParameters, ProbabilisticScoringDecayParameters}; +//! # use lightning::types::amount::LightningAmount; //! # use lightning::sign::KeysManager; //! # use lightning::util::logger::{Logger, Record}; //! # use bitcoin::secp256k1::PublicKey; @@ -38,7 +39,7 @@ //! //! // Or use custom channel penalties. //! let params = ProbabilisticScoringFeeParameters { -//! liquidity_penalty_multiplier_msat: 2 * 1000, +//! liquidity_penalty_multiplier: LightningAmount::from_msat(2 * 1000), //! ..ProbabilisticScoringFeeParameters::default() //! }; //! let decay_params = ProbabilisticScoringDecayParameters::default(); @@ -59,6 +60,7 @@ use crate::routing::gossip::{DirectedChannelInfo, EffectiveCapacity, NetworkGrap use crate::routing::log_approx; use crate::routing::router::{BlindedPathCandidate, CandidateRouteHop, Path, PublicHopCandidate}; use crate::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard}; +use crate::types::amount::LightningAmount; use crate::util::logger::Logger; use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer}; use bucketed_history::{ @@ -403,9 +405,9 @@ pub struct FixedPenaltyScorer { } impl FixedPenaltyScorer { - /// Creates a new scorer using `penalty_msat`. - pub fn with_penalty(penalty_msat: u64) -> Self { - Self { penalty_msat } + /// Creates a new scorer using `penalty`. + pub fn with_penalty(penalty: LightningAmount) -> Self { + Self { penalty_msat: penalty.to_msat() } } } @@ -459,8 +461,8 @@ impl ReadableArgs for FixedPenaltyScorer { /// *Optimally Reliable & Cheap Payment Flows on the Lightning Network* by Rene Pickhardt /// and Stefan Richter [[1]] (i.e. `(upper_bound - payment_amount) / (upper_bound - lower_bound)`). /// -/// This probability is combined with the [`liquidity_penalty_multiplier_msat`] and -/// [`liquidity_penalty_amount_multiplier_msat`] parameters to calculate a concrete penalty in +/// This probability is combined with the [`liquidity_penalty_multiplier`] and +/// [`liquidity_penalty_amount_multiplier`] parameters to calculate a concrete penalty in /// milli-satoshis. The penalties, when added across all hops, have the property of being linear in /// terms of the entire path's success probability. This allows the router to directly compare /// penalties for different paths. See the documentation of those parameters for the exact formulas. @@ -468,17 +470,17 @@ impl ReadableArgs for FixedPenaltyScorer { /// The liquidity bounds are decayed by halving them every [`liquidity_offset_half_life`]. /// /// Further, we track the history of our upper and lower liquidity bounds for each channel, -/// allowing us to assign a second penalty (using [`historical_liquidity_penalty_multiplier_msat`] -/// and [`historical_liquidity_penalty_amount_multiplier_msat`]) based on the same probability +/// allowing us to assign a second penalty (using [`historical_liquidity_penalty_multiplier`] +/// and [`historical_liquidity_penalty_amount_multiplier`]) based on the same probability /// formula, but using the history of a channel rather than our latest estimates for the liquidity /// bounds. /// /// [1]: https://arxiv.org/abs/2107.05322 -/// [`liquidity_penalty_multiplier_msat`]: ProbabilisticScoringFeeParameters::liquidity_penalty_multiplier_msat -/// [`liquidity_penalty_amount_multiplier_msat`]: ProbabilisticScoringFeeParameters::liquidity_penalty_amount_multiplier_msat +/// [`liquidity_penalty_multiplier`]: ProbabilisticScoringFeeParameters::liquidity_penalty_multiplier +/// [`liquidity_penalty_amount_multiplier`]: ProbabilisticScoringFeeParameters::liquidity_penalty_amount_multiplier /// [`liquidity_offset_half_life`]: ProbabilisticScoringDecayParameters::liquidity_offset_half_life -/// [`historical_liquidity_penalty_multiplier_msat`]: ProbabilisticScoringFeeParameters::historical_liquidity_penalty_multiplier_msat -/// [`historical_liquidity_penalty_amount_multiplier_msat`]: ProbabilisticScoringFeeParameters::historical_liquidity_penalty_amount_multiplier_msat +/// [`historical_liquidity_penalty_multiplier`]: ProbabilisticScoringFeeParameters::historical_liquidity_penalty_multiplier +/// [`historical_liquidity_penalty_amount_multiplier`]: ProbabilisticScoringFeeParameters::historical_liquidity_penalty_amount_multiplier pub struct ProbabilisticScorer>, L: Logger> { decay_params: ProbabilisticScoringDecayParameters, network_graph: G, @@ -583,35 +585,35 @@ impl Writeable for ChannelLiquidities { pub struct ProbabilisticScoringFeeParameters { /// A fixed penalty in msats to apply to each channel. /// - /// In testing, a value of roughly 1/10th of [`historical_liquidity_penalty_multiplier_msat`] + /// In testing, a value of roughly 1/10th of [`historical_liquidity_penalty_multiplier`] /// (implying scaling all estimated probabilities down by a factor of ~79%) resulted in the /// most accurate total success probabilities. /// /// Default value: 1,024 msat (i.e. we're willing to pay 1 sat to avoid each additional hop). /// - /// [`historical_liquidity_penalty_multiplier_msat`]: Self::historical_liquidity_penalty_multiplier_msat - pub base_penalty_msat: u64, + /// [`historical_liquidity_penalty_multiplier`]: Self::historical_liquidity_penalty_multiplier + pub base_penalty: LightningAmount, /// A multiplier used with the payment amount to calculate a fixed penalty applied to each - /// channel, in excess of the [`base_penalty_msat`]. + /// channel, in excess of the [`base_penalty`]. /// /// The purpose of the amount penalty is to avoid having fees dominate the channel cost (i.e., /// fees plus penalty) for large payments. The penalty is computed as the product of this /// multiplier and `2^30`ths of the payment amount. /// - /// ie `base_penalty_amount_multiplier_msat * amount_msat / 2^30` + /// ie `base_penalty_amount_multiplier * amount_msat / 2^30` /// /// In testing, a value of roughly ~100x (1/10th * 2^10) of - /// [`historical_liquidity_penalty_amount_multiplier_msat`] (implying scaling all estimated + /// [`historical_liquidity_penalty_amount_multiplier`] (implying scaling all estimated /// probabilities down by a factor of ~79%) resulted in the most accurate total success /// probabilities. /// /// Default value: 131,072 msat (i.e. we're willing to pay 0.125bps to avoid each additional /// hop). /// - /// [`base_penalty_msat`]: Self::base_penalty_msat - /// [`historical_liquidity_penalty_amount_multiplier_msat`]: Self::historical_liquidity_penalty_amount_multiplier_msat - pub base_penalty_amount_multiplier_msat: u64, + /// [`base_penalty`]: Self::base_penalty + /// [`historical_liquidity_penalty_amount_multiplier`]: Self::historical_liquidity_penalty_amount_multiplier + pub base_penalty_amount_multiplier: LightningAmount, /// A multiplier used in conjunction with the negative `log10` of the channel's success /// probability for a payment, as determined by our latest estimates of the channel's @@ -619,22 +621,22 @@ pub struct ProbabilisticScoringFeeParameters { /// /// The penalty is based in part on the knowledge learned from prior successful and unsuccessful /// payments. This knowledge is decayed over time based on [`liquidity_offset_half_life`]. The - /// penalty is effectively limited to `2 * liquidity_penalty_multiplier_msat` (corresponding to + /// penalty is effectively limited to `2 * liquidity_penalty_multiplier` (corresponding to /// lower bounding the success probability to `0.01`) when the amount falls within the /// uncertainty bounds of the channel liquidity balance. Amounts above the upper bound will /// result in a `u64::max_value` penalty, however. /// - /// `-log10(success_probability) * liquidity_penalty_multiplier_msat` + /// `-log10(success_probability) * liquidity_penalty_multiplier` /// /// In testing, this scoring model performs much worse than the historical scoring model - /// configured with the [`historical_liquidity_penalty_multiplier_msat`] and thus is disabled + /// configured with the [`historical_liquidity_penalty_multiplier`] and thus is disabled /// by default. /// /// Default value: 0 msat /// /// [`liquidity_offset_half_life`]: ProbabilisticScoringDecayParameters::liquidity_offset_half_life - /// [`historical_liquidity_penalty_multiplier_msat`]: Self::historical_liquidity_penalty_multiplier_msat - pub liquidity_penalty_multiplier_msat: u64, + /// [`historical_liquidity_penalty_multiplier`]: Self::historical_liquidity_penalty_multiplier + pub liquidity_penalty_multiplier: LightningAmount, /// A multiplier used in conjunction with the payment amount and the negative `log10` of the /// channel's success probability for the total amount flowing over a channel, as determined by @@ -645,7 +647,7 @@ pub struct ProbabilisticScoringFeeParameters { /// multiplier and `2^20`ths of the payment amount, weighted by the negative `log10` of the /// success probability. /// - /// `-log10(success_probability) * liquidity_penalty_amount_multiplier_msat * amount_msat / 2^20` + /// `-log10(success_probability) * liquidity_penalty_amount_multiplier * amount_msat / 2^20` /// /// In practice, this means for 0.1 success probability (`-log10(0.1) == 1`) each `2^20`th of /// the amount will result in a penalty of the multiplier. And, as the success probability @@ -654,19 +656,19 @@ pub struct ProbabilisticScoringFeeParameters { /// fall below `1`. /// /// In testing, this scoring model performs much worse than the historical scoring model - /// configured with the [`historical_liquidity_penalty_amount_multiplier_msat`] and thus is + /// configured with the [`historical_liquidity_penalty_amount_multiplier`] and thus is /// disabled by default. /// /// Default value: 0 msat /// - /// [`historical_liquidity_penalty_amount_multiplier_msat`]: Self::historical_liquidity_penalty_amount_multiplier_msat - pub liquidity_penalty_amount_multiplier_msat: u64, + /// [`historical_liquidity_penalty_amount_multiplier`]: Self::historical_liquidity_penalty_amount_multiplier + pub liquidity_penalty_amount_multiplier: LightningAmount, /// A multiplier used in conjunction with the negative `log10` of the channel's success /// probability for the payment, as determined based on the history of our estimates of the /// channel's available liquidity, to determine a penalty. /// - /// This penalty is similar to [`liquidity_penalty_multiplier_msat`], however, instead of using + /// This penalty is similar to [`liquidity_penalty_multiplier`], however, instead of using /// only our latest estimate for the current liquidity available in the channel, it estimates /// success probability based on the estimated liquidity available in the channel through /// history. Specifically, every time we update our liquidity bounds on a given channel, we @@ -676,8 +678,8 @@ pub struct ProbabilisticScoringFeeParameters { /// Default value: 10,000 msat (i.e. willing to pay 1 sat to avoid an 80% probability channel, /// or 6 sats to avoid a 25% probability channel). /// - /// [`liquidity_penalty_multiplier_msat`]: Self::liquidity_penalty_multiplier_msat - pub historical_liquidity_penalty_multiplier_msat: u64, + /// [`liquidity_penalty_multiplier`]: Self::liquidity_penalty_multiplier + pub historical_liquidity_penalty_multiplier: LightningAmount, /// A multiplier used in conjunction with the payment amount and the negative `log10` of the /// channel's success probability for the total amount flowing over a channel, as determined @@ -688,7 +690,7 @@ pub struct ProbabilisticScoringFeeParameters { /// large payments. The penalty is computed as the product of this multiplier and `2^20`ths /// of the payment amount, weighted by the negative `log10` of the success probability. /// - /// This penalty is similar to [`liquidity_penalty_amount_multiplier_msat`], however, instead + /// This penalty is similar to [`liquidity_penalty_amount_multiplier`], however, instead /// of using only our latest estimate for the current liquidity available in the channel, it /// estimates success probability based on the estimated liquidity available in the channel /// through history. Specifically, every time we update our liquidity bounds on a given @@ -699,8 +701,8 @@ pub struct ProbabilisticScoringFeeParameters { /// probability channels, or 0.5bps to avoid a 38% probability /// channel). /// - /// [`liquidity_penalty_amount_multiplier_msat`]: Self::liquidity_penalty_amount_multiplier_msat - pub historical_liquidity_penalty_amount_multiplier_msat: u64, + /// [`liquidity_penalty_amount_multiplier`]: Self::liquidity_penalty_amount_multiplier + pub historical_liquidity_penalty_amount_multiplier: LightningAmount, /// Manual penalties used for the given nodes. Allows to set a particular penalty for a given /// node. Note that a manual penalty of `u64::max_value()` means the node would not ever be @@ -716,15 +718,15 @@ pub struct ProbabilisticScoringFeeParameters { /// to restrict `htlc_maximum_msat` and improve privacy. /// /// Default value: 250 msat - pub anti_probing_penalty_msat: u64, + pub anti_probing_penalty: LightningAmount, /// This penalty is applied when the total amount flowing over a channel exceeds our current /// estimate of the channel's available liquidity. The total amount is the amount of the /// current HTLC plus any HTLCs which we've sent over the same channel. /// /// Note that in this case all other penalties, including the - /// [`liquidity_penalty_multiplier_msat`] and [`liquidity_penalty_amount_multiplier_msat`]-based - /// penalties, as well as the [`base_penalty_msat`] and the [`anti_probing_penalty_msat`], if + /// [`liquidity_penalty_multiplier`] and [`liquidity_penalty_amount_multiplier`]-based + /// penalties, as well as the [`base_penalty`] and the [`anti_probing_penalty`], if /// applicable, are still included in the overall penalty. /// /// If you wish to avoid creating paths with such channels entirely, setting this to a value of @@ -732,11 +734,11 @@ pub struct ProbabilisticScoringFeeParameters { /// /// Default value: 1_0000_0000_000 msat (1 Bitcoin) /// - /// [`liquidity_penalty_multiplier_msat`]: Self::liquidity_penalty_multiplier_msat - /// [`liquidity_penalty_amount_multiplier_msat`]: Self::liquidity_penalty_amount_multiplier_msat - /// [`base_penalty_msat`]: Self::base_penalty_msat - /// [`anti_probing_penalty_msat`]: Self::anti_probing_penalty_msat - pub considered_impossible_penalty_msat: u64, + /// [`liquidity_penalty_multiplier`]: Self::liquidity_penalty_multiplier + /// [`liquidity_penalty_amount_multiplier`]: Self::liquidity_penalty_amount_multiplier + /// [`base_penalty`]: Self::base_penalty + /// [`anti_probing_penalty`]: Self::anti_probing_penalty + pub considered_impossible_penalty: LightningAmount, /// In order to calculate most of the scores above, we must first convert a lower and upper /// bound on the available liquidity in a channel into the probability that we think a payment @@ -771,33 +773,33 @@ pub struct ProbabilisticScoringFeeParameters { /// pathfinding result for background probing. /// /// Specifically, the following penalty is applied - /// `probing_diversity_penalty_msat * max(0, (86400 - current time + last update))^2 / 86400^2` is + /// `probing_diversity_penalty * max(0, (86400 - current time + last update))^2 / 86400^2` is /// /// As this is a maximum value, when setting this you should consider it in relation to the /// other values set to ensure that, at maximum, we strongly avoid paths which we recently /// tried (similar to if they have a low success probability). For example, you might set this - /// to be the sum of [`Self::base_penalty_msat`] and - /// [`Self::historical_liquidity_penalty_multiplier_msat`] (plus some multiple of their + /// to be the sum of [`Self::base_penalty`] and + /// [`Self::historical_liquidity_penalty_multiplier`] (plus some multiple of their /// corresponding `amount_multiplier`s). /// /// Default value: 0 - pub probing_diversity_penalty_msat: u64, + pub probing_diversity_penalty: LightningAmount, } impl Default for ProbabilisticScoringFeeParameters { fn default() -> Self { Self { - base_penalty_msat: 1024, - base_penalty_amount_multiplier_msat: 131_072, - liquidity_penalty_multiplier_msat: 0, - liquidity_penalty_amount_multiplier_msat: 0, + base_penalty: LightningAmount::from_msat(1024), + base_penalty_amount_multiplier: LightningAmount::from_msat(131_072), + liquidity_penalty_multiplier: LightningAmount::from_msat(0), + liquidity_penalty_amount_multiplier: LightningAmount::from_msat(0), manual_node_penalties: new_hash_map(), - anti_probing_penalty_msat: 250, - considered_impossible_penalty_msat: 1_0000_0000_000, - historical_liquidity_penalty_multiplier_msat: 10_000, - historical_liquidity_penalty_amount_multiplier_msat: 1_250, + anti_probing_penalty: LightningAmount::from_msat(250), + considered_impossible_penalty: LightningAmount::from_msat(1_0000_0000_000), + historical_liquidity_penalty_multiplier: LightningAmount::from_msat(10_000), + historical_liquidity_penalty_amount_multiplier: LightningAmount::from_msat(1_250), linear_success_probability: false, - probing_diversity_penalty_msat: 0, + probing_diversity_penalty: LightningAmount::from_msat(0), } } } @@ -842,17 +844,17 @@ impl ProbabilisticScoringFeeParameters { impl ProbabilisticScoringFeeParameters { fn zero_penalty() -> Self { Self { - base_penalty_msat: 0, - base_penalty_amount_multiplier_msat: 0, - liquidity_penalty_multiplier_msat: 0, - liquidity_penalty_amount_multiplier_msat: 0, - historical_liquidity_penalty_multiplier_msat: 0, - historical_liquidity_penalty_amount_multiplier_msat: 0, + base_penalty: LightningAmount::from_msat(0), + base_penalty_amount_multiplier: LightningAmount::from_msat(0), + liquidity_penalty_multiplier: LightningAmount::from_msat(0), + liquidity_penalty_amount_multiplier: LightningAmount::from_msat(0), + historical_liquidity_penalty_multiplier: LightningAmount::from_msat(0), + historical_liquidity_penalty_amount_multiplier: LightningAmount::from_msat(0), manual_node_penalties: new_hash_map(), - anti_probing_penalty_msat: 0, - considered_impossible_penalty_msat: 0, + anti_probing_penalty: LightningAmount::from_msat(0), + considered_impossible_penalty: LightningAmount::from_msat(0), linear_success_probability: true, - probing_diversity_penalty_msat: 0, + probing_diversity_penalty: LightningAmount::from_msat(0), } } } @@ -993,7 +995,7 @@ impl>, L: Logger> ProbabilisticScorer { if let Some(chan_debug) = graph.channels().get(scid) { let log_direction = |source, target| { if let Some((directed_info, _)) = chan_debug.as_directed_to(target) { - let amt = directed_info.effective_capacity().as_msat(); + let amt = directed_info.effective_capacity().as_amount().to_msat(); let dir_liq = liq.as_directed(source, target, amt); let min_buckets = &dir_liq.liquidity_history.min_liquidity_offset_history_buckets(); @@ -1047,7 +1049,7 @@ impl>, L: Logger> ProbabilisticScorer { if let Some(chan) = graph.channels().get(&scid) { if let Some(liq) = self.channel_liquidities.get(&scid) { if let Some((directed_info, source)) = chan.as_directed_to(target) { - let amt = directed_info.effective_capacity().as_msat(); + let amt = directed_info.effective_capacity().as_amount().to_msat(); let dir_liq = liq.as_directed(source, target, amt); return Some((dir_liq.min_liquidity_msat(), dir_liq.max_liquidity_msat())); } @@ -1090,7 +1092,7 @@ impl>, L: Logger> ProbabilisticScorer { if let Some(chan) = graph.channels().get(&scid) { if let Some(liq) = self.channel_liquidities.get(&scid) { if let Some((directed_info, source)) = chan.as_directed_to(target) { - let amt = directed_info.effective_capacity().as_msat(); + let amt = directed_info.effective_capacity().as_amount().to_msat(); let dir_liq = liq.as_directed(source, target, amt); let min_buckets = *dir_liq.liquidity_history.min_liquidity_offset_history_buckets(); @@ -1129,7 +1131,7 @@ impl>, L: Logger> ProbabilisticScorer { if let Some(chan) = graph.channels().get(&scid) { if let Some((directed_info, source)) = chan.as_directed_to(target) { if let Some(liq) = self.channel_liquidities.get(&scid) { - let capacity_msat = directed_info.effective_capacity().as_msat(); + let capacity_msat = directed_info.effective_capacity().as_amount().to_msat(); let dir_liq = liq.as_directed(source, target, capacity_msat); let res = dir_liq.liquidity_history.calculate_success_probability_times_billion( @@ -1156,7 +1158,7 @@ impl>, L: Logger> ProbabilisticScorer { amt: u64, params: &ProbabilisticScoringFeeParameters, min_zero_penalty: bool, ) -> f64 { - let capacity_msat = directed_info.effective_capacity().as_msat(); + let capacity_msat = directed_info.effective_capacity().as_amount().to_msat(); let dummy_liq = ChannelLiquidity::new(Duration::ZERO); let liq = self.channel_liquidities.get(&scid) .unwrap_or(&dummy_liq) @@ -1457,8 +1459,8 @@ impl< let min_liquidity_msat = core::cmp::min(self.min_liquidity_msat(), max_liquidity_msat); let mut res = 0; - if score_params.liquidity_penalty_multiplier_msat != 0 || - score_params.liquidity_penalty_amount_multiplier_msat != 0 { + if score_params.liquidity_penalty_multiplier.to_msat() != 0 || + score_params.liquidity_penalty_amount_multiplier.to_msat() != 0 { if total_inflight_amount_msat <= min_liquidity_msat { // If the in-flight is less than the minimum liquidity estimate, we don't assign a // liquidity penalty at all (as the success probability is 100%). @@ -1468,8 +1470,8 @@ impl< // impossibility penalty. let negative_log10_times_2048 = NEGATIVE_LOG10_UPPER_BOUND * 2048; res = Self::combined_penalty_msat(amount_msat, negative_log10_times_2048, - score_params.liquidity_penalty_multiplier_msat, - score_params.liquidity_penalty_amount_multiplier_msat); + score_params.liquidity_penalty_multiplier.to_msat(), + score_params.liquidity_penalty_amount_multiplier.to_msat()); } else { let (numerator, denominator) = success_probability( total_inflight_amount_msat, min_liquidity_msat, max_liquidity_msat, @@ -1483,27 +1485,27 @@ impl< let negative_log10_times_2048 = log_approx::negative_log10_times_2048(numerator, denominator); res = Self::combined_penalty_msat(amount_msat, negative_log10_times_2048, - score_params.liquidity_penalty_multiplier_msat, - score_params.liquidity_penalty_amount_multiplier_msat); + score_params.liquidity_penalty_multiplier.to_msat(), + score_params.liquidity_penalty_amount_multiplier.to_msat()); } } } if total_inflight_amount_msat >= max_liquidity_msat { - res = res.saturating_add(score_params.considered_impossible_penalty_msat); + res = res.saturating_add(score_params.considered_impossible_penalty.to_msat()); } if total_inflight_amount_msat >= available_capacity { // We're trying to send more than the capacity, use a max penalty. res = res.saturating_add(Self::combined_penalty_msat(amount_msat, NEGATIVE_LOG10_UPPER_BOUND * 2048, - score_params.historical_liquidity_penalty_multiplier_msat, - score_params.historical_liquidity_penalty_amount_multiplier_msat)); + score_params.historical_liquidity_penalty_multiplier.to_msat(), + score_params.historical_liquidity_penalty_amount_multiplier.to_msat())); return res; } - if score_params.historical_liquidity_penalty_multiplier_msat != 0 || - score_params.historical_liquidity_penalty_amount_multiplier_msat != 0 { + if score_params.historical_liquidity_penalty_multiplier.to_msat() != 0 || + score_params.historical_liquidity_penalty_amount_multiplier.to_msat() != 0 { if let Some(cumulative_success_prob_times_billion) = self.liquidity_history .calculate_success_probability_times_billion( score_params, total_inflight_amount_msat, self.capacity_msat @@ -1512,8 +1514,8 @@ impl< let historical_negative_log10_times_2048 = log_approx::negative_log10_times_2048(cumulative_success_prob_times_billion + 1, 1024 * 1024 * 1024); res = res.saturating_add(Self::combined_penalty_msat(amount_msat, - historical_negative_log10_times_2048, score_params.historical_liquidity_penalty_multiplier_msat, - score_params.historical_liquidity_penalty_amount_multiplier_msat)); + historical_negative_log10_times_2048, score_params.historical_liquidity_penalty_multiplier.to_msat(), + score_params.historical_liquidity_penalty_amount_multiplier.to_msat())); } else { // If we don't have any valid points (or, once decayed, we have less than a full // point), redo the non-historical calculation with no liquidity bounds tracked and @@ -1525,12 +1527,12 @@ impl< let negative_log10_times_2048 = log_approx::negative_log10_times_2048(numerator, denominator); res = res.saturating_add(Self::combined_penalty_msat(amount_msat, negative_log10_times_2048, - score_params.historical_liquidity_penalty_multiplier_msat, - score_params.historical_liquidity_penalty_amount_multiplier_msat)); + score_params.historical_liquidity_penalty_multiplier.to_msat(), + score_params.historical_liquidity_penalty_amount_multiplier.to_msat())); } } - if score_params.probing_diversity_penalty_msat != 0 { + if score_params.probing_diversity_penalty.to_msat() != 0 { // We use `last_update_time` as a stand-in for the current time as we don't want to // fetch the current time in every score call (slowing things down substantially on // some platforms where a syscall is required), don't want to add an unnecessary `std` @@ -1538,7 +1540,7 @@ impl< // to the current time, (and using the last the last time we probed is also fine here). let time_since_update = last_update_time.saturating_sub(*self.last_datapoint_time); let mul = Duration::from_secs(60 * 60 * 24).saturating_sub(time_since_update).as_secs(); - let penalty = score_params.probing_diversity_penalty_msat.saturating_mul(mul * mul); + let penalty = score_params.probing_diversity_penalty.to_msat().saturating_mul(mul * mul); res = res.saturating_add(penalty / ((60 * 60 * 24) * (60 * 60 * 24))); } @@ -1679,7 +1681,7 @@ impl>, L: Logger> ScoreLookUp for Probabilisti if usage.amount_msat > hint.payinfo.htlc_maximum_msat { return u64::max_value(); } else if total_inflight_amount_msat > hint.payinfo.htlc_maximum_msat { - return score_params.considered_impossible_penalty_msat; + return score_params.considered_impossible_penalty.to_msat(); } else { return 0; } @@ -1691,8 +1693,8 @@ impl>, L: Logger> ScoreLookUp for Probabilisti return *penalty; } - let base_penalty_msat = score_params.base_penalty_msat.saturating_add( - score_params.base_penalty_amount_multiplier_msat + let base_penalty_msat = score_params.base_penalty.to_msat().saturating_add( + score_params.base_penalty_amount_multiplier.to_msat() .saturating_mul(usage.amount_msat) / BASE_AMOUNT_PENALTY_DIVISOR); let mut anti_probing_penalty_msat = 0; @@ -1708,13 +1710,13 @@ impl>, L: Logger> ScoreLookUp for Probabilisti }, EffectiveCapacity::Total { capacity_msat, htlc_maximum_msat } => { if htlc_maximum_msat >= capacity_msat/2 { - anti_probing_penalty_msat = score_params.anti_probing_penalty_msat; + anti_probing_penalty_msat = score_params.anti_probing_penalty.to_msat(); } }, _ => {}, } - let capacity_msat = usage.effective_capacity.as_msat(); + let capacity_msat = usage.effective_capacity.as_amount().to_msat(); let time = self.last_update_time; self.channel_liquidities .get(scid) @@ -1729,7 +1731,7 @@ impl>, L: Logger> ScoreLookUp for Probabilisti impl>, L: Logger> ScoreUpdate for ProbabilisticScorer { #[rustfmt::skip] fn payment_path_failed(&mut self, path: &Path, short_channel_id: u64, duration_since_epoch: Duration) { - let amount_msat = path.final_value_msat(); + let amount_msat = path.final_value().to_msat(); log_trace!(self.logger, "Scoring path through to SCID {} as having failed at {} msat", short_channel_id, amount_msat); let network_graph = self.network_graph.read_only(); for (hop_idx, hop) in path.hops.iter().enumerate() { @@ -1745,7 +1747,7 @@ impl>, L: Logger> ScoreUpdate for Probabilisti // Only score announced channels. if let Some((channel, source)) = channel_directed_from_source { - let capacity_msat = channel.effective_capacity().as_msat(); + let capacity_msat = channel.effective_capacity().as_amount().to_msat(); if at_failed_channel { self.channel_liquidities .entry(hop.short_channel_id) @@ -1772,7 +1774,7 @@ impl>, L: Logger> ScoreUpdate for Probabilisti #[rustfmt::skip] fn payment_path_successful(&mut self, path: &Path, duration_since_epoch: Duration) { - let amount_msat = path.final_value_msat(); + let amount_msat = path.final_value().to_msat(); log_trace!(self.logger, "Scoring path through SCID {} as having succeeded at {} msat.", path.hops.split_last().map(|(hop, _)| hop.short_channel_id).unwrap_or(0), amount_msat); let network_graph = self.network_graph.read_only(); @@ -1784,7 +1786,7 @@ impl>, L: Logger> ScoreUpdate for Probabilisti // Only score announced channels. if let Some((channel, source)) = channel_directed_from_source { - let capacity_msat = channel.effective_capacity().as_msat(); + let capacity_msat = channel.effective_capacity().as_amount().to_msat(); self.channel_liquidities .entry(hop.short_channel_id) .or_insert_with(|| ChannelLiquidity::new(duration_since_epoch)) @@ -2598,6 +2600,7 @@ mod tests { ProbabilisticScoringDecayParameters, ProbabilisticScoringFeeParameters, }; use crate::blinded_path::BlindedHop; + use crate::types::amount::LightningAmount; use crate::util::config::UserConfig; use crate::ln::channelmanager; @@ -2977,7 +2980,7 @@ mod tests { let logger = TestLogger::new(); let network_graph = network_graph(&logger); let params = ProbabilisticScoringFeeParameters { - liquidity_penalty_multiplier_msat: 1_000, + liquidity_penalty_multiplier: LightningAmount::from_msat(1_000), ..ProbabilisticScoringFeeParameters::zero_penalty() }; let decay_params = ProbabilisticScoringDecayParameters::default(); @@ -3033,8 +3036,8 @@ mod tests { let last_datapoint_time = Duration::ZERO; let network_graph = network_graph(&logger); let params = ProbabilisticScoringFeeParameters { - liquidity_penalty_multiplier_msat: 1_000, - considered_impossible_penalty_msat: u64::max_value(), + liquidity_penalty_multiplier: LightningAmount::from_msat(1_000), + considered_impossible_penalty: LightningAmount::from_msat(u64::max_value()), ..ProbabilisticScoringFeeParameters::zero_penalty() }; let decay_params = ProbabilisticScoringDecayParameters { @@ -3074,7 +3077,7 @@ mod tests { let logger = TestLogger::new(); let network_graph = network_graph(&logger); let params = ProbabilisticScoringFeeParameters { - liquidity_penalty_multiplier_msat: 1_000, + liquidity_penalty_multiplier: LightningAmount::from_msat(1_000), ..ProbabilisticScoringFeeParameters::zero_penalty() }; let mut scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); @@ -3108,7 +3111,7 @@ mod tests { let logger = TestLogger::new(); let network_graph = network_graph(&logger); let params = ProbabilisticScoringFeeParameters { - liquidity_penalty_multiplier_msat: 1_000, + liquidity_penalty_multiplier: LightningAmount::from_msat(1_000), ..ProbabilisticScoringFeeParameters::zero_penalty() }; let mut scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); @@ -3148,8 +3151,8 @@ mod tests { let logger = TestLogger::new(); let network_graph = network_graph(&logger); let params = ProbabilisticScoringFeeParameters { - liquidity_penalty_multiplier_msat: 1_000, - considered_impossible_penalty_msat: u64::max_value(), + liquidity_penalty_multiplier: LightningAmount::from_msat(1_000), + considered_impossible_penalty: LightningAmount::from_msat(u64::max_value()), ..ProbabilisticScoringFeeParameters::zero_penalty() }; let mut scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); @@ -3218,7 +3221,7 @@ mod tests { let node_c = NodeId::from_pubkey(&pub_c); let params = ProbabilisticScoringFeeParameters { - liquidity_penalty_multiplier_msat: 1_000, + liquidity_penalty_multiplier: LightningAmount::from_msat(1_000), ..ProbabilisticScoringFeeParameters::zero_penalty() }; let mut scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); @@ -3283,7 +3286,7 @@ mod tests { let logger = TestLogger::new(); let network_graph = network_graph(&logger); let params = ProbabilisticScoringFeeParameters { - liquidity_penalty_multiplier_msat: 1_000, + liquidity_penalty_multiplier: LightningAmount::from_msat(1_000), ..ProbabilisticScoringFeeParameters::zero_penalty() }; let mut scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); @@ -3328,8 +3331,8 @@ mod tests { let logger = TestLogger::new(); let network_graph = network_graph(&logger); let params = ProbabilisticScoringFeeParameters { - liquidity_penalty_multiplier_msat: 1_000, - considered_impossible_penalty_msat: u64::max_value(), + liquidity_penalty_multiplier: LightningAmount::from_msat(1_000), + considered_impossible_penalty: LightningAmount::from_msat(u64::max_value()), ..ProbabilisticScoringFeeParameters::zero_penalty() }; let decay_params = ProbabilisticScoringDecayParameters { @@ -3420,7 +3423,7 @@ mod tests { let logger = TestLogger::new(); let network_graph = network_graph(&logger); let params = ProbabilisticScoringFeeParameters { - liquidity_penalty_multiplier_msat: 1_000, + liquidity_penalty_multiplier: LightningAmount::from_msat(1_000), ..ProbabilisticScoringFeeParameters::zero_penalty() }; let decay_params = ProbabilisticScoringDecayParameters { @@ -3473,8 +3476,8 @@ mod tests { let logger = TestLogger::new(); let network_graph = network_graph(&logger); let params = ProbabilisticScoringFeeParameters { - liquidity_penalty_multiplier_msat: 1_000, - considered_impossible_penalty_msat: u64::max_value(), + liquidity_penalty_multiplier: LightningAmount::from_msat(1_000), + considered_impossible_penalty: LightningAmount::from_msat(u64::max_value()), ..ProbabilisticScoringFeeParameters::zero_penalty() }; let decay_params = ProbabilisticScoringDecayParameters { @@ -3518,8 +3521,8 @@ mod tests { let logger = TestLogger::new(); let network_graph = network_graph(&logger); let params = ProbabilisticScoringFeeParameters { - liquidity_penalty_multiplier_msat: 1_000, - considered_impossible_penalty_msat: u64::max_value(), + liquidity_penalty_multiplier: LightningAmount::from_msat(1_000), + considered_impossible_penalty: LightningAmount::from_msat(u64::max_value()), ..ProbabilisticScoringFeeParameters::zero_penalty() }; let decay_params = ProbabilisticScoringDecayParameters { @@ -3650,7 +3653,7 @@ mod tests { }; let params = ProbabilisticScoringFeeParameters { - liquidity_penalty_multiplier_msat: 1_000, + liquidity_penalty_multiplier: LightningAmount::from_msat(1_000), ..ProbabilisticScoringFeeParameters::zero_penalty() }; let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); @@ -3663,16 +3666,16 @@ mod tests { assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 58); let params = ProbabilisticScoringFeeParameters { - base_penalty_msat: 500, liquidity_penalty_multiplier_msat: 1_000, - anti_probing_penalty_msat: 0, ..ProbabilisticScoringFeeParameters::zero_penalty() + base_penalty: LightningAmount::from_msat(500), liquidity_penalty_multiplier: LightningAmount::from_msat(1_000), + anti_probing_penalty: LightningAmount::from_msat(0), ..ProbabilisticScoringFeeParameters::zero_penalty() }; let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 558); let params = ProbabilisticScoringFeeParameters { - base_penalty_msat: 500, liquidity_penalty_multiplier_msat: 1_000, - base_penalty_amount_multiplier_msat: (1 << 30), - anti_probing_penalty_msat: 0, ..ProbabilisticScoringFeeParameters::zero_penalty() + base_penalty: LightningAmount::from_msat(500), liquidity_penalty_multiplier: LightningAmount::from_msat(1_000), + base_penalty_amount_multiplier: LightningAmount::from_msat(1 << 30), + anti_probing_penalty: LightningAmount::from_msat(0), ..ProbabilisticScoringFeeParameters::zero_penalty() }; let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); @@ -3692,8 +3695,8 @@ mod tests { }; let params = ProbabilisticScoringFeeParameters { - liquidity_penalty_multiplier_msat: 1_000, - liquidity_penalty_amount_multiplier_msat: 0, + liquidity_penalty_multiplier: LightningAmount::from_msat(1_000), + liquidity_penalty_amount_multiplier: LightningAmount::from_msat(0), ..ProbabilisticScoringFeeParameters::zero_penalty() }; let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); @@ -3706,8 +3709,8 @@ mod tests { assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 300); let params = ProbabilisticScoringFeeParameters { - liquidity_penalty_multiplier_msat: 1_000, - liquidity_penalty_amount_multiplier_msat: 256, + liquidity_penalty_multiplier: LightningAmount::from_msat(1_000), + liquidity_penalty_amount_multiplier: LightningAmount::from_msat(256), ..ProbabilisticScoringFeeParameters::zero_penalty() }; let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); @@ -3726,7 +3729,7 @@ mod tests { effective_capacity: EffectiveCapacity::Infinite, }; let params = ProbabilisticScoringFeeParameters { - liquidity_penalty_multiplier_msat: 40_000, + liquidity_penalty_multiplier: LightningAmount::from_msat(40_000), ..ProbabilisticScoringFeeParameters::zero_penalty() }; let decay_params = ProbabilisticScoringDecayParameters::zero_penalty(); @@ -3746,7 +3749,7 @@ mod tests { let logger = TestLogger::new(); let network_graph = network_graph(&logger); let params = ProbabilisticScoringFeeParameters { - considered_impossible_penalty_msat: u64::max_value(), + considered_impossible_penalty: LightningAmount::from_msat(u64::max_value()), ..ProbabilisticScoringFeeParameters::zero_penalty() }; let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); @@ -3779,7 +3782,7 @@ mod tests { let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); let source = source_node_id(); - let base_penalty_msat = params.base_penalty_msat; + let base_penalty_msat = params.base_penalty.to_msat(); let usage = ChannelUsage { amount_msat: 750, inflight_htlc_msat: 0, @@ -3807,8 +3810,8 @@ mod tests { let logger = TestLogger::new(); let network_graph = network_graph(&logger); let params = ProbabilisticScoringFeeParameters { - historical_liquidity_penalty_multiplier_msat: 1024, - historical_liquidity_penalty_amount_multiplier_msat: 1024, + historical_liquidity_penalty_multiplier: LightningAmount::from_msat(1024), + historical_liquidity_penalty_amount_multiplier: LightningAmount::from_msat(1024), ..ProbabilisticScoringFeeParameters::zero_penalty() }; let decay_params = ProbabilisticScoringDecayParameters { @@ -3970,7 +3973,7 @@ mod tests { let network_graph = network_graph(&logger); let source = source_node_id(); let params = ProbabilisticScoringFeeParameters { - anti_probing_penalty_msat: 500, + anti_probing_penalty: LightningAmount::from_msat(500), ..ProbabilisticScoringFeeParameters::zero_penalty() }; let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); @@ -4022,7 +4025,7 @@ mod tests { let logger = TestLogger::new(); let network_graph = network_graph(&logger); let params = ProbabilisticScoringFeeParameters { - liquidity_penalty_multiplier_msat: 1_000, + liquidity_penalty_multiplier: LightningAmount::from_msat(1_000), ..ProbabilisticScoringFeeParameters::zero_penalty() }; let decay_params = ProbabilisticScoringDecayParameters::default(); @@ -4074,8 +4077,8 @@ mod tests { let logger = TestLogger::new(); let mut network_graph = network_graph(&logger); let params = ProbabilisticScoringFeeParameters { - historical_liquidity_penalty_multiplier_msat: 1024, - historical_liquidity_penalty_amount_multiplier_msat: 1024, + historical_liquidity_penalty_multiplier: LightningAmount::from_msat(1024), + historical_liquidity_penalty_amount_multiplier: LightningAmount::from_msat(1024), ..ProbabilisticScoringFeeParameters::zero_penalty() }; let decay_params = ProbabilisticScoringDecayParameters { @@ -4149,7 +4152,7 @@ mod tests { let logger = TestLogger::new(); let network_graph = network_graph(&logger); let params = ProbabilisticScoringFeeParameters { - liquidity_penalty_multiplier_msat: 1_000, + liquidity_penalty_multiplier: LightningAmount::from_msat(1_000), ..ProbabilisticScoringFeeParameters::zero_penalty() }; let mut scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); @@ -4251,11 +4254,11 @@ mod tests { #[test] #[rustfmt::skip] fn probes_for_diversity() { - // Tests the probing_diversity_penalty_msat is applied + // Tests the probing_diversity_penalty is applied let logger = TestLogger::new(); let network_graph = network_graph(&logger); let params = ProbabilisticScoringFeeParameters { - probing_diversity_penalty_msat: 1_000_000, + probing_diversity_penalty: LightningAmount::from_msat(1_000_000), ..ProbabilisticScoringFeeParameters::zero_penalty() }; let decay_params = ProbabilisticScoringDecayParameters { @@ -4283,7 +4286,7 @@ mod tests { // Apply an update to set the last-update time to 1 second scorer.payment_path_failed(&payment_path_for_amount(500), 42, Duration::from_secs(1)); - // If no time has passed, we get the full probing_diversity_penalty_msat + // If no time has passed, we get the full probing_diversity_penalty assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 1_000_000); // As time passes the penalty decreases.