Skip to content

Commit 2366984

Browse files
committed
Add BIP 157 compact block filter chain source
1 parent ee6c997 commit 2366984

File tree

9 files changed

+1287
-7
lines changed

9 files changed

+1287
-7
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ lightning-macros = { git = "https://github.com/lightningdevkit/rust-lightning",
5454
bdk_chain = { version = "0.23.0", default-features = false, features = ["std"] }
5555
bdk_esplora = { version = "0.22.0", default-features = false, features = ["async-https-rustls", "tokio"]}
5656
bdk_electrum = { version = "0.23.0", default-features = false, features = ["use-rustls-ring"]}
57+
bip157 = { version = "0.4.2", default-features = false }
5758
bdk_wallet = { version = "2.3.0", default-features = false, features = ["std", "keys-bip39"]}
5859

5960
bitreq = { version = "0.3", default-features = false, features = ["async-https", "json-using-serde"] }

bindings/ldk_node.udl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ typedef dictionary EsploraSyncConfig;
99

1010
typedef dictionary ElectrumSyncConfig;
1111

12+
typedef dictionary CbfSyncConfig;
13+
1214
typedef dictionary TorConfig;
1315

1416
typedef interface NodeEntropy;
@@ -38,6 +40,7 @@ interface Builder {
3840
constructor(Config config);
3941
void set_chain_source_esplora(string server_url, EsploraSyncConfig? config);
4042
void set_chain_source_electrum(string server_url, ElectrumSyncConfig? config);
43+
void set_chain_source_cbf(sequence<string> peers, CbfSyncConfig? sync_config);
4144
void set_chain_source_bitcoind_rpc(string rpc_host, u16 rpc_port, string rpc_user, string rpc_password);
4245
void set_chain_source_bitcoind_rest(string rest_host, u16 rest_port, string rpc_host, u16 rpc_port, string rpc_user, string rpc_password);
4346
void set_gossip_source_p2p();

src/builder.rs

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ use vss_client::headers::VssHeaderProvider;
4545
use crate::chain::ChainSource;
4646
use crate::config::{
4747
default_user_config, may_announce_channel, AnnounceError, AsyncPaymentsRole,
48-
BitcoindRestClientConfig, Config, ElectrumSyncConfig, EsploraSyncConfig, TorConfig,
49-
DEFAULT_ESPLORA_SERVER_URL, DEFAULT_LOG_FILENAME, DEFAULT_LOG_LEVEL,
48+
BitcoindRestClientConfig, CbfSyncConfig, Config, ElectrumSyncConfig, EsploraSyncConfig,
49+
TorConfig, DEFAULT_ESPLORA_SERVER_URL, DEFAULT_LOG_FILENAME, DEFAULT_LOG_LEVEL,
5050
};
5151
use crate::connection::ConnectionManager;
5252
use crate::entropy::NodeEntropy;
@@ -105,6 +105,10 @@ enum ChainDataSourceConfig {
105105
rpc_password: String,
106106
rest_client_config: Option<BitcoindRestClientConfig>,
107107
},
108+
Cbf {
109+
peers: Vec<String>,
110+
sync_config: Option<CbfSyncConfig>,
111+
},
108112
}
109113

110114
#[derive(Debug, Clone)]
@@ -365,6 +369,26 @@ impl NodeBuilder {
365369
self
366370
}
367371

372+
/// Configures the [`Node`] instance to source its chain data via BIP 157 compact block
373+
/// filters.
374+
///
375+
/// `peers` is an optional list of peer addresses to connect to for sourcing compact block
376+
/// filters. If empty, the node will discover peers via DNS seeds.
377+
///
378+
/// If no `sync_config` is given, default values are used. See [`CbfSyncConfig`] for more
379+
/// information.
380+
///
381+
/// Note: fee rate estimation with this chain source uses block-level averages (total fees
382+
/// divided by block weight) rather than per-transaction fee rates. This can underestimate
383+
/// next-block inclusion rates during periods of high mempool congestion. Percentile-based
384+
/// target selection partially mitigates this.
385+
pub fn set_chain_source_cbf(
386+
&mut self, peers: Vec<String>, sync_config: Option<CbfSyncConfig>,
387+
) -> &mut Self {
388+
self.chain_data_source_config = Some(ChainDataSourceConfig::Cbf { peers, sync_config });
389+
self
390+
}
391+
368392
/// Configures the [`Node`] instance to connect to a Bitcoin Core node via RPC.
369393
///
370394
/// This method establishes an RPC connection that enables all essential chain operations including
@@ -892,6 +916,23 @@ impl ArcedNodeBuilder {
892916
self.inner.write().unwrap().set_chain_source_electrum(server_url, sync_config);
893917
}
894918

919+
/// Configures the [`Node`] instance to source its chain data via BIP 157 compact block
920+
/// filters.
921+
///
922+
/// `peers` is an optional list of peer addresses to connect to for sourcing compact block
923+
/// filters. If empty, the node will discover peers via DNS seeds.
924+
///
925+
/// If no `sync_config` is given, default values are used. See [`CbfSyncConfig`] for more
926+
/// information.
927+
///
928+
/// Note: fee rate estimation with this chain source uses block-level averages (total fees
929+
/// divided by block weight) rather than per-transaction fee rates. This can underestimate
930+
/// next-block inclusion rates during periods of high mempool congestion. Percentile-based
931+
/// target selection partially mitigates this.
932+
pub fn set_chain_source_cbf(&self, peers: Vec<String>, sync_config: Option<CbfSyncConfig>) {
933+
self.inner.write().unwrap().set_chain_source_cbf(peers, sync_config);
934+
}
935+
895936
/// Configures the [`Node`] instance to connect to a Bitcoin Core node via RPC.
896937
///
897938
/// This method establishes an RPC connection that enables all essential chain operations including
@@ -1364,6 +1405,20 @@ fn build_with_store_internal(
13641405
}),
13651406
},
13661407

