Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions bindings/ldk_node.udl
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ typedef dictionary ElectrumSyncConfig;

typedef dictionary TorConfig;

typedef dictionary ScoringFeeParameters;

typedef dictionary ScoringDecayParameters;

typedef interface NodeEntropy;

typedef enum WordCount;
Expand Down Expand Up @@ -43,6 +47,8 @@ interface Builder {
void set_gossip_source_p2p();
void set_gossip_source_rgs(string rgs_server_url);
void set_pathfinding_scores_source(string url);
void set_scoring_fee_params(ScoringFeeParameters scoring_fee_params);
void set_scoring_decay_params(ScoringDecayParameters scoring_decay_params);
void set_liquidity_source_lsps1(PublicKey node_id, SocketAddress address, string? token);
void set_liquidity_source_lsps2(PublicKey node_id, SocketAddress address, string? token);
void set_storage_dir_path(string storage_dir_path);
Expand Down
66 changes: 62 additions & 4 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ use crate::chain::ChainSource;
use crate::config::{
default_user_config, may_announce_channel, AnnounceError, AsyncPaymentsRole,
BitcoindRestClientConfig, Config, ElectrumSyncConfig, EsploraSyncConfig, HRNResolverConfig,
TorConfig, DEFAULT_ESPLORA_SERVER_URL, DEFAULT_LOG_FILENAME, DEFAULT_LOG_LEVEL,
ScoringDecayParameters, ScoringFeeParameters, TorConfig, DEFAULT_ESPLORA_SERVER_URL,
DEFAULT_LOG_FILENAME, DEFAULT_LOG_LEVEL,
};
use crate::connection::ConnectionManager;
use crate::entropy::NodeEntropy;
Expand Down Expand Up @@ -444,6 +445,22 @@ impl NodeBuilder {
self
}

/// Configures the [`Node`] instance to use custom probabilistic scorer fee parameters.
pub fn set_scoring_fee_params(
&mut self, scoring_fee_params: ScoringFeeParameters,
) -> &mut Self {
self.config.scoring_fee_params = Some(scoring_fee_params);
self
}

/// Configures the [`Node`] instance to use custom probabilistic scorer decay parameters.
pub fn set_scoring_decay_params(
&mut self, scoring_decay_params: ScoringDecayParameters,
) -> &mut Self {
self.config.scoring_decay_params = Some(scoring_decay_params);
self
}

/// Configures the [`Node`] instance to source inbound liquidity from the given
/// [bLIP-51 / LSPS1] service.
///
Expand Down Expand Up @@ -965,6 +982,16 @@ impl ArcedNodeBuilder {
self.inner.write().expect("lock").set_pathfinding_scores_source(url);
}

/// Configures the [`Node`] instance to use custom probabilistic scorer fee parameters.
pub fn set_scoring_fee_params(&self, scoring_fee_params: ScoringFeeParameters) {
self.inner.write().expect("lock").set_scoring_fee_params(scoring_fee_params);
}

/// Configures the [`Node`] instance to use custom probabilistic scorer decay parameters.
pub fn set_scoring_decay_params(&self, scoring_decay_params: ScoringDecayParameters) {
self.inner.write().expect("lock").set_scoring_decay_params(scoring_decay_params);
}

/// Configures the [`Node`] instance to source inbound liquidity from the given
/// [bLIP-51 / LSPS1] service.
///
Expand Down Expand Up @@ -1614,7 +1641,8 @@ fn build_with_store_internal(
Ok(scorer) => scorer,
Err(e) => {
if e.kind() == std::io::ErrorKind::NotFound {
let params = ProbabilisticScoringDecayParameters::default();
let params: ProbabilisticScoringDecayParameters =
config.scoring_decay_params.unwrap_or_default().into();
ProbabilisticScorer::new(params, Arc::clone(&network_graph), Arc::clone(&logger))
} else {
log_error!(logger, "Failed to read scoring data from store: {}", e);
Expand All @@ -1639,7 +1667,8 @@ fn build_with_store_internal(
},
}

let scoring_fee_params = ProbabilisticScoringFeeParameters::default();
let scoring_fee_params: ProbabilisticScoringFeeParameters =
config.scoring_fee_params.unwrap_or_default().into();
let router = Arc::new(DefaultRouter::new(
Arc::clone(&network_graph),
Arc::clone(&logger),
Expand Down Expand Up @@ -2148,7 +2177,8 @@ pub(crate) fn sanitize_alias(alias_str: &str) -> Result<NodeAlias, BuildError> {

#[cfg(test)]
mod tests {
use super::{sanitize_alias, BuildError, NodeAlias};
use super::{sanitize_alias, BuildError, NodeAlias, NodeBuilder};
use crate::config::{ScoringDecayParameters, ScoringFeeParameters};

#[test]
fn sanitize_empty_node_alias() {
Expand Down Expand Up @@ -2185,4 +2215,32 @@ mod tests {
let node = sanitize_alias(alias);
assert_eq!(node.err().unwrap(), BuildError::InvalidNodeAlias);
}

#[test]
fn set_scoring_params_on_builder_config() {
let mut builder = NodeBuilder::new();

let scoring_fee_params = ScoringFeeParameters {
base_penalty_msat: 2_048,
base_penalty_amount_multiplier_msat: 262_144,
liquidity_penalty_multiplier_msat: 10,
liquidity_penalty_amount_multiplier_msat: 20,
historical_liquidity_penalty_multiplier_msat: 30,
historical_liquidity_penalty_amount_multiplier_msat: 40,
anti_probing_penalty_msat: 50,
considered_impossible_penalty_msat: 60,
linear_success_probability: true,
probing_diversity_penalty_msat: 70,
};
let scoring_decay_params = ScoringDecayParameters {
historical_no_updates_half_life_secs: 1234,
liquidity_offset_half_life_secs: 5678,
};

builder.set_scoring_fee_params(scoring_fee_params);
builder.set_scoring_decay_params(scoring_decay_params);

assert_eq!(builder.config.scoring_fee_params, Some(scoring_fee_params));
assert_eq!(builder.config.scoring_decay_params, Some(scoring_decay_params));
}
}
121 changes: 121 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ use bitcoin::Network;
use lightning::ln::msgs::SocketAddress;
use lightning::routing::gossip::NodeAlias;
use lightning::routing::router::RouteParametersConfig;
use lightning::routing::scoring::{
ProbabilisticScoringDecayParameters, ProbabilisticScoringFeeParameters,
};
use lightning::util::config::{
ChannelConfig as LdkChannelConfig, MaxDustHTLCExposure as LdkMaxDustHTLCExposure, UserConfig,
};
Expand Down Expand Up @@ -194,6 +197,14 @@ pub struct Config {
/// **Note:** If unset, default parameters will be used, and you will be able to override the
/// parameters on a per-payment basis in the corresponding method calls.
pub route_parameters: Option<RouteParametersConfig>,
/// Configuration options for the probabilistic routing scorer fee parameters.
///
/// **Note:** If unset, LDK's default values will be used.
pub scoring_fee_params: Option<ScoringFeeParameters>,
/// Configuration options for the probabilistic routing scorer decay parameters.
///
/// **Note:** If unset, LDK's default values will be used.
pub scoring_decay_params: Option<ScoringDecayParameters>,
/// Configuration options for enabling peer connections via the Tor network.
///
/// Setting [`TorConfig`] enables connecting to peers with OnionV3 addresses. No other connections
Expand All @@ -219,12 +230,122 @@ impl Default for Config {
anchor_channels_config: Some(AnchorChannelsConfig::default()),
tor_config: None,
route_parameters: None,
scoring_fee_params: None,
scoring_decay_params: None,
node_alias: None,
hrn_config: HumanReadableNamesConfig::default(),
}
}
}

/// Configuration options for probabilistic routing scorer fee-related penalties.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
pub struct ScoringFeeParameters {
/// A fixed penalty in msats to apply to each channel.
pub base_penalty_msat: u64,
/// Multiplier used with the amount for a fixed per-channel amount penalty.
pub base_penalty_amount_multiplier_msat: u64,
/// Multiplier used with channel success probability to determine liquidity penalty.
pub liquidity_penalty_multiplier_msat: u64,
/// Multiplier used with amount and success probability for liquidity amount penalty.
pub liquidity_penalty_amount_multiplier_msat: u64,
/// Multiplier for historical liquidity-based penalties.
pub historical_liquidity_penalty_multiplier_msat: u64,
/// Amount-aware multiplier for historical liquidity-based penalties.
pub historical_liquidity_penalty_amount_multiplier_msat: u64,
/// Penalty applied for channels with large `htlc_maximum_msat`.
pub anti_probing_penalty_msat: u64,
/// Penalty applied when amount exceeds estimated available channel liquidity.
pub considered_impossible_penalty_msat: u64,
/// If true, use a linear channel success probability distribution.
pub linear_success_probability: bool,
/// Additional penalty for recently probed channels, useful for probing diversity.
pub probing_diversity_penalty_msat: u64,
}

impl Default for ScoringFeeParameters {
fn default() -> Self {
ProbabilisticScoringFeeParameters::default().into()
}
}

impl From<ProbabilisticScoringFeeParameters> for ScoringFeeParameters {
fn from(value: ProbabilisticScoringFeeParameters) -> Self {
Self {
base_penalty_msat: value.base_penalty_msat,
base_penalty_amount_multiplier_msat: value.base_penalty_amount_multiplier_msat,
liquidity_penalty_multiplier_msat: value.liquidity_penalty_multiplier_msat,
liquidity_penalty_amount_multiplier_msat: value
.liquidity_penalty_amount_multiplier_msat,
historical_liquidity_penalty_multiplier_msat: value
.historical_liquidity_penalty_multiplier_msat,
historical_liquidity_penalty_amount_multiplier_msat: value
.historical_liquidity_penalty_amount_multiplier_msat,
anti_probing_penalty_msat: value.anti_probing_penalty_msat,
considered_impossible_penalty_msat: value.considered_impossible_penalty_msat,
linear_success_probability: value.linear_success_probability,
probing_diversity_penalty_msat: value.probing_diversity_penalty_msat,
}
}
}

impl From<ScoringFeeParameters> for ProbabilisticScoringFeeParameters {
fn from(value: ScoringFeeParameters) -> Self {
let mut ldk_value = ProbabilisticScoringFeeParameters::default();
ldk_value.base_penalty_msat = value.base_penalty_msat;
ldk_value.base_penalty_amount_multiplier_msat = value.base_penalty_amount_multiplier_msat;
ldk_value.liquidity_penalty_multiplier_msat = value.liquidity_penalty_multiplier_msat;
ldk_value.liquidity_penalty_amount_multiplier_msat =
value.liquidity_penalty_amount_multiplier_msat;
ldk_value.historical_liquidity_penalty_multiplier_msat =
value.historical_liquidity_penalty_multiplier_msat;
ldk_value.historical_liquidity_penalty_amount_multiplier_msat =
value.historical_liquidity_penalty_amount_multiplier_msat;
ldk_value.anti_probing_penalty_msat = value.anti_probing_penalty_msat;
ldk_value.considered_impossible_penalty_msat = value.considered_impossible_penalty_msat;
ldk_value.linear_success_probability = value.linear_success_probability;
ldk_value.probing_diversity_penalty_msat = value.probing_diversity_penalty_msat;
ldk_value
}
}

/// Configuration options for probabilistic routing scorer decay behavior.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
pub struct ScoringDecayParameters {
/// Time after which historical samples are decayed by half, in seconds.
pub historical_no_updates_half_life_secs: u64,
/// Time after which liquidity-offset bounds are decayed by half, in seconds.
pub liquidity_offset_half_life_secs: u64,
}

impl Default for ScoringDecayParameters {
fn default() -> Self {
ProbabilisticScoringDecayParameters::default().into()
}
}

impl From<ProbabilisticScoringDecayParameters> for ScoringDecayParameters {
fn from(value: ProbabilisticScoringDecayParameters) -> Self {
Self {
historical_no_updates_half_life_secs: value.historical_no_updates_half_life.as_secs(),
liquidity_offset_half_life_secs: value.liquidity_offset_half_life.as_secs(),
}
}
}

impl From<ScoringDecayParameters> for ProbabilisticScoringDecayParameters {
fn from(value: ScoringDecayParameters) -> Self {
Self {
historical_no_updates_half_life: Duration::from_secs(
value.historical_no_updates_half_life_secs,
),
liquidity_offset_half_life: Duration::from_secs(value.liquidity_offset_half_life_secs),
}
}
}

/// Configuration options for how our node resolves Human-Readable Names (BIP 353).
///
/// [BIP 353]: https://github.com/bitcoin/bips/blob/master/bip-0353.mediawiki
Expand Down
5 changes: 4 additions & 1 deletion src/ffi/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,10 @@ impl VssClientHeaderProvider for VssHeaderProviderAdapter {
}

use crate::builder::sanitize_alias;
pub use crate::config::{default_config, ElectrumSyncConfig, EsploraSyncConfig, TorConfig};
pub use crate::config::{
default_config, ElectrumSyncConfig, EsploraSyncConfig, ScoringDecayParameters,
ScoringFeeParameters, TorConfig,
};
pub use crate::entropy::{generate_entropy_mnemonic, NodeEntropy, WordCount};
use crate::error::Error;
pub use crate::liquidity::LSPS1OrderStatus;
Expand Down
Loading