Skip to content

Commit f2bc100

Browse files
committed
Add Bolt12CreationError error type to ChannelManager
Introduced the Bolt12CreationError error type for bolt12 errors that occur outside the builder. This error type is used in the ChannelManger functions. I moved, DuplicatePayment, and InsufficientLiquidity out of Bolt12SemanticsErrors into the new error type as well. Additionally, I updated the code to replace occurrences where we replaced Bolt12SemanticsErrors with the new Bolt12CreationError type throughout the relevant files.
1 parent 1916fc4 commit f2bc100

File tree

3 files changed

+51
-37
lines changed

3 files changed

+51
-37
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1700,10 +1700,9 @@ where
17001700
///
17011701
/// ```
17021702
/// # use lightning::events::{Event, EventsProvider, PaymentPurpose};
1703-
/// # use lightning::ln::channelmanager::AChannelManager;
1704-
/// # use lightning::offers::parse::Bolt12SemanticError;
1703+
/// # use lightning::ln::channelmanager::{AChannelManager, Bolt12CreationError};
17051704
/// #
1706-
/// # fn example<T: AChannelManager>(channel_manager: T) -> Result<(), Bolt12SemanticError> {
1705+
/// # fn example<T: AChannelManager>(channel_manager: T) -> Result<(), Bolt12CreationError> {
17071706
/// # let channel_manager = channel_manager.get_cm();
17081707
/// # let absolute_expiry = None;
17091708
/// let offer = channel_manager
@@ -1805,13 +1804,12 @@ where
18051804
/// ```
18061805
/// # use core::time::Duration;
18071806
/// # use lightning::events::{Event, EventsProvider};
1808-
/// # use lightning::ln::channelmanager::{AChannelManager, PaymentId, RecentPaymentDetails, Retry};
1809-
/// # use lightning::offers::parse::Bolt12SemanticError;
1807+
/// # use lightning::ln::channelmanager::{AChannelManager, Bolt12CreationError, PaymentId, RecentPaymentDetails, Retry};
18101808
/// #
18111809
/// # fn example<T: AChannelManager>(
18121810
/// # channel_manager: T, amount_msats: u64, absolute_expiry: Duration, retry: Retry,
18131811
/// # max_total_routing_fee_msat: Option<u64>
1814-
/// # ) -> Result<(), Bolt12SemanticError> {
1812+
/// # ) -> Result<(), Bolt12CreationError> {
18151813
/// # let channel_manager = channel_manager.get_cm();
18161814
/// let payment_id = PaymentId([42; 32]);
18171815
/// let refund = channel_manager
@@ -2526,6 +2524,26 @@ pub enum RecentPaymentDetails {
25262524
},
25272525
}
25282526

