Skip to content
Open
6 changes: 5 additions & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,11 @@ jobs:
- name: Test on Rust ${{ matrix.toolchain }}
if: "matrix.platform != 'windows-latest'"
run: |
RUSTFLAGS="--cfg no_download --cfg cycle_tests" cargo test
RUSTFLAGS="--cfg no_download --cfg cycle_tests" cargo test -- --skip cbf
- name: Test CBF on Rust ${{ matrix.toolchain }}
if: "matrix.platform != 'windows-latest'"
run: |
RUSTFLAGS="--cfg no_download --cfg cycle_tests" cargo test cbf -- --test-threads=1
- name: Test with UniFFI support on Rust ${{ matrix.toolchain }}
if: "matrix.platform != 'windows-latest' && matrix.build-uniffi"
run: |
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ lightning-macros = { git = "https://github.com/lightningdevkit/rust-lightning",
bdk_chain = { version = "0.23.0", default-features = false, features = ["std"] }
bdk_esplora = { version = "0.22.0", default-features = false, features = ["async-https-rustls", "tokio"]}
bdk_electrum = { version = "0.23.0", default-features = false, features = ["use-rustls-ring"]}
bip157 = { version = "0.4.2", default-features = false }
bdk_wallet = { version = "2.3.0", default-features = false, features = ["std", "keys-bip39"]}

bitreq = { version = "0.3", default-features = false, features = ["async-https", "json-using-serde"] }
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ fn main() {
LDK Node currently comes with a decidedly opinionated set of design choices:

- On-chain data is handled by the integrated [BDK][bdk] wallet.
- Chain data may currently be sourced from the Bitcoin Core RPC interface, or from an [Electrum][electrum] or [Esplora][esplora] server.
- Chain data may currently be sourced from the Bitcoin Core RPC interface, from an [Electrum][electrum] or [Esplora][esplora] server, or via [compact block filters (BIP 157)][bip157] when the `cbf` feature is enabled.
- Wallet and channel state may be persisted to an [SQLite][sqlite] database, to file system, or to a custom back-end to be implemented by the user.
- Gossip data may be sourced via Lightning's peer-to-peer network or the [Rapid Gossip Sync](https://docs.rs/lightning-rapid-gossip-sync/*/lightning_rapid_gossip_sync/) protocol.
- Entropy for the Lightning and on-chain wallets may be sourced from raw bytes or a [BIP39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) mnemonic. In addition, LDK Node offers the means to generate and persist the entropy bytes to disk.
Expand All @@ -80,6 +80,7 @@ The Minimum Supported Rust Version (MSRV) is currently 1.85.0.
[bdk]: https://bitcoindevkit.org/
[electrum]: https://github.com/spesmilo/electrum-protocol
[esplora]: https://github.com/Blockstream/esplora
[bip157]: https://github.com/bitcoin/bips/blob/master/bip-0157.mediawiki
[sqlite]: https://sqlite.org/
[rust]: https://www.rust-lang.org/
[swift]: https://www.swift.org/
Expand Down
3 changes: 3 additions & 0 deletions bindings/ldk_node.udl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ typedef dictionary EsploraSyncConfig;

typedef dictionary ElectrumSyncConfig;

typedef dictionary CbfSyncConfig;

typedef interface NodeEntropy;

typedef enum WordCount;
Expand Down Expand Up @@ -36,6 +38,7 @@ interface Builder {
constructor(Config config);
void set_chain_source_esplora(string server_url, EsploraSyncConfig? config);
void set_chain_source_electrum(string server_url, ElectrumSyncConfig? config);
void set_chain_source_cbf(sequence<string> peers, CbfSyncConfig? sync_config);
void set_chain_source_bitcoind_rpc(string rpc_host, u16 rpc_port, string rpc_user, string rpc_password);
void set_chain_source_bitcoind_rest(string rest_host, u16 rest_port, string rpc_host, u16 rpc_port, string rpc_user, string rpc_password);
void set_gossip_source_p2p();
Expand Down
69 changes: 68 additions & 1 deletion src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ use vss_client::headers::VssHeaderProvider;
use crate::chain::ChainSource;
use crate::config::{
default_user_config, may_announce_channel, AnnounceError, AsyncPaymentsRole,
BitcoindRestClientConfig, Config, ElectrumSyncConfig, EsploraSyncConfig,
BitcoindRestClientConfig, CbfSyncConfig, Config, ElectrumSyncConfig, EsploraSyncConfig,
DEFAULT_ESPLORA_SERVER_URL, DEFAULT_LOG_FILENAME, DEFAULT_LOG_LEVEL,
};
use crate::connection::ConnectionManager;
Expand Down Expand Up @@ -105,6 +105,10 @@ enum ChainDataSourceConfig {
rpc_password: String,
rest_client_config: Option<BitcoindRestClientConfig>,
},
Cbf {
peers: Vec<String>,
sync_config: Option<CbfSyncConfig>,
},
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -376,6 +380,21 @@ impl NodeBuilder {
self
}

/// Configures the [`Node`] instance to source its chain data via BIP 157 compact block
/// filters.
///
/// `peers` is an optional list of peer addresses to connect to for sourcing compact block
/// filters. If empty, the node will discover peers via DNS seeds.
///
/// If no `sync_config` is given, default values are used. See [`CbfSyncConfig`] for more
/// information.
pub fn set_chain_source_cbf(
&mut self, peers: Vec<String>, sync_config: Option<CbfSyncConfig>,
) -> &mut Self {
self.chain_data_source_config = Some(ChainDataSourceConfig::Cbf { peers, sync_config });
self
}

/// Configures the [`Node`] instance to source its gossip data from the Lightning peer-to-peer
/// network.
pub fn set_gossip_source_p2p(&mut self) -> &mut Self {
Expand Down Expand Up @@ -805,6 +824,18 @@ impl ArcedNodeBuilder {
self.inner.write().unwrap().set_chain_source_electrum(server_url, sync_config);
}

/// Configures the [`Node`] instance to source its chain data via BIP 157 compact block
/// filters.
///
/// `peers` is an optional list of peer addresses to connect to for sourcing compact block
/// filters. If empty, the node will discover peers via DNS seeds.
///
/// If no `sync_config` is given, default values are used. See [`CbfSyncConfig`] for more
/// information.
pub fn set_chain_source_cbf(&self, peers: Vec<String>, sync_config: Option<CbfSyncConfig>) {
self.inner.write().unwrap().set_chain_source_cbf(peers, sync_config);
}

/// 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 @@ -1255,6 +1286,20 @@ fn build_with_store_internal(
}),
},

Some(ChainDataSourceConfig::Cbf { peers, sync_config }) => {
let sync_config = sync_config.clone().unwrap_or(CbfSyncConfig::default());
ChainSource::new_cbf(
peers.clone(),
sync_config,
Arc::clone(&fee_estimator),
Arc::clone(&tx_broadcaster),
Arc::clone(&kv_store),
Arc::clone(&config),
Arc::clone(&logger),
Arc::clone(&node_metrics),
)
},

None => {
// Default to Esplora client.
let server_url = DEFAULT_ESPLORA_SERVER_URL.to_string();
Expand Down Expand Up @@ -1972,6 +2017,9 @@ pub(crate) fn sanitize_alias(alias_str: &str) -> Result<NodeAlias, BuildError> {

#[cfg(test)]
mod tests {
#[cfg(feature = "uniffi")]
use crate::config::CbfSyncConfig;

use super::{sanitize_alias, BuildError, NodeAlias};

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

#[cfg(feature = "uniffi")]
#[test]
fn arced_builder_can_set_cbf_chain_source() {
let builder = super::ArcedNodeBuilder::new();
let sync_config = CbfSyncConfig::default();

let peers = vec!["127.0.0.1:8333".to_string()];
builder.set_chain_source_cbf(peers.clone(), Some(sync_config.clone()));

let guard = builder.inner.read().unwrap();
assert!(matches!(
guard.chain_data_source_config.as_ref(),
Some(super::ChainDataSourceConfig::Cbf {
peers: p,
sync_config: Some(config),
}) if config == &sync_config && p == &peers
));
}
}
Loading
Loading