Skip to content

Commit 38740ee

Browse files
Add checks for min value to all create_inbound_payment methods
1 parent 9179991 commit 38740ee

File tree

3 files changed

+22
-11
lines changed

3 files changed

+22
-11
lines changed

lightning-invoice/src/utils.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ where
6363
let (payment_hash, payment_secret) = channelmanager.create_inbound_payment(
6464
amt_msat,
6565
DEFAULT_EXPIRY_TIME.try_into().unwrap(),
66-
);
66+
).unwrap();
6767
let our_node_pubkey = channelmanager.get_our_node_id();
6868
let mut invoice = InvoiceBuilder::new(network)
6969
.description(description)

lightning/src/ln/channelmanager.rs

+18-7
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ use routing::router::{Payee, Route, RouteHop, RoutePath, RouteParameters};
4949
use ln::msgs;
5050
use ln::msgs::NetAddress;
5151
use ln::onion_utils;
52-
use ln::msgs::{ChannelMessageHandler, DecodeError, LightningError, OptionalField};
52+
use ln::msgs::{ChannelMessageHandler, DecodeError, LightningError, MAX_VALUE_MSAT, OptionalField};
5353
use chain::keysinterface::{Sign, KeyMaterial, KeysInterface, KeysManager, InMemorySigner};
5454
use util::config::UserConfig;
5555
use util::events::{EventHandler, EventsProvider, MessageSendEvent, MessageSendEventsProvider, ClosureReason};
@@ -4626,6 +4626,10 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
46264626
fn set_payment_hash_secret_map(&self, payment_hash: PaymentHash, payment_preimage: Option<PaymentPreimage>, min_value_msat: Option<u64>, invoice_expiry_delta_secs: u32) -> Result<PaymentSecret, APIError> {
46274627
assert!(invoice_expiry_delta_secs <= 60*60*24*365); // Sadly bitcoin timestamps are u32s, so panic before 2106
46284628

4629+
if min_value_msat.is_some() && min_value_msat.unwrap() > MAX_VALUE_MSAT {
4630+
return Err(APIError::APIMisuseError { err: format!("min_value_msat of {} greater than total 21 million bitcoin supply", min_value_msat.unwrap()) });
4631+
}
4632+
46294633
let payment_secret = PaymentSecret(self.keys_manager.get_secure_random_bytes());
46304634

46314635
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier);
@@ -4675,7 +4679,11 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
46754679
/// [`PaymentReceived::payment_preimage`]: events::Event::PaymentReceived::payment_preimage
46764680
/// [`create_inbound_payment_for_hash`]: Self::create_inbound_payment_for_hash
46774681
// For details on the implementation of this method, see `verify_inbound_payment_data`.
4678-
pub fn create_inbound_payment(&self, min_value_msat: Option<u64>, invoice_expiry_delta_secs: u32) -> (PaymentHash, PaymentSecret) {
4682+
pub fn create_inbound_payment(&self, min_value_msat: Option<u64>, invoice_expiry_delta_secs: u32) -> Result<(PaymentHash, PaymentSecret), APIError> {
4683+
if min_value_msat.is_some() && min_value_msat.unwrap() > MAX_VALUE_MSAT {
4684+
return Err(APIError::APIMisuseError { err: format!("min_value_msat of {} greater than total 21 million bitcoin supply", min_value_msat.unwrap()) });
4685+
}
4686+
46794687
let (metadata_key, _, ldk_pmt_hash_key) = self.get_expanded_inbound_payment_key();
46804688
let min_amt_msat_bytes: [u8; 8] = match min_value_msat {
46814689
Some(amt) => amt.to_be_bytes(),
@@ -4714,7 +4722,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
47144722
}
47154723

47164724
let payment_hash = PaymentHash(Sha256::hash(&payment_preimage_bytes).into_inner());
4717-
(payment_hash, PaymentSecret(payment_secret_bytes))
4725+
Ok((payment_hash, PaymentSecret(payment_secret_bytes)))
47184726
}
47194727

47204728
/// Legacy version of [`create_inbound_payment`]. Use this method if you wish to share
@@ -4724,12 +4732,11 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
47244732
/// This method will be deprecated in the next few versions.
47254733
///
47264734
/// [`create_inbound_payment`]: Self::create_inbound_payment
4727-
pub fn create_inbound_payment_legacy(&self, min_value_msat: Option<u64>, invoice_expiry_delta_secs: u32) -> (PaymentHash, PaymentSecret) {
4735+
pub fn create_inbound_payment_legacy(&self, min_value_msat: Option<u64>, invoice_expiry_delta_secs: u32) -> Result<(PaymentHash, PaymentSecret), APIError> {
47284736
let payment_preimage = PaymentPreimage(self.keys_manager.get_secure_random_bytes());
47294737
let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0).into_inner());
4730-
(payment_hash,
4731-
self.set_payment_hash_secret_map(payment_hash, Some(payment_preimage), min_value_msat, invoice_expiry_delta_secs)
4732-
.expect("RNG Generated Duplicate PaymentHash"))
4738+
let payment_secret = self.set_payment_hash_secret_map(payment_hash, Some(payment_preimage), min_value_msat, invoice_expiry_delta_secs)?;
4739+
Ok((payment_hash, payment_secret))
47334740
}
47344741

