Skip to content

Commit 369fbda

Browse files
Add checks for min value to all create_inbound_payment methods
1 parent 1e575f8 commit 369fbda

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};
@@ -4648,6 +4648,10 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
46484648
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> {
46494649
assert!(invoice_expiry_delta_secs <= 60*60*24*365); // Sadly bitcoin timestamps are u32s, so panic before 2106
46504650

4651+
if min_value_msat.is_some() && min_value_msat.unwrap() > MAX_VALUE_MSAT {
4652+
return Err(APIError::APIMisuseError { err: format!("min_value_msat of {} greater than total 21 million bitcoin supply", min_value_msat.unwrap()) });
4653+
}
4654+
46514655
let payment_secret = PaymentSecret(self.keys_manager.get_secure_random_bytes());
46524656

46534657
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier);
@@ -4697,7 +4701,11 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
46974701
/// [`PaymentReceived::payment_preimage`]: events::Event::PaymentReceived::payment_preimage
46984702
/// [`create_inbound_payment_for_hash`]: Self::create_inbound_payment_for_hash
46994703
// For details on the implementation of this method, see `verify_inbound_payment_data`.
4700-
pub fn create_inbound_payment(&self, min_value_msat: Option<u64>, invoice_expiry_delta_secs: u32) -> (PaymentHash, PaymentSecret) {
4704+
pub fn create_inbound_payment(&self, min_value_msat: Option<u64>, invoice_expiry_delta_secs: u32) -> Result<(PaymentHash, PaymentSecret), APIError> {
4705+
if min_value_msat.is_some() && min_value_msat.unwrap() > MAX_VALUE_MSAT {
4706+
return Err(APIError::APIMisuseError { err: format!("min_value_msat of {} greater than total 21 million bitcoin supply", min_value_msat.unwrap()) });
4707+
}
4708+
47014709
let min_amt_msat_bytes: [u8; 8] = match min_value_msat {
47024710
Some(amt) => amt.to_be_bytes(),
47034711
None => [0; 8],
@@ -4735,7 +4743,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
47354743
}
47364744

47374745
let payment_hash = PaymentHash(Sha256::hash(&payment_preimage_bytes).into_inner());
4738-
(payment_hash, PaymentSecret(payment_secret_bytes))
4746+
Ok((payment_hash, PaymentSecret(payment_secret_bytes)))
47394747
}
47404748

47414749
/// Legacy version of [`create_inbound_payment`]. Use this method if you wish to share
@@ -4745,12 +4753,11 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
47454753
/// This method will be deprecated in the next few versions.
47464754
///
47474755
/// [`create_inbound_payment`]: Self::create_inbound_payment
4748-
pub fn create_inbound_payment_legacy(&self, min_value_msat: Option<u64>, invoice_expiry_delta_secs: u32) -> (PaymentHash, PaymentSecret) {
4756+
pub fn create_inbound_payment_legacy(&self, min_value_msat: Option<u64>, invoice_expiry_delta_secs: u32) -> Result<(PaymentHash, PaymentSecret), APIError> {
47494757
let payment_preimage = PaymentPreimage(self.keys_manager.get_secure_random_bytes());
47504758
let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0).into_inner());
4751-
(payment_hash,
4752-
self.set_payment_hash_secret_map(payment_hash, Some(payment_preimage), min_value_msat, invoice_expiry_delta_secs)
4753-
.expect("RNG Generated Duplicate PaymentHash"))
4759+
let payment_secret = self.set_payment_hash_secret_map(payment_hash, Some(payment_preimage), min_value_msat, invoice_expiry_delta_secs)?;
4760+
Ok((payment_hash, payment_secret))
47544761
}
47554762

47564763
/// Gets a [`PaymentSecret`] for a given [`PaymentHash`], for which the payment preimage is
@@ -4797,6 +4804,10 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
47974804
/// [`PaymentReceived`]: events::Event::PaymentReceived
47984805
// For details on the implementation of this method, see `verify_inbound_payment_data`.
47994806
pub fn create_inbound_payment_for_hash(&self, payment_hash: PaymentHash, min_value_msat: Option<u64>, invoice_expiry_delta_secs: u32) -> Result<PaymentSecret, APIError> {
4807+
if min_value_msat.is_some() && min_value_msat.unwrap() > MAX_VALUE_MSAT {
4808+
return Err(APIError::APIMisuseError { err: format!("min_value_msat of {} greater than total 21 million bitcoin supply", min_value_msat.unwrap()) });
4809+
}
4810+
48004811
let mut min_amt_msat_bytes: [u8; 8] = match min_value_msat {
48014812
Some(amt) => amt.to_be_bytes(),
48024813
None => [0; 8],

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)