1408+
Some(ChainDataSourceConfig::Cbf { peers, sync_config }) => {
1409+
let sync_config = sync_config.clone().unwrap_or(CbfSyncConfig::default());
1410+
ChainSource::new_cbf(
1411+
peers.clone(),
1412+
sync_config,
1413+
Arc::clone(&fee_estimator),
1414+
Arc::clone(&tx_broadcaster),
1415+
Arc::clone(&kv_store),
1416+
Arc::clone(&config),
1417+
Arc::clone(&logger),
1418+
Arc::clone(&node_metrics),
1419+
)
1420+
},
1421+
13671422
None => {
13681423
// Default to Esplora client.
13691424
let server_url = DEFAULT_ESPLORA_SERVER_URL.to_string();
@@ -2079,6 +2134,9 @@ pub(crate) fn sanitize_alias(alias_str: &str) -> Result<NodeAlias, BuildError> {
20792134

20802135
#[cfg(test)]
20812136
mod tests {
2137+
#[cfg(feature = "uniffi")]
2138+
use crate::config::CbfSyncConfig;
2139+
20822140
use super::{sanitize_alias, BuildError, NodeAlias};
20832141

20842142
#[test]
@@ -2116,4 +2174,23 @@ mod tests {
21162174
let node = sanitize_alias(alias);
21172175
assert_eq!(node.err().unwrap(), BuildError::InvalidNodeAlias);
21182176
}
2177+
2178+
#[cfg(feature = "uniffi")]
2179+
#[test]
2180+
fn arced_builder_can_set_cbf_chain_source() {
2181+
let builder = super::ArcedNodeBuilder::new();
2182+
let sync_config = CbfSyncConfig::default();
2183+
2184+
let peers = vec!["127.0.0.1:8333".to_string()];
2185+
builder.set_chain_source_cbf(peers.clone(), Some(sync_config.clone()));
2186+
2187+
let guard = builder.inner.read().unwrap();
2188+
assert!(matches!(
2189+
guard.chain_data_source_config.as_ref(),
2190+
Some(super::ChainDataSourceConfig::Cbf {
2191+
peers: p,
2192+
sync_config: Some(config),
2193+
}) if config == &sync_config && p == &peers
2194+
));
2195+
}
21192196
}

0 commit comments

Comments
 (0)