47354742
/// Gets a [`PaymentSecret`] for a given [`PaymentHash`], for which the payment preimage is
@@ -4776,6 +4783,10 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
47764783
/// [`PaymentReceived`]: events::Event::PaymentReceived
47774784
// For details on the implementation of this method, see `verify_inbound_payment_data`.
47784785
pub fn create_inbound_payment_for_hash(&self, payment_hash: PaymentHash, min_value_msat: Option<u64>, invoice_expiry_delta_secs: u32) -> Result<PaymentSecret, APIError> {
4786+
if min_value_msat.is_some() && min_value_msat.unwrap() > MAX_VALUE_MSAT {
4787+
return Err(APIError::APIMisuseError { err: format!("min_value_msat of {} greater than total 21 million bitcoin supply", min_value_msat.unwrap()) });
4788+
}
4789+
47794790
let (metadata_key, user_pmt_hash_key, _) = self.get_expanded_inbound_payment_key();
47804791
let mut min_amt_msat_bytes: [u8; 8] = match min_value_msat {
47814792
Some(amt) => amt.to_be_bytes(),

lightning/src/ln/functional_tests.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -8073,7 +8073,7 @@ fn test_preimage_storage() {
80738073
create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
80748074

80758075
{
8076-
let (payment_hash, payment_secret) = nodes[1].node.create_inbound_payment(Some(100_000), 7200);
8076+
let (payment_hash, payment_secret) = nodes[1].node.create_inbound_payment(Some(100_000), 7200).unwrap();
80778077
let (route, _, _, _) = get_route_and_payment_hash!(nodes[0], nodes[1], 100_000);
80788078
nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret)).unwrap();
80798079
check_added_monitors!(nodes[0], 1);
@@ -8111,7 +8111,7 @@ fn test_secret_timeout() {
81118111

81128112
create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
81138113

8114-
let (payment_hash, payment_secret_1) = nodes[1].node.create_inbound_payment_legacy(Some(100_000), 2);
8114+
let (payment_hash, payment_secret_1) = nodes[1].node.create_inbound_payment_legacy(Some(100_000), 2).unwrap();
81158115

81168116
// We should fail to register the same payment hash twice, at least until we've connected a
81178117
// block with time 7200 + CHAN_CONFIRM_DEPTH + 1.
@@ -8178,7 +8178,7 @@ fn test_bad_secret_hash() {
81788178

81798179
let random_payment_hash = PaymentHash([42; 32]);
81808180
let random_payment_secret = PaymentSecret([43; 32]);
8181-
let (our_payment_hash, our_payment_secret) = nodes[1].node.create_inbound_payment(Some(100_000), 2);
8181+
let (our_payment_hash, our_payment_secret) = nodes[1].node.create_inbound_payment(Some(100_000), 2).unwrap();
81828182
let (route, _, _, _) = get_route_and_payment_hash!(nodes[0], nodes[1], 100_000);
81838183

81848184
// All the below cases should end up being handled exactly identically, so we macro the

0 commit comments

Comments
 (0)