(2, self.final_value_msat, required),
// LDK versions prior to 0.0.114 had the `final_cltv_expiry_delta` parameter in
// `RouteParameters` directly. For compatibility, we write it here.
(2, self.final_value_msat, required),
// LDK versions prior to 0.0.114 had the `final_cltv_expiry_delta` parameter in
// `RouteParameters` directly. For compatibility, we write it here.
- (4, self.payment_params.final_cltv_expiry_delta, required),
+ (4, self.payment_params.payee.final_cltv_expiry_delta(), option),
_init_and_read_tlv_fields!(reader, {
(0, payment_params, (required: ReadableArgs, 0)),
(2, final_value_msat, required),
_init_and_read_tlv_fields!(reader, {
(0, payment_params, (required: ReadableArgs, 0)),
(2, final_value_msat, required),
- (4, final_cltv_expiry_delta, required),
+ (4, final_cltv_delta, option),
- if payment_params.final_cltv_expiry_delta == 0 {
- payment_params.final_cltv_expiry_delta = final_cltv_expiry_delta.0.unwrap();
+ if let Payee::Clear { ref mut final_cltv_expiry_delta, .. } = payment_params.payee {
+ if final_cltv_expiry_delta == &0 {
+ *final_cltv_expiry_delta = final_cltv_delta.ok_or(DecodeError::InvalidValue)?;
+ }
/// payment to fail. Future attempts for the same payment shouldn't be relayed through any of
/// these SCIDs.
pub previously_failed_channels: Vec<u64>,
/// payment to fail. Future attempts for the same payment shouldn't be relayed through any of
/// these SCIDs.
pub previously_failed_channels: Vec<u64>,
(6, self.expiry_time, option),
(7, self.previously_failed_channels, vec_type),
(8, *blinded_hints, optional_vec),
(6, self.expiry_time, option),
(7, self.previously_failed_channels, vec_type),
(8, *blinded_hints, optional_vec),
- (9, self.final_cltv_expiry_delta, required),
+ (9, self.payee.final_cltv_expiry_delta(), option),
route_hints: clear_route_hints,
node_id: payee_pubkey.ok_or(DecodeError::InvalidValue)?,
features: features.and_then(|f| f.bolt11()),
route_hints: clear_route_hints,
node_id: payee_pubkey.ok_or(DecodeError::InvalidValue)?,
features: features.and_then(|f| f.bolt11()),
max_channel_saturation_power_of_half: _init_tlv_based_struct_field!(max_channel_saturation_power_of_half, (default_value, unused)),
expiry_time,
previously_failed_channels: previously_failed_channels.unwrap_or(Vec::new()),
max_channel_saturation_power_of_half: _init_tlv_based_struct_field!(max_channel_saturation_power_of_half, (default_value, unused)),
expiry_time,
previously_failed_channels: previously_failed_channels.unwrap_or(Vec::new()),
- payee: Payee::Clear { node_id: payee_pubkey, route_hints: vec![], features: None },
+ payee: Payee::Clear { node_id: payee_pubkey, route_hints: vec![], features: None, final_cltv_expiry_delta },
expiry_time: None,
max_total_cltv_expiry_delta: DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA,
max_path_count: DEFAULT_MAX_PATH_COUNT,
max_channel_saturation_power_of_half: 2,
previously_failed_channels: Vec::new(),
expiry_time: None,
max_total_cltv_expiry_delta: DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA,
max_path_count: DEFAULT_MAX_PATH_COUNT,
max_channel_saturation_power_of_half: 2,
previously_failed_channels: Vec::new(),
pub fn with_bolt11_features(self, features: InvoiceFeatures) -> Result<Self, ()> {
match self.payee {
Payee::Blinded { .. } => Err(()),
pub fn with_bolt11_features(self, features: InvoiceFeatures) -> Result<Self, ()> {
match self.payee {
Payee::Blinded { .. } => Err(()),
- Payee::Clear { route_hints, node_id, .. } =>
- Ok(Self { payee: Payee::Clear { route_hints, node_id, features: Some(features) }, ..self })
+ Payee::Clear { route_hints, node_id, final_cltv_expiry_delta, .. } =>
+ Ok(Self {
+ payee: Payee::Clear {
+ route_hints, node_id, features: Some(features), final_cltv_expiry_delta
+ }, ..self
+ })
pub fn with_route_hints(self, route_hints: Vec<RouteHint>) -> Result<Self, ()> {
match self.payee {
Payee::Blinded { .. } => Err(()),
pub fn with_route_hints(self, route_hints: Vec<RouteHint>) -> Result<Self, ()> {
match self.payee {
Payee::Blinded { .. } => Err(()),
- Payee::Clear { node_id, features, .. } =>
- Ok(Self { payee: Payee::Clear { route_hints, node_id, features }, ..self })
+ Payee::Clear { node_id, features, final_cltv_expiry_delta, .. } =>
+ Ok(Self {
+ payee: Payee::Clear {
+ route_hints, node_id, features, final_cltv_expiry_delta,
+ }, ..self
+ })
///
/// [`for_keysend`]: PaymentParameters::for_keysend
features: Option<InvoiceFeatures>,
///
/// [`for_keysend`]: PaymentParameters::for_keysend
features: Option<InvoiceFeatures>,
_ => return Err(LightningError{err: "Routing to blinded paths isn't supported yet".to_owned(), action: ErrorAction::IgnoreError}),
}
_ => return Err(LightningError{err: "Routing to blinded paths isn't supported yet".to_owned(), action: ErrorAction::IgnoreError}),
}
// In order to already account for some of the privacy enhancing random CLTV
// expiry delta offset we add on top later, we subtract a rough estimate
// (2*MEDIAN_HOP_CLTV_EXPIRY_DELTA) here.
// In order to already account for some of the privacy enhancing random CLTV
// expiry delta offset we add on top later, we subtract a rough estimate
// (2*MEDIAN_HOP_CLTV_EXPIRY_DELTA) here.
let hop_total_cltv_delta = ($next_hops_cltv_delta as u32)
.saturating_add($candidate.cltv_expiry_delta());
let exceeds_cltv_delta_limit = hop_total_cltv_delta > max_total_cltv_expiry_delta;
let hop_total_cltv_delta = ($next_hops_cltv_delta as u32)
.saturating_add($candidate.cltv_expiry_delta());
let exceeds_cltv_delta_limit = hop_total_cltv_delta > max_total_cltv_expiry_delta;
}).collect::<Vec<_>>();
// Propagate the cltv_expiry_delta one hop backwards since the delta from the current hop is
// applicable for the previous hop.
}).collect::<Vec<_>>();
// Propagate the cltv_expiry_delta one hop backwards since the delta from the current hop is
// applicable for the previous hop.
core::mem::replace(&mut hop.as_mut().unwrap().cltv_expiry_delta, prev_cltv_expiry_delta)
});
selected_paths.push(path);
core::mem::replace(&mut hop.as_mut().unwrap().cltv_expiry_delta, prev_cltv_expiry_delta)
});
selected_paths.push(path);
use crate::routing::scoring::{ChannelUsage, FixedPenaltyScorer, Score, ProbabilisticScorer, ProbabilisticScoringParameters};
use crate::routing::test_utils::{add_channel, add_or_update_node, build_graph, build_line_graph, id_to_feature_flags, get_nodes, update_channel};
use crate::chain::transaction::OutPoint;
use crate::routing::scoring::{ChannelUsage, FixedPenaltyScorer, Score, ProbabilisticScorer, ProbabilisticScoringParameters};
use crate::routing::test_utils::{add_channel, add_or_update_node, build_graph, build_line_graph, id_to_feature_flags, get_nodes, update_channel};
use crate::chain::transaction::OutPoint;
use crate::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
use crate::ln::msgs::{ErrorAction, LightningError, UnsignedChannelUpdate, MAX_VALUE_MSAT};
use crate::ln::channelmanager;
use crate::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
use crate::ln::msgs::{ErrorAction, LightningError, UnsignedChannelUpdate, MAX_VALUE_MSAT};
use crate::ln::channelmanager;
use bitcoin::hashes::Hash;
use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
use crate::chain::transaction::OutPoint;
use bitcoin::hashes::Hash;
use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
use crate::chain::transaction::OutPoint;
use crate::ln::channelmanager::{self, ChannelCounterparty, ChannelDetails};
use crate::ln::features::InvoiceFeatures;
use crate::routing::gossip::NetworkGraph;
use crate::ln::channelmanager::{self, ChannelCounterparty, ChannelDetails};
use crate::ln::features::InvoiceFeatures;
use crate::routing::gossip::NetworkGraph;