Skip to content

Commit 92d703b

Browse files
authored
Merge pull request #1164 from randomlogin/cbf-prep-electrum-fee-fn
Move Electrum fee rate estimation into a free function
2 parents 6c2f077 + bb06058 commit 92d703b

1 file changed

Lines changed: 81 additions & 84 deletions

File tree

‎src/chain/electrum.rs‎

Lines changed: 81 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,6 @@ impl ElectrumChainSource {
9999
self.server_url.clone(),
100100
self.sync_config.clone(),
101101
Arc::clone(&runtime),
102-
Arc::clone(&self.config),
103102
Arc::clone(&self.logger),
104103
)
105104
}
@@ -311,7 +310,14 @@ impl ElectrumChainSource {
311310

312311
let now = Instant::now();
313312

314-
let new_fee_rate_cache = electrum_client.get_fee_rate_cache_update().await?;
313+
let new_fee_rate_cache = get_electrum_fee_rate_cache_update(
314+
Arc::clone(&electrum_client.runtime),
315+
Arc::clone(&electrum_client.electrum_client),
316+
self.config.network,
317+
self.sync_config.timeouts_config.fee_rate_cache_update_timeout_secs,
318+
Arc::clone(&self.logger),
319+
)
320+
.await?;
315321
self.fee_estimator.set_fee_rate_cache(new_fee_rate_cache);
316322

317323
log_debug!(
@@ -438,15 +444,15 @@ impl ElectrumRuntimeStatus {
438444

439445
pub(super) fn start(
440446
&mut self, server_url: String, sync_config: ElectrumSyncConfig, runtime: Arc<Runtime>,
441-
config: Arc<Config>, logger: Arc<Logger>,
447+
logger: Arc<Logger>,
442448
) -> Result<(), Error> {
443449
if self.client.is_some() {
444450
debug_assert!(false, "We shouldn't call start if we're already started");
445451
return Ok(());
446452
}
447453

448454
let client =
449-
Arc::new(ElectrumRuntimeClient::new(server_url, sync_config, runtime, config, logger)?);
455+
Arc::new(ElectrumRuntimeClient::new(server_url, sync_config, runtime, logger)?);
450456

451457
// (Re-)apply all known `Filter` entries to the fresh client.
452458
for (txid, script_pubkey) in self.registered_txs.iter() {
@@ -495,15 +501,14 @@ struct ElectrumRuntimeClient {
495501
bdk_electrum_client: Arc<BdkElectrumClient<Arc<ElectrumClient>>>,
496502
tx_sync: Arc<ElectrumSyncClient<Arc<Logger>>>,
497503
runtime: Arc<Runtime>,
498-
config: Arc<Config>,
499504
logger: Arc<Logger>,
500505
confirm_gate: Arc<ConfirmGate>,
501506
}
502507

503508
impl ElectrumRuntimeClient {
504509
fn new(
505510
server_url: String, sync_config: ElectrumSyncConfig, runtime: Arc<Runtime>,
506-
config: Arc<Config>, logger: Arc<Logger>,
511+
logger: Arc<Logger>,
507512
) -> Result<Self, Error> {
508513
let electrum_config = ElectrumConfigBuilder::new()
509514
.retry(ELECTRUM_CLIENT_NUM_RETRIES)
@@ -532,7 +537,6 @@ impl ElectrumRuntimeClient {
532537
bdk_electrum_client,
533538
tx_sync,
534539
runtime,
535-
config,
536540
logger,
537541
confirm_gate: Arc::new(ConfirmGate::new()),
538542
})
@@ -753,91 +757,84 @@ impl ElectrumRuntimeClient {
753757
Err(e) => self.log_broadcast_error(e, &txids, &package),
754758
}
755759
}
760+
}
756761

757-
async fn get_fee_rate_cache_update(
758-
&self,
759-
) -> Result<HashMap<ConfirmationTarget, FeeRate>, Error> {
760-
let electrum_client = Arc::clone(&self.electrum_client);
761-
762-
let mut batch = Batch::default();
763-
let confirmation_targets = get_all_conf_targets();
764-
for target in confirmation_targets {
765-
let num_blocks = get_num_block_defaults_for_target(target);
766-
batch.estimate_fee(num_blocks, None);
767-
}
768-
769-
let spawn_fut = self.runtime.spawn_blocking(move || electrum_client.batch_call(&batch));
762+
pub(crate) async fn get_electrum_fee_rate_cache_update(
763+
runtime: Arc<Runtime>, electrum_client: Arc<ElectrumClient>, network: Network,
764+
fee_rate_cache_update_timeout_secs: u64, logger: Arc<Logger>,
765+
) -> Result<HashMap<ConfirmationTarget, FeeRate>, Error> {
766+
let mut batch = Batch::default();
767+
let confirmation_targets = get_all_conf_targets();
768+
for target in confirmation_targets {
769+
let num_blocks = get_num_block_defaults_for_target(target);
770+
batch.estimate_fee(num_blocks, None);
771+
}
770772

771-
let timeout_fut = tokio::time::timeout(
772-
Duration::from_secs(
773-
self.sync_config.timeouts_config.fee_rate_cache_update_timeout_secs,
774-
),
775-
spawn_fut,
773+
let spawn_fut = runtime.spawn_blocking(move || electrum_client.batch_call(&batch));
774+
775+
let timeout_fut =
776+
tokio::time::timeout(Duration::from_secs(fee_rate_cache_update_timeout_secs), spawn_fut);
777+
778+
let raw_estimates_btc_kvb = timeout_fut
779+
.await
780+
.map_err(|e| {
781+
log_error!(logger, "Updating fee rate estimates timed out: {}", e);
782+
Error::FeerateEstimationUpdateTimeout
783+
})?
784+
.map_err(|e| {
785+
log_error!(logger, "Failed to retrieve fee rate estimates: {}", e);
786+
Error::FeerateEstimationUpdateFailed
787+
})?
788+
.map_err(|e| {
789+
log_error!(logger, "Failed to retrieve fee rate estimates: {}", e);
790+
Error::FeerateEstimationUpdateFailed
791+
})?;
792+
793+
if raw_estimates_btc_kvb.len() != confirmation_targets.len() && network == Network::Bitcoin {
794+
// Ensure we fail if we didn't receive all estimates.
795+
debug_assert!(
796+
false,
797+
"Electrum server didn't return all expected results. This is disallowed on Mainnet."
776798
);
777-
778-
let raw_estimates_btc_kvb = timeout_fut
779-
.await
780-
.map_err(|e| {
781-
log_error!(self.logger, "Updating fee rate estimates timed out: {}", e);
782-
Error::FeerateEstimationUpdateTimeout
783-
})?
784-
.map_err(|e| {
785-
log_error!(self.logger, "Failed to retrieve fee rate estimates: {}", e);
786-
Error::FeerateEstimationUpdateFailed
787-
})?
788-
.map_err(|e| {
789-
log_error!(self.logger, "Failed to retrieve fee rate estimates: {}", e);
790-
Error::FeerateEstimationUpdateFailed
791-
})?;
792-
793-
if raw_estimates_btc_kvb.len() != confirmation_targets.len()
794-
&& self.config.network == Network::Bitcoin
795-
{
796-
// Ensure we fail if we didn't receive all estimates.
797-
debug_assert!(false,
798-
"Electrum server didn't return all expected results. This is disallowed on Mainnet."
799-
);
800-
log_error!(self.logger,
799+
log_error!(logger,
801800
"Failed to retrieve fee rate estimates: Electrum server didn't return all expected results. This is disallowed on Mainnet."
802801
);
803-
return Err(Error::FeerateEstimationUpdateFailed);
804-
}
802+
return Err(Error::FeerateEstimationUpdateFailed);
803+
}
805804

806-
let mut new_fee_rate_cache = HashMap::with_capacity(10);
807-
for (target, raw_fee_rate_btc_per_kvb) in
808-
confirmation_targets.into_iter().zip(raw_estimates_btc_kvb.into_iter())
809-
{
810-
// Parse the retrieved serde_json::Value and fall back to 1 sat/vb (10^3 / 10^8 = 10^-5
811-
// = 0.00001 btc/kvb) if we fail or it yields less than that. This is mostly necessary
812-
// to continue on `signet`/`regtest` where we might not get estimates (or bogus
813-
// values).
814-
let fee_rate_btc_per_kvb = raw_fee_rate_btc_per_kvb
815-
.as_f64()
816-
.map_or(0.00001, |converted| converted.max(0.00001));
817-
818-
// Electrum, just like Bitcoin Core, gives us a feerate in BTC/KvB.
819-
// Thus, we multiply by 25_000_000 (10^8 / 4) to get satoshis/kwu.
820-
let fee_rate = {
821-
let fee_rate_sat_per_kwu = (fee_rate_btc_per_kvb * 25_000_000.0).round() as u64;
822-
FeeRate::from_sat_per_kwu(fee_rate_sat_per_kwu)
823-
};
824-
825-
// LDK 0.0.118 introduced changes to the `ConfirmationTarget` semantics that
826-
// require some post-estimation adjustments to the fee rates, which we do here.
827-
let adjusted_fee_rate = apply_post_estimation_adjustments(target, fee_rate);
828-
829-
new_fee_rate_cache.insert(target, adjusted_fee_rate);
830-
831-
log_trace!(
832-
self.logger,
833-
"Fee rate estimation updated for {:?}: {} sats/kwu",
834-
target,
835-
adjusted_fee_rate.to_sat_per_kwu(),
836-
);
837-
}
805+
let mut new_fee_rate_cache = HashMap::with_capacity(10);
806+
for (target, raw_fee_rate_btc_per_kvb) in
807+
confirmation_targets.into_iter().zip(raw_estimates_btc_kvb.into_iter())
808+
{
809+
// Parse the retrieved serde_json::Value and fall back to 1 sat/vb (10^3 / 10^8 = 10^-5
810+
// = 0.00001 btc/kvb) if we fail or it yields less than that. This is mostly necessary
811+
// to continue on `signet`/`regtest` where we might not get estimates (or bogus
812+
// values).
813+
let fee_rate_btc_per_kvb =
814+
raw_fee_rate_btc_per_kvb.as_f64().map_or(0.00001, |converted| converted.max(0.00001));
815+
816+
// Electrum, just like Bitcoin Core, gives us a feerate in BTC/KvB.
817+
// Thus, we multiply by 25_000_000 (10^8 / 4) to get satoshis/kwu.
818+
let fee_rate = {
819+
let fee_rate_sat_per_kwu = (fee_rate_btc_per_kvb * 25_000_000.0).round() as u64;
820+
FeeRate::from_sat_per_kwu(fee_rate_sat_per_kwu)
821+
};
822+
823+
// LDK 0.0.118 introduced changes to the `ConfirmationTarget` semantics that
824+
// require some post-estimation adjustments to the fee rates, which we do here.
825+
let adjusted_fee_rate = apply_post_estimation_adjustments(target, fee_rate);
838826

839-
Ok(new_fee_rate_cache)
827+
new_fee_rate_cache.insert(target, adjusted_fee_rate);
828+
829+
log_trace!(
830+
logger,
831+
"Fee rate estimation updated for {:?}: {} sats/kwu",
832+
target,
833+
adjusted_fee_rate.to_sat_per_kwu(),
834+
);
840835
}
836+
837+
Ok(new_fee_rate_cache)
841838
}
842839

843840
struct ConfirmGate {

0 commit comments

Comments
 (0)