2527+
/// Error during creation and handling of BOLT 12 related payments.
2528+
#[derive(Debug, Clone, PartialEq)]
2529+
pub enum Bolt12CreationError {
2530+
/// Error from BOLT 12 semantic checks.
2531+
InvalidSemantics(Bolt12SemanticError),
2532+
/// The payment id for a refund or request is already in use.
2533+
DuplicatePaymentId,
2534+
/// There is insufficient liquidity to complete the payment.
2535+
InsufficientLiquidity,
2536+
/// Failed to create a blinded path.
2537+
BlindedPathCreationFailed,
2538+
}
2539+
2540+
impl From<Bolt12SemanticError> for Bolt12CreationError {
2541+
fn from(err: Bolt12SemanticError) -> Self {
2542+
Bolt12CreationError::InvalidSemantics(err)
2543+
}
2544+
}
2545+
2546+
25292547
/// Route hints used in constructing invoices for [phantom node payents].
25302548
///
25312549
/// [phantom node payments]: crate::sign::PhantomKeysManager
@@ -8801,7 +8819,7 @@ macro_rules! create_offer_builder { ($self: ident, $builder: ty) => {
88018819
/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
88028820
pub fn create_offer_builder(
88038821
&$self, absolute_expiry: Option<Duration>
8804-
) -> Result<$builder, Bolt12SemanticError> {
8822+
) -> Result<$builder, Bolt12CreationError> {
88058823
let node_id = $self.get_our_node_id();
88068824
let expanded_key = &$self.inbound_payment_key;
88078825
let entropy = &*$self.entropy_source;
@@ -8811,7 +8829,7 @@ macro_rules! create_offer_builder { ($self: ident, $builder: ty) => {
88118829
let context = OffersContext::InvoiceRequest { nonce };
88128830
let path = $self.create_blinded_paths_using_absolute_expiry(context, absolute_expiry)
88138831
.and_then(|paths| paths.into_iter().next().ok_or(()))
8814-
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
8832+
.map_err(|_| Bolt12CreationError::BlindedPathCreationFailed)?;
88158833
let builder = OfferBuilder::deriving_signing_pubkey(node_id, expanded_key, nonce, secp_ctx)
88168834
.chain_hash($self.chain_hash)
88178835
.path(path);
@@ -8874,7 +8892,7 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
88748892
pub fn create_refund_builder(
88758893
&$self, amount_msats: u64, absolute_expiry: Duration, payment_id: PaymentId,
88768894
retry_strategy: Retry, max_total_routing_fee_msat: Option<u64>
8877-
) -> Result<$builder, Bolt12SemanticError> {
8895+
) -> Result<$builder, Bolt12CreationError> {
88788896
let node_id = $self.get_our_node_id();
88798897
let expanded_key = &$self.inbound_payment_key;
88808898
let entropy = &*$self.entropy_source;
@@ -8884,7 +8902,7 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
88848902
let context = OffersContext::OutboundPayment { payment_id, nonce };
88858903
let path = $self.create_blinded_paths_using_absolute_expiry(context, Some(absolute_expiry))
88868904
.and_then(|paths| paths.into_iter().next().ok_or(()))
8887-
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
8905+
.map_err(|_| Bolt12CreationError::BlindedPathCreationFailed)?;
88888906

88898907
let builder = RefundBuilder::deriving_payer_id(
88908908
node_id, expanded_key, nonce, secp_ctx, amount_msats, payment_id
@@ -8900,7 +8918,7 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
89008918
.add_new_awaiting_invoice(
89018919
payment_id, expiration, retry_strategy, max_total_routing_fee_msat,
89028920
)
8903-
.map_err(|_| Bolt12SemanticError::DuplicatePaymentId)?;
8921+
.map_err(|_| Bolt12CreationError::DuplicatePaymentId)?;
89048922

89058923
Ok(builder.into())
89068924
}
@@ -8991,7 +9009,7 @@ where
89919009
&self, offer: &Offer, quantity: Option<u64>, amount_msats: Option<u64>,
89929010
payer_note: Option<String>, payment_id: PaymentId, retry_strategy: Retry,
89939011
max_total_routing_fee_msat: Option<u64>
8994-
) -> Result<(), Bolt12SemanticError> {
9012+
) -> Result<(), Bolt12CreationError> {
89959013
let expanded_key = &self.inbound_payment_key;
89969014
let entropy = &*self.entropy_source;
89979015
let secp_ctx = &self.secp_ctx;
@@ -9018,7 +9036,7 @@ where
90189036

90199037
let context = OffersContext::OutboundPayment { payment_id, nonce };
90209038
let reply_paths = self.create_blinded_paths(context)
9021-
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
9039+
.map_err(|_| Bolt12CreationError::BlindedPathCreationFailed)?;
90229040

90239041
let total_liquidity: u64 = self.list_usable_channels().iter().map(|channel| channel.next_outbound_htlc_limit_msat).sum();
90249042
let total_amount_msats = match invoice_request.amount_msats() {
@@ -9032,7 +9050,7 @@ where
90329050
if let Some(amount) = total_amount_msats {
90339051
if amount > total_liquidity {
90349052
log_error!(self.logger, "Insufficient liquidity for payment with payment id: {}", payment_id);
9035-
return Err(Bolt12SemanticError::InsufficientLiquidity);
9053+
return Err(Bolt12CreationError::InsufficientLiquidity);
90369054
}
90379055
}
90389056

@@ -9043,7 +9061,7 @@ where
90439061
.add_new_awaiting_invoice(
90449062
payment_id, expiration, retry_strategy, max_total_routing_fee_msat
90459063
)
9046-
.map_err(|_| Bolt12SemanticError::DuplicatePaymentId)?;
9064+
.map_err(|_| Bolt12CreationError::DuplicatePaymentId)?;
90479065

90489066
let mut pending_offers_messages = self.pending_offers_messages.lock().unwrap();
90499067
if !offer.paths().is_empty() {
@@ -9070,7 +9088,7 @@ where
90709088
}
90719089
} else {
90729090
debug_assert!(false);
9073-
return Err(Bolt12SemanticError::MissingSigningPubkey);
9091+
return Err(Bolt12CreationError::InvalidSemantics(Bolt12SemanticError::MissingSigningPubkey));
90749092
}
90759093

90769094
Ok(())
@@ -9100,7 +9118,7 @@ where
91009118
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
91019119
pub fn request_refund_payment(
91029120
&self, refund: &Refund
9103-
) -> Result<Bolt12Invoice, Bolt12SemanticError> {
9121+
) -> Result<Bolt12Invoice, Bolt12CreationError> {
91049122
let expanded_key = &self.inbound_payment_key;
91059123
let entropy = &*self.entropy_source;
91069124
let secp_ctx = &self.secp_ctx;
@@ -9109,7 +9127,7 @@ where
91099127
let relative_expiry = DEFAULT_RELATIVE_EXPIRY.as_secs() as u32;
91109128

91119129
if refund.chain() != self.chain_hash {
9112-
return Err(Bolt12SemanticError::UnsupportedChain);
9130+
return Err(Bolt12CreationError::InvalidSemantics(Bolt12SemanticError::UnsupportedChain));
91139131
}
91149132

91159133
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
@@ -9120,7 +9138,7 @@ where
91209138
let payment_paths = self.create_blinded_payment_paths(
91219139
amount_msats, payment_secret, payment_context
91229140
)
9123-
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
9141+
.map_err(|_| Bolt12CreationError::BlindedPathCreationFailed)?;
91249142

91259143
#[cfg(feature = "std")]
91269144
let builder = refund.respond_using_derived_keys(
@@ -9137,7 +9155,7 @@ where
91379155
let builder: InvoiceBuilder<DerivedSigningPubkey> = builder.into();
91389156
let invoice = builder.allow_mpp().build_and_sign(secp_ctx)?;
91399157
let reply_paths = self.create_blinded_paths(OffersContext::Unknown {})
9140-
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
9158+
.map_err(|_| Bolt12CreationError::BlindedPathCreationFailed)?;
91419159

91429160
let mut pending_offers_messages = self.pending_offers_messages.lock().unwrap();
91439161
if refund.paths().is_empty() {
@@ -9166,7 +9184,7 @@ where
91669184

91679185
Ok(invoice)
91689186
},
9169-
Err(()) => Err(Bolt12SemanticError::InvalidAmount),
9187+
Err(()) => Err(Bolt12CreationError::InvalidSemantics(Bolt12SemanticError::InvalidAmount)),
91709188
}
91719189
}
91729190

lightning/src/ln/offers_tests.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ use core::time::Duration;
4646
use crate::blinded_path::{BlindedPath, IntroductionNode};
4747
use crate::blinded_path::payment::{Bolt12OfferContext, Bolt12RefundContext, PaymentContext};
4848
use crate::events::{Event, MessageSendEventsProvider, PaymentPurpose};
49-
use crate::ln::channelmanager::{Bolt12PaymentError, MAX_SHORT_LIVED_RELATIVE_EXPIRY, PaymentId, RecentPaymentDetails, Retry, self};
49+
use crate::ln::channelmanager::{Bolt12CreationError, Bolt12PaymentError, MAX_SHORT_LIVED_RELATIVE_EXPIRY, PaymentId, RecentPaymentDetails, Retry, self};
5050
use crate::ln::functional_test_utils::*;
5151
use crate::ln::msgs::{ChannelMessageHandler, Init, NodeAnnouncement, OnionMessage, OnionMessageHandler, RoutingMessageHandler, SocketAddress, UnsignedGossipMessage, UnsignedNodeAnnouncement};
5252
use crate::ln::outbound_payment::IDEMPOTENCY_TIMEOUT_TICKS;
@@ -1600,7 +1600,7 @@ fn fails_creating_or_paying_for_offer_without_connected_peers() {
16001600
let absolute_expiry = alice.node.duration_since_epoch() + MAX_SHORT_LIVED_RELATIVE_EXPIRY;
16011601
match alice.node.create_offer_builder(Some(absolute_expiry)) {
16021602
Ok(_) => panic!("Expected error"),
1603-
Err(e) => assert_eq!(e, Bolt12SemanticError::MissingPaths),
1603+
Err(e) => assert_eq!(e, Bolt12CreationError::BlindedPathCreationFailed),
16041604
}
16051605

16061606
let mut args = ReconnectArgs::new(alice, bob);
@@ -1616,7 +1616,7 @@ fn fails_creating_or_paying_for_offer_without_connected_peers() {
16161616

16171617
match david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), None) {
16181618
Ok(_) => panic!("Expected error"),
1619-
Err(e) => assert_eq!(e, Bolt12SemanticError::MissingPaths),
1619+
Err(e) => assert_eq!(e, Bolt12CreationError::BlindedPathCreationFailed),
16201620
}
16211621

16221622
assert!(nodes[0].node.list_recent_payments().is_empty());
@@ -1674,7 +1674,7 @@ fn fails_creating_refund_or_sending_invoice_without_connected_peers() {
16741674
10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), None
16751675
) {
16761676
Ok(_) => panic!("Expected error"),
1677-
Err(e) => assert_eq!(e, Bolt12SemanticError::MissingPaths),
1677+
Err(e) => assert_eq!(e, Bolt12CreationError::BlindedPathCreationFailed),
16781678
}
16791679

16801680
let mut args = ReconnectArgs::new(charlie, david);
@@ -1688,7 +1688,7 @@ fn fails_creating_refund_or_sending_invoice_without_connected_peers() {
16881688

16891689
match alice.node.request_refund_payment(&refund) {
16901690
Ok(_) => panic!("Expected error"),
1691-
Err(e) => assert_eq!(e, Bolt12SemanticError::MissingPaths),
1691+
Err(e) => assert_eq!(e, Bolt12CreationError::BlindedPathCreationFailed),
16921692
}
16931693

16941694
let mut args = ReconnectArgs::new(alice, bob);
@@ -1720,7 +1720,7 @@ fn fails_creating_invoice_request_for_unsupported_chain() {
17201720
let payment_id = PaymentId([1; 32]);
17211721
match bob.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), None) {
17221722
Ok(_) => panic!("Expected error"),
1723-
Err(e) => assert_eq!(e, Bolt12SemanticError::UnsupportedChain),
1723+
Err(e) => assert_eq!(e, Bolt12CreationError::InvalidSemantics(Bolt12SemanticError::UnsupportedChain)),
17241724
}
17251725
}
17261726

@@ -1747,7 +1747,7 @@ fn fails_sending_invoice_with_unsupported_chain_for_refund() {
17471747

17481748
match alice.node.request_refund_payment(&refund) {
17491749
Ok(_) => panic!("Expected error"),
1750-
Err(e) => assert_eq!(e, Bolt12SemanticError::UnsupportedChain),
1750+
Err(e) => assert_eq!(e, Bolt12CreationError::InvalidSemantics(Bolt12SemanticError::UnsupportedChain)),
17511751
}
17521752
}
17531753

@@ -1780,7 +1780,7 @@ fn fails_creating_invoice_request_without_blinded_reply_path() {
17801780

17811781
match david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), None) {
17821782
Ok(_) => panic!("Expected error"),
1783-
Err(e) => assert_eq!(e, Bolt12SemanticError::MissingPaths),
1783+
Err(e) => assert_eq!(e, Bolt12CreationError::BlindedPathCreationFailed),
17841784
}
17851785

17861786
assert!(nodes[0].node.list_recent_payments().is_empty());
@@ -1820,7 +1820,7 @@ fn fails_creating_invoice_request_with_duplicate_payment_id() {
18201820

18211821
match david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), None) {
18221822
Ok(_) => panic!("Expected error"),
1823-
Err(e) => assert_eq!(e, Bolt12SemanticError::DuplicatePaymentId),
1823+
Err(e) => assert_eq!(e, Bolt12CreationError::DuplicatePaymentId),
18241824
}
18251825

18261826
expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id);
@@ -1848,7 +1848,7 @@ fn fails_creating_refund_with_duplicate_payment_id() {
18481848
10_000, absolute_expiry, payment_id, Retry::Attempts(0), None
18491849
) {
18501850
Ok(_) => panic!("Expected error"),
1851-
Err(e) => assert_eq!(e, Bolt12SemanticError::DuplicatePaymentId),
1851+
Err(e) => assert_eq!(e, Bolt12CreationError::DuplicatePaymentId),
18521852
}
18531853

18541854
expect_recent_payment!(nodes[0], RecentPaymentDetails::AwaitingInvoice, payment_id);
@@ -1970,7 +1970,7 @@ fn fails_sending_invoice_without_blinded_payment_paths_for_refund() {
19701970

19711971
match alice.node.request_refund_payment(&refund) {
19721972
Ok(_) => panic!("Expected error"),
1973-
Err(e) => assert_eq!(e, Bolt12SemanticError::MissingPaths),
1973+
Err(e) => assert_eq!(e, Bolt12CreationError::BlindedPathCreationFailed),
19741974
}
19751975
}
19761976

@@ -2093,7 +2093,7 @@ fn test_insufficient_liquidity_for_bolt12_offer() {
20932093
match result {
20942094
Ok(_) => panic!("Expected error with insufficient liquidity."),
20952095
Err(e) => {
2096-
assert_eq!(e, Bolt12SemanticError::InsufficientLiquidity);
2096+
assert_eq!(e, Bolt12CreationError::InsufficientLiquidity);
20972097
}
20982098
}
20992099
}

lightning/src/offers/parse.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,6 @@ pub enum Bolt12SemanticError {
177177
MissingPayerMetadata,
178178
/// A payer id was expected but was missing.
179179
MissingPayerId,
180-
/// The payment id for a refund or request is already in use.
181-
DuplicatePaymentId,
182180
/// Blinded paths were expected but were missing.
183181
MissingPaths,
184182
/// Blinded paths were provided but were not expected.
@@ -193,8 +191,6 @@ pub enum Bolt12SemanticError {
193191
UnexpectedPaymentHash,
194192
/// A signature was expected but was missing.
195193
MissingSignature,
196-
/// There is insufficient liquidity to complete the payment.
197-
InsufficientLiquidity,
198194
}
199195

200196
impl From<bech32::Error> for Bolt12ParseError {

0 commit comments

Comments
 (0)