Skip to content

Commit 822fe46

Browse files
committed
feat: initial bitcoind sync client support
Adds: - Sync client configuration with RPC (default) and REST variants - Extend the ChainSource::Bitcoind configuration options - Preliminary implementation for BitcoindSyncClient in RPC mode
1 parent d840bbd commit 822fe46

File tree

9 files changed

+179
-77
lines changed

9 files changed

+179
-77
lines changed

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ lightning-net-tokio = { version = "0.1.0" }
3535
lightning-persister = { version = "0.1.0" }
3636
lightning-background-processor = { version = "0.1.0", features = ["futures"] }
3737
lightning-rapid-gossip-sync = { version = "0.1.0" }
38-
lightning-block-sync = { version = "0.1.0", features = ["rpc-client", "tokio"] }
38+
lightning-block-sync = { version = "0.1.0", features = ["rpc-client", "rest-client", "tokio"] }
3939
lightning-transaction-sync = { version = "0.1.0", features = ["esplora-async-https", "time", "electrum"] }
4040
lightning-liquidity = { version = "0.1.0", features = ["std"] }
4141

bindings/ldk_node.udl

+7-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ dictionary ElectrumSyncConfig {
3434
BackgroundSyncConfig? background_sync_config;
3535
};
3636

37+
[Enum]
38+
interface BitcoindSyncClientConfig {
39+
Rpc();
40+
Rest(string rest_host, u16 rest_port);
41+
};
42+
3743
dictionary LSPS2ServiceConfig {
3844
string? require_token;
3945
boolean advertise_service;
@@ -77,7 +83,7 @@ interface Builder {
7783
void set_entropy_bip39_mnemonic(Mnemonic mnemonic, string? passphrase);
7884
void set_chain_source_esplora(string server_url, EsploraSyncConfig? config);
7985
void set_chain_source_electrum(string server_url, ElectrumSyncConfig? config);
80-
void set_chain_source_bitcoind_rpc(string rpc_host, u16 rpc_port, string rpc_user, string rpc_password);
86+
void set_chain_source_bitcoind(string rpc_host, u16 rpc_port, string rpc_user, string rpc_password, BitcoindSyncClientConfig? sync_client_config);
8187
void set_gossip_source_p2p();
8288
void set_gossip_source_rgs(string rgs_server_url);
8389
void set_liquidity_source_lsps1(PublicKey node_id, SocketAddress address, string? token);

src/builder.rs

+59-26
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77

88
use crate::chain::{ChainSource, DEFAULT_ESPLORA_SERVER_URL};
99
use crate::config::{
10-
default_user_config, may_announce_channel, AnnounceError, Config, ElectrumSyncConfig,
11-
EsploraSyncConfig, DEFAULT_LOG_FILENAME, DEFAULT_LOG_LEVEL, WALLET_KEYS_SEED_LEN,
10+
default_user_config, may_announce_channel, AnnounceError, BitcoindSyncClientConfig, Config,
11+
ElectrumSyncConfig, EsploraSyncConfig, DEFAULT_LOG_FILENAME, DEFAULT_LOG_LEVEL,
12+
WALLET_KEYS_SEED_LEN,
1213
};
1314

1415
use crate::connection::ConnectionManager;
@@ -82,9 +83,21 @@ const LSPS_HARDENED_CHILD_INDEX: u32 = 577;
8283

8384
#[derive(Debug, Clone)]
8485
enum ChainDataSourceConfig {
85-
Esplora { server_url: String, sync_config: Option<EsploraSyncConfig> },
86-
Electrum { server_url: String, sync_config: Option<ElectrumSyncConfig> },
87-
BitcoindRpc { rpc_host: String, rpc_port: u16, rpc_user: String, rpc_password: String },
86+
Esplora {
87+
server_url: String,
88+
sync_config: Option<EsploraSyncConfig>,
89+
},
90+
Electrum {
91+
server_url: String,
92+
sync_config: Option<ElectrumSyncConfig>,
93+
},
94+
Bitcoind {
95+
rpc_host: String,
96+
rpc_port: u16,
97+
rpc_user: String,
98+
rpc_password: String,
99+
sync_client_config: BitcoindSyncClientConfig,
100+
},
88101
}
89102

90103
#[derive(Debug, Clone)]
@@ -297,13 +310,26 @@ impl NodeBuilder {
297310
self
298311
}
299312

300-
/// Configures the [`Node`] instance to source its chain data from the given Bitcoin Core RPC
313+
/// Configures the [`Node`] instance to synchronize its chain data from the given Bitcoin Core RPC
301314
/// endpoint.
302-
pub fn set_chain_source_bitcoind_rpc(
315+
///
316+
/// This method configures an RPC connection for essential operations, with options for
317+
/// synchronization via either RPC (default) or REST.
318+
///
319+
/// # Parameters:
320+
/// * `rpc_host`, `rpc_port`, `rpc_user`, `rpc_password` - Required parameters for the Bitcoin Core RPC connection
321+
/// * `sync_client_config` - Optional synchronization client configuration; defaults to using RPC for sync
322+
pub fn set_chain_source_bitcoind(
303323
&mut self, rpc_host: String, rpc_port: u16, rpc_user: String, rpc_password: String,
324+
sync_client_config: Option<BitcoindSyncClientConfig>,
304325
) -> &mut Self {
305-
self.chain_data_source_config =
306-
Some(ChainDataSourceConfig::BitcoindRpc { rpc_host, rpc_port, rpc_user, rpc_password });
326+
self.chain_data_source_config = Some(ChainDataSourceConfig::Bitcoind {
327+
rpc_host,
328+
rpc_port,
329+
rpc_user,
330+
rpc_password,
331+
sync_client_config: sync_client_config.unwrap_or(BitcoindSyncClientConfig::Rpc),
332+
});
307333
self
308334
}
309335

@@ -716,14 +742,16 @@ impl ArcedNodeBuilder {
716742

717743
/// Configures the [`Node`] instance to source its chain data from the given Bitcoin Core RPC
718744
/// endpoint.
719-
pub fn set_chain_source_bitcoind_rpc(
745+
pub fn set_chain_source_bitcoind(
720746
&self, rpc_host: String, rpc_port: u16, rpc_user: String, rpc_password: String,
747+
sync_client_config: Option<BitcoindSyncClientConfig>,
721748
) {
722-
self.inner.write().unwrap().set_chain_source_bitcoind_rpc(
749+
self.inner.write().unwrap().set_chain_source_bitcoind(
723750
rpc_host,
724751
rpc_port,
725752
rpc_user,
726753
rpc_password,
754+
sync_client_config,
727755
);
728756
}
729757

@@ -1061,21 +1089,26 @@ fn build_with_store_internal(
10611089
Arc::clone(&node_metrics),
10621090
))
10631091
},
1064-
Some(ChainDataSourceConfig::BitcoindRpc { rpc_host, rpc_port, rpc_user, rpc_password }) => {
1065-
Arc::new(ChainSource::new_bitcoind_rpc(
1066-
rpc_host.clone(),
1067-
*rpc_port,
1068-
rpc_user.clone(),
1069-
rpc_password.clone(),
1070-
Arc::clone(&wallet),
1071-
Arc::clone(&fee_estimator),
1072-
Arc::clone(&tx_broadcaster),
1073-
Arc::clone(&kv_store),
1074-
Arc::clone(&config),
1075-
Arc::clone(&logger),
1076-
Arc::clone(&node_metrics),
1077-
))
1078-
},
1092+
Some(ChainDataSourceConfig::Bitcoind {
1093+
rpc_host,
1094+
rpc_port,
1095+
rpc_user,
1096+
rpc_password,
1097+
sync_client_config,
1098+
}) => Arc::new(ChainSource::new_bitcoind(
1099+
rpc_host.clone(),
1100+
*rpc_port,
1101+
rpc_user.clone(),
1102+
rpc_password.clone(),
1103+
Arc::clone(&wallet),
1104+
Arc::clone(&fee_estimator),
1105+
Arc::clone(&tx_broadcaster),
1106+
Arc::clone(&kv_store),
1107+
Arc::clone(&config),
1108+
sync_client_config.clone(),
1109+
Arc::clone(&logger),
1110+
Arc::clone(&node_metrics),
1111+
)),
10791112
None => {
10801113
// Default to Esplora client.
10811114
let server_url = DEFAULT_ESPLORA_SERVER_URL.to_string();

src/chain/bitcoind_rpc.rs

+8-21
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@ use lightning_block_sync::http::HttpEndpoint;
1313
use lightning_block_sync::http::JsonResponse;
1414
use lightning_block_sync::poll::ValidatedBlockHeader;
1515
use lightning_block_sync::rpc::{RpcClient, RpcError};
16-
use lightning_block_sync::{
17-
AsyncBlockSourceResult, BlockData, BlockHeaderData, BlockSource, Cache,
18-
};
16+
use lightning_block_sync::Cache;
1917

2018
use serde::Serialize;
2119

@@ -36,9 +34,8 @@ pub struct BitcoindRpcClient {
3634

3735
impl BitcoindRpcClient {
3836
pub(crate) fn new(host: String, port: u16, rpc_user: String, rpc_password: String) -> Self {
39-
let http_endpoint = HttpEndpoint::for_host(host.clone()).with_port(port);
40-
let rpc_credentials =
41-
BASE64_STANDARD.encode(format!("{}:{}", rpc_user.clone(), rpc_password.clone()));
37+
let http_endpoint = endpoint(host, port);
38+
let rpc_credentials = rpc_credentials(rpc_user, rpc_password);
4239

4340
let rpc_client = Arc::new(RpcClient::new(&rpc_credentials, http_endpoint));
4441

@@ -254,22 +251,12 @@ impl BitcoindRpcClient {
254251
}
255252
}
256253

257-
impl BlockSource for BitcoindRpcClient {
258-
fn get_header<'a>(
259-
&'a self, header_hash: &'a BlockHash, height_hint: Option<u32>,
260-
) -> AsyncBlockSourceResult<'a, BlockHeaderData> {
261-
Box::pin(async move { self.rpc_client.get_header(header_hash, height_hint).await })
262-
}
263-
264-
fn get_block<'a>(
265-
&'a self, header_hash: &'a BlockHash,
266-
) -> AsyncBlockSourceResult<'a, BlockData> {
267-
Box::pin(async move { self.rpc_client.get_block(header_hash).await })
268-
}
254+
pub(crate) fn rpc_credentials(rpc_user: String, rpc_password: String) -> String {
255+
BASE64_STANDARD.encode(format!("{}:{}", rpc_user, rpc_password))
256+
}
269257

270-
fn get_best_block(&self) -> AsyncBlockSourceResult<(BlockHash, Option<u32>)> {
271-
Box::pin(async move { self.rpc_client.get_best_block().await })
272-
}
258+
pub(crate) fn endpoint(host: String, port: u16) -> HttpEndpoint {
259+
HttpEndpoint::for_host(host.clone()).with_port(port)
273260
}
274261

275262
pub(crate) struct FeeResponse(pub FeeRate);

0 commit comments

Comments
 (0)