//! The payment recipient must include a [`PaymentHash`], so as to reveal the preimage upon payment
//! receipt, and one or more [`BlindedPath`]s for the payer to use when sending the payment.
//!
-//! ```ignore
+//! ```
//! extern crate bitcoin;
//! extern crate lightning;
//!
/// Information needed to route a payment across a [`BlindedPath`].
#[derive(Clone, Debug, PartialEq)]
pub struct BlindedPayInfo {
- fee_base_msat: u32,
- fee_proportional_millionths: u32,
- cltv_expiry_delta: u16,
- htlc_minimum_msat: u64,
- htlc_maximum_msat: u64,
- features: BlindedHopFeatures,
+ /// Base fee charged (in millisatoshi) for the entire blinded path.
+ pub fee_base_msat: u32,
+
+ /// Liquidity fee charged (in millionths of the amount transferred) for the entire blinded path
+ /// (i.e., 10,000 is 1%).
+ pub fee_proportional_millionths: u32,
+
+ /// Number of blocks subtracted from an incoming HTLC's `cltv_expiry` for the entire blinded
+ /// path.
+ pub cltv_expiry_delta: u16,
+
+ /// The minimum HTLC value (in millisatoshi) that is acceptable to all channel peers on the
+ /// blinded path from the introduction node to the recipient, accounting for any fees, i.e., as
+ /// seen by the recipient.
+ pub htlc_minimum_msat: u64,
+
+ /// The maximum HTLC value (in millisatoshi) that is acceptable to all channel peers on the
+ /// blinded path from the introduction node to the recipient, accounting for any fees, i.e., as
+ /// seen by the recipient.
+ pub htlc_maximum_msat: u64,
+
+ /// Features set in `encrypted_data_tlv` for the `encrypted_recipient_data` TLV record in an
+ /// onion payload.
+ pub features: BlindedHopFeatures,
}
impl_writeable!(BlindedPayInfo, {
}
}
+ #[cfg(feature = "std")]
+ #[test]
+ fn builds_invoice_from_offer_with_expiration() {
+ let future_expiry = Duration::from_secs(u64::max_value());
+ let past_expiry = Duration::from_secs(0);
+
+ if let Err(e) = OfferBuilder::new("foo".into(), recipient_pubkey())
+ .amount_msats(1000)
+ .absolute_expiry(future_expiry)
+ .build().unwrap()
+ .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
+ .build().unwrap()
+ .sign(payer_sign).unwrap()
+ .respond_with(payment_paths(), payment_hash())
+ .unwrap()
+ .build()
+ {
+ panic!("error building invoice: {:?}", e);
+ }
+
+ match OfferBuilder::new("foo".into(), recipient_pubkey())
+ .amount_msats(1000)
+ .absolute_expiry(past_expiry)
+ .build().unwrap()
+ .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
+ .build_unchecked()
+ .sign(payer_sign).unwrap()
+ .respond_with(payment_paths(), payment_hash())
+ .unwrap()
+ .build()
+ {
+ Ok(_) => panic!("expected error"),
+ Err(e) => assert_eq!(e, SemanticError::AlreadyExpired),
+ }
+ }
+
#[cfg(feature = "std")]
#[test]
fn builds_invoice_from_refund_with_expiration() {
.build().unwrap();
// Only standard addresses will be included.
- let mut fallbacks = unsigned_invoice.invoice.fields_mut().fallbacks.as_mut().unwrap();
+ let fallbacks = unsigned_invoice.invoice.fields_mut().fallbacks.as_mut().unwrap();
// Non-standard addresses
fallbacks.push(FallbackAddress { version: 1, program: vec![0u8; 41] });
fallbacks.push(FallbackAddress { version: 2, program: vec![0u8; 1] });