Skip to content

Commit e51c623

Browse files
Add checks for min value to all create_inbound_payment methods
1 parent 9224d25 commit e51c623

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

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

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

47384746
let payment_hash = PaymentHash(Sha256::hash(&payment_preimage_bytes).into_inner());
4739-
(payment_hash, PaymentSecret(payment_secret_bytes))
4747+
Ok((payment_hash, PaymentSecret(payment_secret_bytes)))
47404748
}
47414749

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

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