Skip to content

Commit 7bb147f

Browse files
committed
Switch from reqwest to bitreq
`reqwest` is one of the largest contributors of code size and dependencies (including single-author dependencies) to much of the rust-bitcoin ecosystem, including ldk-node. Thus, Tobin took the time to (ask an LLM to) fork `minreq` and add async support to it, including async `rustls` support. As its now a functional HTTP(s) client, its time for the ecosystem to start switching over. Luckily, its ~trivial to do.
1 parent 1fbc4ed commit 7bb147f

File tree

4 files changed

+38
-48
lines changed

4 files changed

+38
-48
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ bdk_esplora = { version = "0.22.0", default-features = false, features = ["async
5656
bdk_electrum = { version = "0.23.0", default-features = false, features = ["use-rustls-ring"]}
5757
bdk_wallet = { version = "2.2.0", default-features = false, features = ["std", "keys-bip39"]}
5858

59-
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
59+
bitreq = { version = "0.3", default-features = false, features = ["async-https"] }
6060
rustls = { version = "0.23", default-features = false }
6161
rusqlite = { version = "0.31.0", features = ["bundled"] }
6262
bitcoin = "0.32.7"

src/config.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,20 @@ pub(crate) const FEE_RATE_CACHE_UPDATE_TIMEOUT_SECS: u64 = 5;
8787
// The timeout after which we abort a transaction broadcast operation.
8888
pub(crate) const TX_BROADCAST_TIMEOUT_SECS: u64 = 5;
8989

90+
// The maximum encoded size of an RGS snapshot we'll accept.
91+
// In practice the maximum we see is around 4MiB.
92+
pub(crate) const RGS_SNAPSHOT_MAX_SIZE: usize = 15 * 1024 * 1024;
93+
9094
// The timeout after which we abort a RGS sync operation.
9195
pub(crate) const RGS_SYNC_TIMEOUT_SECS: u64 = 5;
9296

9397
/// The length in bytes of our wallets' keys seed.
9498
pub const WALLET_KEYS_SEED_LEN: usize = 64;
9599

100+
// The maximum encoded size of external scores we'll accept.
101+
// In practice we see scores files in the 5MiB range.
102+
pub(crate) const EXTERNAL_PATHFINDING_SCORES_MAX_SIZE: usize = 20 * 1024 * 1024;
103+
96104
// The timeout after which we abort a external scores sync operation.
97105
pub(crate) const EXTERNAL_PATHFINDING_SCORES_SYNC_TIMEOUT_SECS: u64 = 5;
98106

src/gossip.rs

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,12 @@
77

88
use std::sync::atomic::{AtomicU32, Ordering};
99
use std::sync::Arc;
10-
use std::time::Duration;
1110

1211
use lightning_block_sync::gossip::GossipVerifier;
1312

1413
use crate::chain::ChainSource;
15-
use crate::config::RGS_SYNC_TIMEOUT_SECS;
16-
use crate::logger::{log_trace, LdkLogger, Logger};
14+
use crate::config::{RGS_SNAPSHOT_MAX_SIZE, RGS_SYNC_TIMEOUT_SECS};
15+
use crate::logger::{log_error, log_trace, LdkLogger, Logger};
1716
use crate::runtime::{Runtime, RuntimeSpawner};
1817
use crate::types::{GossipSync, Graph, P2PGossipSync, RapidGossipSync};
1918
use crate::Error;
@@ -70,29 +69,18 @@ impl GossipSource {
7069
let query_timestamp = latest_sync_timestamp.load(Ordering::Acquire);
7170
let query_url = format!("{}/{}", server_url, query_timestamp);
7271

73-
let response = tokio::time::timeout(
74-
Duration::from_secs(RGS_SYNC_TIMEOUT_SECS),
75-
reqwest::get(query_url),
76-
)
77-
.await
78-
.map_err(|e| {
79-
log_trace!(logger, "Retrieving RGS gossip update timed out: {}", e);
72+
let query = bitreq::get(query_url)
73+
.with_max_body_size(Some(RGS_SNAPSHOT_MAX_SIZE))
74+
.with_timeout(RGS_SYNC_TIMEOUT_SECS);
75+
let response = query.send_async().await.map_err(|e| {
76+
log_error!(logger, "Failed to retrieve RGS gossip update: {e}");
8077
Error::GossipUpdateTimeout
81-
})?
82-
.map_err(|e| {
83-
log_trace!(logger, "Failed to retrieve RGS gossip update: {}", e);
84-
Error::GossipUpdateFailed
8578
})?;
8679

87-
match response.error_for_status() {
88-
Ok(res) => {
89-
let update_data = res.bytes().await.map_err(|e| {
90-
log_trace!(logger, "Failed to retrieve RGS gossip update: {}", e);
91-
Error::GossipUpdateFailed
92-
})?;
93-
80+
match response.status_code {
81+
200 => {
9482
let new_latest_sync_timestamp =
95-
gossip_sync.update_network_graph(&update_data).map_err(|e| {
83+
gossip_sync.update_network_graph(response.as_bytes()).map_err(|e| {
9684
log_trace!(
9785
logger,
9886
"Failed to update network graph with RGS data: {:?}",
@@ -103,8 +91,8 @@ impl GossipSource {
10391
latest_sync_timestamp.store(new_latest_sync_timestamp, Ordering::Release);
10492
Ok(new_latest_sync_timestamp)
10593
},
106-
Err(e) => {
107-
log_trace!(logger, "Failed to retrieve RGS gossip update: {}", e);
94+
code => {
95+
log_trace!(logger, "Failed to retrieve RGS gossip update: HTTP {}", code);
10896
Err(Error::GossipUpdateFailed)
10997
},
11098
}

src/scoring.rs

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
use std::sync::{Arc, Mutex, RwLock};
2-
use std::time::{Duration, SystemTime};
2+
use std::time::SystemTime;
33

44
use lightning::routing::scoring::ChannelLiquidities;
55
use lightning::util::ser::Readable;
66
use lightning::{log_error, log_info, log_trace};
77

88
use crate::config::{
9-
EXTERNAL_PATHFINDING_SCORES_SYNC_INTERVAL, EXTERNAL_PATHFINDING_SCORES_SYNC_TIMEOUT_SECS,
9+
EXTERNAL_PATHFINDING_SCORES_MAX_SIZE, EXTERNAL_PATHFINDING_SCORES_SYNC_INTERVAL,
10+
EXTERNAL_PATHFINDING_SCORES_SYNC_TIMEOUT_SECS,
1011
};
1112
use crate::io::utils::write_external_pathfinding_scores_to_cache;
1213
use crate::logger::LdkLogger;
@@ -53,34 +54,27 @@ async fn sync_external_scores(
5354
logger: &Logger, scorer: &Mutex<Scorer>, node_metrics: &RwLock<NodeMetrics>,
5455
kv_store: Arc<DynStore>, url: &String,
5556
) -> () {
56-
let response = tokio::time::timeout(
57-
Duration::from_secs(EXTERNAL_PATHFINDING_SCORES_SYNC_TIMEOUT_SECS),
58-
reqwest::get(url),
59-
)
60-
.await;
57+
let request = bitreq::get(url)
58+
.with_timeout(EXTERNAL_PATHFINDING_SCORES_SYNC_TIMEOUT_SECS)
59+
.with_max_body_size(Some(EXTERNAL_PATHFINDING_SCORES_MAX_SIZE));
6160

62-
let response = match response {
63-
Ok(resp) => resp,
64-
Err(e) => {
65-
log_error!(logger, "Retrieving external scores timed out: {}", e);
66-
return;
67-
},
68-
};
69-
let response = match response {
61+
let response = match request.send_async().await {
7062
Ok(resp) => resp,
7163
Err(e) => {
7264
log_error!(logger, "Failed to retrieve external scores update: {}", e);
7365
return;
7466
},
7567
};
76-
let reader = match response.bytes().await {
77-
Ok(bytes) => bytes,
78-
Err(e) => {
79-
log_error!(logger, "Failed to read external scores update: {}", e);
80-
return;
81-
},
82-
};
83-
match ChannelLiquidities::read(&mut &*reader) {
68+
if response.status_code != 200 {
69+
log_error!(
70+
logger,
71+
"Failed to retrieve external scores update: HTTP {}",
72+
response.status_code
73+
);
74+
return;
75+
}
76+
let mut reader = response.as_bytes();
77+
match ChannelLiquidities::read(&mut reader) {
8478
Ok(liquidities) => {
8579
if let Err(e) =
8680
write_external_pathfinding_scores_to_cache(&*kv_store, &liquidities, logger).await

0 commit comments

Comments
 (0)