Skip to content
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ bdk_chain = { version = "0.23.3", default-features = false, features = ["std"] }
bdk_esplora = { version = "0.22.2", default-features = false, features = ["async-https-rustls", "tokio"]}
bdk_electrum = { version = "0.24.0", default-features = false, features = ["use-rustls-ring"]}
bdk_wallet = { version = "3.1.0", default-features = false, features = ["std", "keys-bip39"]}
bip157 = { version = "0.6.1", default-features = false }

bitreq = { version = "0.3", default-features = false, features = ["async-https", "json-using-serde"] }
rustls = { version = "0.23", default-features = false }
Expand Down
31 changes: 30 additions & 1 deletion src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ use lightning::util::sweep::OutputSweeper;
use lightning_dns_resolver::OMDomainResolver;
use vss_client::headers::VssHeaderProvider;

use crate::chain::ChainSource;
use crate::chain::{CbfFeeSourceConfig, ChainSource};
use crate::config::{
default_user_config, may_announce_channel, AnnounceError, AsyncPaymentsRole,
BitcoindRestClientConfig, Config, ElectrumSyncConfig, EsploraSyncConfig, HRNResolverConfig,
Expand Down Expand Up @@ -112,6 +112,10 @@ enum ChainDataSourceConfig {
rest_client_config: Option<BitcoindRestClientConfig>,
wallet_rescan_from_height: Option<u32>,
},
Cbf {
peers: Vec<String>,
fee_source_config: Option<CbfFeeSourceConfig>,
},
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -396,6 +400,19 @@ impl NodeBuilder {
self
}

/// Configures the [`Node`] instance to source chain data via compact block filters
/// (BIP157/BIP158), connecting to the given peers (`ip:port`).
///
/// `fee_source_config` optionally delegates fee estimation to an Esplora or Electrum server;
/// if `None`, fee rates are derived from recent blocks.
pub fn set_chain_source_cbf(
&mut self, peers: Vec<String>, fee_source_config: Option<CbfFeeSourceConfig>,
) -> &mut Self {
self.chain_data_source_config =
Some(ChainDataSourceConfig::Cbf { peers, fee_source_config });
self
}

/// Configures the [`Node`] instance to connect to a Bitcoin Core node via RPC.
///
/// This method establishes an RPC connection that enables all essential chain operations including
Expand Down Expand Up @@ -1514,6 +1531,18 @@ fn build_with_store_internal(
Arc::clone(&node_metrics),
)
},
Some(ChainDataSourceConfig::Cbf { peers, fee_source_config }) => ChainSource::new_cbf(
peers.clone(),
fee_source_config.clone(),
Arc::clone(&runtime),
Arc::clone(&fee_estimator),
Arc::clone(&tx_broadcaster),
Arc::clone(&kv_store),
Arc::clone(&config),
Arc::clone(&logger),
Arc::clone(&node_metrics),
)
.map_err(|_| BuildError::ChainSourceSetupFailed)?,
Some(ChainDataSourceConfig::Bitcoind {
rpc_host,
rpc_port,
Expand Down
25 changes: 25 additions & 0 deletions src/chain/bitcoind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1458,13 +1458,38 @@ pub(crate) enum FeeRateEstimationMode {
Conservative,
}

#[derive(Clone)]
pub(crate) struct ChainListener {
pub(crate) onchain_wallet: Arc<Wallet>,
pub(crate) channel_manager: Arc<ChannelManager>,
pub(crate) chain_monitor: Arc<ChainMonitor>,
pub(crate) output_sweeper: Arc<Sweeper>,
}

impl ChainListener {
pub(crate) fn get_best_block(&self) -> BlockLocator {
let candidates = [
self.onchain_wallet.current_best_block(),
self.channel_manager.current_best_block(),
self.output_sweeper.current_best_block(),
];
let mut min = candidates.into_iter().min_by_key(|b| b.height).expect("non-empty");
if let Some(worst_monitor) = self
.chain_monitor
.list_monitors()
.iter()
.flat_map(|id| self.chain_monitor.get_monitor(*id))
.map(|m| m.current_best_block())
.min_by_key(|b| b.height)
{
if worst_monitor.height < min.height {
min = worst_monitor;
}
}
min
}
}

impl Listen for ChainListener {
fn filtered_block_connected(
&self, header: &bitcoin::block::Header,
Expand Down
Loading
Loading