From 7cab89e191f9de303cb43f366ef236b8c2459965 Mon Sep 17 00:00:00 2001 From: maan2003 Date: Fri, 29 Mar 2024 03:19:05 +0530 Subject: [PATCH 01/18] feat: backoff in retry helper I really like 0.2, 0.2, 0.4, 0.6, 1.0, 1.6, ... We should export some statergy in fedimint-core but naming is hard. --- Cargo.lock | 13 ++++ fedimint-core/Cargo.toml | 1 + fedimint-core/src/config.rs | 10 ++- fedimint-core/src/util/mod.rs | 74 ++++++++++++------- gateway/ln-gateway/tests/integration_tests.rs | 14 ++-- 5 files changed, 76 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 132b5a13dd3..712ae5b94e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -382,6 +382,18 @@ dependencies = [ "syn 2.0.52", ] +[[package]] +name = "backon" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c491fa80d69c03084223a4e73c378dd9f9a1e612eb54051213f88b2d5249b458" +dependencies = [ + "fastrand", + "futures-core", + "pin-project", + "tokio", +] + [[package]] name = "backtrace" version = "0.3.69" @@ -1419,6 +1431,7 @@ dependencies = [ "async-lock", "async-recursion", "async-trait", + "backon", "backtrace", "bech32", "bincode", diff --git a/fedimint-core/Cargo.toml b/fedimint-core/Cargo.toml index 1152ba06636..33cf68eefa7 100644 --- a/fedimint-core/Cargo.toml +++ b/fedimint-core/Cargo.toml @@ -53,6 +53,7 @@ macro_rules_attribute = "0.2.0" bitvec = "1.0.1" parity-scale-codec = { version = "3.6.9", features = ["derive"] } imbl = "2.0.3" +backon = "=0.4.3" # don't upgrade unless really needed [target.'cfg(not(target_family = "wasm"))'.dependencies] jsonrpsee-ws-client = { version = "0.22.2", features = ["webpki-tls"], default-features = false } diff --git a/fedimint-core/src/config.rs b/fedimint-core/src/config.rs index 25928dd3ae5..f392a232514 100644 --- a/fedimint-core/src/config.rs +++ b/fedimint-core/src/config.rs @@ -238,11 +238,15 @@ impl ClientConfig { ) -> anyhow::Result { debug!("Downloading client config from {:?}", invite_code); - fedimint_core::util::retry( + crate::util::retry( "Downloading client config", + // 0.2, 0.2, 0.4, 0.6, 1.0, 1.6, ... + // sum = 21.2 + fedimint_core::util::FibonacciBackoff::default() + .with_min_delay(Duration::from_millis(200)) + .with_max_delay(Duration::from_secs(5)) + .with_max_times(10), || Self::try_download_client_config(invite_code), - Duration::from_millis(500), - 10, ) .await .context("Failed to download client config") diff --git a/fedimint-core/src/util/mod.rs b/fedimint-core/src/util/mod.rs index f99a1a8f628..02f2c49e961 100644 --- a/fedimint-core/src/util/mod.rs +++ b/fedimint-core/src/util/mod.rs @@ -9,7 +9,6 @@ use std::io::Write; use std::path::Path; use std::pin::Pin; use std::str::FromStr; -use std::time::Duration; use std::{fs, io}; use anyhow::format_err; @@ -309,6 +308,11 @@ pub fn handle_version_hash_command(version_hash: &str) { } } +pub use backon::{ + BackoffBuilder, ConstantBuilder as ConstantBackoff, ExponentialBuilder as ExponentialBackoff, + FibonacciBuilder as FibonacciBackoff, +}; + /// Run the supplied closure `op_fn` up to `max_attempts` times. Wait for the /// supplied `Duration` `interval` between attempts /// @@ -319,42 +323,42 @@ pub fn handle_version_hash_command(version_hash: &str) { /// error of the closure is returned pub async fn retry( op_name: impl Into, + statergy: impl backon::BackoffBuilder, op_fn: F, - interval: Duration, - max_attempts: u32, ) -> Result where F: Fn() -> Fut, Fut: Future>, { + let mut statergy = statergy.build(); let op_name = op_name.into(); - assert_ne!(max_attempts, 0, "max_attempts must be greater than 0"); let mut attempts = 0; loop { attempts += 1; match op_fn().await { Ok(result) => return Ok(result), - Err(error) if attempts < max_attempts => { - // run closure op_fn again - debug!( - target: LOG_CORE, - %error, - %attempts, - interval = interval.as_secs(), - "{} failed, retrying", - op_name, - ); - task::sleep(interval).await; - } Err(error) => { - warn!( - target: LOG_CORE, - %error, - %attempts, - "{} failed", - op_name, - ); - return Err(error); + if let Some(interval) = statergy.next() { + // run closure op_fn again + debug!( + target: LOG_CORE, + %error, + %attempts, + interval = interval.as_secs(), + "{} failed, retrying", + op_name, + ); + task::sleep(interval).await; + } else { + warn!( + target: LOG_CORE, + %error, + %attempts, + "{} failed", + op_name, + ); + return Err(error); + } } } } @@ -369,9 +373,8 @@ mod tests { use fedimint_core::task::Elapsed; use futures::FutureExt; - use super::retry; + use super::*; use crate::task::timeout; - use crate::util::{NextOrPending, SafeUrl}; #[test] fn test_safe_url() { @@ -442,7 +445,14 @@ mod tests { Ok(42) }; - let _ = retry("Run once".to_string(), closure, Duration::ZERO, 3).await; + let _ = retry( + "Run once", + ConstantBackoff::default() + .with_delay(Duration::ZERO) + .with_max_times(3), + closure, + ) + .await; assert_eq!(counter.load(Ordering::SeqCst), 1); } @@ -456,7 +466,15 @@ mod tests { Err::<(), anyhow::Error>(anyhow!("42")) }; - let _ = retry("Run 3 times".to_string(), closure, Duration::ZERO, 3).await; + let _ = retry( + "Run 3 once", + ConstantBackoff::default() + .with_delay(Duration::ZERO) + // retry two error + .with_max_times(2), + closure, + ) + .await; assert_eq!(counter.load(Ordering::SeqCst), 3); } diff --git a/gateway/ln-gateway/tests/integration_tests.rs b/gateway/ln-gateway/tests/integration_tests.rs index cbfd1463031..21c47d0445e 100644 --- a/gateway/ln-gateway/tests/integration_tests.rs +++ b/gateway/ln-gateway/tests/integration_tests.rs @@ -14,7 +14,7 @@ use fedimint_client::ClientHandleArc; use fedimint_core::config::FederationId; use fedimint_core::core::{IntoDynInstance, OperationId}; use fedimint_core::task::sleep_in_test; -use fedimint_core::util::{retry, NextOrPending}; +use fedimint_core::util::{retry, FibonacciBackoff, NextOrPending}; use fedimint_core::{msats, sats, Amount, OutPoint, TransactionId}; use fedimint_dummy_client::{DummyClientInit, DummyClientModule}; use fedimint_dummy_common::config::DummyGenParams; @@ -1156,12 +1156,14 @@ async fn test_gateway_configuration() -> anyhow::Result<()> { let rpc_client = rpc_client.with_password(Some(new_password.clone())); let gw_info = retry( "Get info after restart".to_string(), + FibonacciBackoff::default() + .with_min_delay(Duration::from_millis(200)) + .with_max_delay(Duration::from_secs(3)) + .with_max_times(20), || async { let info = rpc_client.get_info().await?; Ok(info) }, - Duration::from_secs(1), - 30, ) .await?; @@ -1465,6 +1467,10 @@ async fn test_gateway_executes_swaps_between_connected_federations() -> anyhow:: // its balances on both federations. let post_balances = retry( "Gateway balance after swap".to_string(), + FibonacciBackoff::default() + .with_min_delay(Duration::from_millis(200)) + .with_max_delay(Duration::from_secs(3)) + .with_max_times(10), || async { let post_balances = get_balances(&rpc, &[id1, id2]).await; if post_balances[0] == pre_balances[0] || post_balances[1] == pre_balances[1] { @@ -1472,8 +1478,6 @@ async fn test_gateway_executes_swaps_between_connected_federations() -> anyhow:: }; Ok(post_balances) }, - Duration::from_secs(1), - 15, ) .await?; assert_eq!( From 1d8afa43c71d8012ffac8ee7f4b96fc5b58d1873 Mon Sep 17 00:00:00 2001 From: maan2003 Date: Sun, 31 Mar 2024 18:42:05 +0530 Subject: [PATCH 02/18] feat: add Waiter helper in fedimint-core --- fedimint-core/src/task.rs | 2 + fedimint-core/src/task/waiter.rs | 112 +++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 fedimint-core/src/task/waiter.rs diff --git a/fedimint-core/src/task.rs b/fedimint-core/src/task.rs index b545fc919f1..71cacb32099 100644 --- a/fedimint-core/src/task.rs +++ b/fedimint-core/src/task.rs @@ -1,5 +1,7 @@ #![cfg_attr(target_family = "wasm", allow(dead_code))] +pub mod waiter; + use std::collections::VecDeque; use std::future::Future; use std::pin::{pin, Pin}; diff --git a/fedimint-core/src/task/waiter.rs b/fedimint-core/src/task/waiter.rs new file mode 100644 index 00000000000..45293b0946d --- /dev/null +++ b/fedimint-core/src/task/waiter.rs @@ -0,0 +1,112 @@ +//! Wait for a task to finish. + +use tokio::sync::Semaphore; + +/// Helper to wait for actions to be [`Self::done`] +#[derive(Debug)] +pub struct Waiter { + done_semaphore: Semaphore, +} + +impl Default for Waiter { + fn default() -> Self { + Self::new() + } +} + +impl Waiter { + pub fn new() -> Self { + Self { + // semaphore never has permits. + done_semaphore: Semaphore::new(0), + } + } + + /// Mark this waiter as done. + /// + /// NOTE: Calling this twice is ignored. + pub fn done(&self) { + // close the semaphore and notify all waiters. + self.done_semaphore.close(); + } + + /// Wait for [`Self::done`] call. + pub async fn wait(&self) { + // wait for semaphore to be closed. + self.done_semaphore + .acquire() + .await + .expect_err("done semaphore is only closed, never has permits"); + } + + /// Check if Waiter was marked as done. + pub fn is_done(&self) -> bool { + self.done_semaphore.is_closed() + } +} + +#[cfg(test)] +mod tests { + use std::time::Duration; + + use super::*; + + #[tokio::test] + async fn test_simple() { + let waiter = Waiter::new(); + assert!(!waiter.is_done()); + waiter.done(); + assert!(waiter.is_done()); + } + + #[tokio::test] + async fn test_async() { + let waiter = Waiter::new(); + assert!(!waiter.is_done()); + tokio::join!( + async { + waiter.done(); + }, + async { + waiter.wait().await; + } + ); + assert!(waiter.is_done()); + waiter.wait().await; + assert!(waiter.is_done()); + } + #[tokio::test] + async fn test_async_multi() { + let waiter = Waiter::new(); + assert!(!waiter.is_done()); + tokio::join!( + async { + waiter.done(); + }, + async { + waiter.done(); + }, + async { + waiter.done(); + }, + ); + assert!(waiter.is_done()); + waiter.wait().await; + assert!(waiter.is_done()); + } + #[tokio::test] + async fn test_async_sleep() { + let waiter = Waiter::new(); + assert!(!waiter.is_done()); + tokio::join!( + async { + fedimint_core::task::sleep(Duration::from_millis(10)).await; + waiter.done(); + }, + waiter.wait(), + ); + assert!(waiter.is_done()); + waiter.wait().await; + assert!(waiter.is_done()); + } +} From 5c07b5bff3f6af5d5848f3aa90cba8d293bf3dde Mon Sep 17 00:00:00 2001 From: maan2003 Date: Fri, 29 Mar 2024 14:47:37 +0530 Subject: [PATCH 03/18] feat: update ln gateway cache in background --- modules/fedimint-ln-client/src/lib.rs | 42 ++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/modules/fedimint-ln-client/src/lib.rs b/modules/fedimint-ln-client/src/lib.rs index 51b26dc346e..776400d818b 100644 --- a/modules/fedimint-ln-client/src/lib.rs +++ b/modules/fedimint-ln-client/src/lib.rs @@ -36,8 +36,9 @@ use fedimint_core::encoding::{Decodable, Encodable}; use fedimint_core::module::{ ApiVersion, CommonModuleInit, ModuleCommon, ModuleInit, MultiApiVersion, TransactionItemAmount, }; -use fedimint_core::task::{timeout, MaybeSend, MaybeSync}; +use fedimint_core::task::{self, timeout, MaybeSend, MaybeSync}; use fedimint_core::time::now; +use fedimint_core::util::{retry, FibonacciBackoff}; use fedimint_core::{ apply, async_trait_maybe_send, push_db_pair_items, Amount, OutPoint, TransactionId, }; @@ -896,6 +897,8 @@ impl LightningClientModule { /// Updates the gateway cache by fetching the latest registered gateways /// from the federation. + /// + /// See also [`Self::update_gateway_cache_continuously`]. pub async fn update_gateway_cache(&self, apply_meta: bool) -> anyhow::Result<()> { let gateways = self.fetch_registered_gateways(apply_meta).await?; let mut dbtx = self.client_ctx.module_db().begin_transaction().await; @@ -916,6 +919,43 @@ impl LightningClientModule { Ok(()) } + /// Continuously update the gateway cache whenever a gateway expires. + /// + /// Client integrators are expected to call this function in a spawned task. + pub async fn update_gateway_cache_continuously(&self, apply_meta: bool) -> ! { + let mut first_time = true; + + const ABOUT_TO_EXPIRE: Duration = Duration::from_secs(30); + const EMPTY_GATEWAY_SLEEP: Duration = Duration::from_secs(10 * 60); + loop { + let gateways = self.list_gateways().await; + // TODO: filter gateways by vetted + let sleep_time = gateways + .into_iter() + .map(|x| x.ttl.saturating_sub(ABOUT_TO_EXPIRE)) + .min() + .unwrap_or(if first_time { + // retry immediately first time + Duration::ZERO + } else { + EMPTY_GATEWAY_SLEEP + }); + task::sleep(sleep_time).await; + + // should never fail with usize::MAX attempts. + let _ = retry( + "update_gateway_cache", + FibonacciBackoff::default() + .with_min_delay(Duration::from_secs(1)) + .with_max_delay(Duration::from_secs(10 * 60)) + .with_max_times(usize::MAX), + || self.update_gateway_cache(apply_meta), + ) + .await; + first_time = false; + } + } + /// Returns all gateways that are currently in the gateway cache. pub async fn list_gateways(&self) -> Vec { let mut dbtx = self.client_ctx.module_db().begin_transaction_nc().await; From b69d00a3233e0161bcb6527ddedcf2a118a5776f Mon Sep 17 00:00:00 2001 From: maan2003 Date: Sun, 31 Mar 2024 21:39:49 +0530 Subject: [PATCH 04/18] chore: remove meta fetching from ln client The integrations should use `MetaManager` to checked vetted gateways manually. --- fedimint-cli/src/client.rs | 2 +- gateway/ln-gateway/tests/integration_tests.rs | 8 +- modules/fedimint-ln-client/src/db.rs | 24 +-- modules/fedimint-ln-client/src/lib.rs | 198 +----------------- modules/fedimint-ln-tests/tests/tests.rs | 28 +-- 5 files changed, 19 insertions(+), 241 deletions(-) diff --git a/fedimint-cli/src/client.rs b/fedimint-cli/src/client.rs index 5a4742c760d..a9bc48738b7 100644 --- a/fedimint-cli/src/client.rs +++ b/fedimint-cli/src/client.rs @@ -429,7 +429,7 @@ pub async fn handle_command( } ClientCmd::UpdateGatewayCache => { let lightning_module = client.get_first_module::(); - lightning_module.update_gateway_cache(true).await?; + lightning_module.update_gateway_cache().await?; let gateways = lightning_module.list_gateways().await; if gateways.is_empty() { return Ok(serde_json::to_value(Vec::::new()).unwrap()); diff --git a/gateway/ln-gateway/tests/integration_tests.rs b/gateway/ln-gateway/tests/integration_tests.rs index 21c47d0445e..01cfce9472f 100644 --- a/gateway/ln-gateway/tests/integration_tests.rs +++ b/gateway/ln-gateway/tests/integration_tests.rs @@ -267,7 +267,7 @@ async fn test_can_change_routing_fees() -> anyhow::Result<()> { // Update the gateway cache since the fees have changed let ln_module = user_client.get_first_module::(); - ln_module.update_gateway_cache(true).await?; + ln_module.update_gateway_cache().await?; // Create test invoice let invoice_amount = sats(250); @@ -805,7 +805,7 @@ async fn test_gateway_register_with_federation() -> anyhow::Result<()> { proportional_millionths: 0, }; let lightning_module = user_client.get_first_module::(); - lightning_module.update_gateway_cache(true).await?; + lightning_module.update_gateway_cache().await?; let gateways = lightning_module.list_gateways().await; assert!(!gateways.is_empty()); assert!(gateways @@ -824,14 +824,14 @@ async fn test_gateway_register_with_federation() -> anyhow::Result<()> { }) .await; - lightning_module.update_gateway_cache(true).await?; + lightning_module.update_gateway_cache().await?; let gateways = lightning_module.list_gateways().await; assert!(gateways.is_empty()); // Reconnect the federation and verify that the gateway has registered. gateway_test.connect_fed(&fed).await; - lightning_module.update_gateway_cache(true).await?; + lightning_module.update_gateway_cache().await?; let gateways = lightning_module.list_gateways().await; assert!(!gateways.is_empty()); assert!(gateways diff --git a/modules/fedimint-ln-client/src/db.rs b/modules/fedimint-ln-client/src/db.rs index 571f228a004..8e55de31488 100644 --- a/modules/fedimint-ln-client/src/db.rs +++ b/modules/fedimint-ln-client/src/db.rs @@ -1,5 +1,3 @@ -use std::time::SystemTime; - use bitcoin_hashes::sha256; use fedimint_client::sm::DynState; use fedimint_core::core::{IntoDynInstance, ModuleInstanceId, OperationId}; @@ -25,7 +23,7 @@ pub enum DbKeyPrefix { // Deprecated ActiveGateway = 0x28, PaymentResult = 0x29, - MetaOverrides = 0x30, + MetaOverridesDeprecated = 0x30, LightningGateway = 0x45, } @@ -73,26 +71,6 @@ impl_db_record!( impl_db_lookup!(key = PaymentResultKey, query_prefix = PaymentResultPrefix); -#[derive(Debug, Encodable, Decodable, Serialize)] -pub struct MetaOverridesKey; - -#[derive(Debug, Encodable, Decodable, Serialize)] -pub struct MetaOverridesPrefix; - -#[derive(Debug, Encodable, Decodable, Serialize)] -pub struct MetaOverrides { - pub value: String, - pub fetched_at: SystemTime, -} - -impl_db_record!( - key = MetaOverridesKey, - value = MetaOverrides, - db_prefix = DbKeyPrefix::MetaOverrides, -); - -impl_db_lookup!(key = MetaOverridesKey, query_prefix = MetaOverridesPrefix); - #[derive(Debug, Encodable, Decodable, Serialize)] pub struct LightningGatewayKey(pub PublicKey); diff --git a/modules/fedimint-ln-client/src/lib.rs b/modules/fedimint-ln-client/src/lib.rs index 776400d818b..538b7dee058 100644 --- a/modules/fedimint-ln-client/src/lib.rs +++ b/modules/fedimint-ln-client/src/lib.rs @@ -29,7 +29,7 @@ use fedimint_client::sm::{DynState, ModuleNotifier, State, StateTransition}; use fedimint_client::transaction::{ClientInput, ClientOutput, TransactionBuilder}; use fedimint_client::{sm_enum_variant_translation, DynGlobalClientContext}; use fedimint_core::api::DynModuleApi; -use fedimint_core::config::{FederationId, META_OVERRIDE_URL_KEY, META_VETTED_GATEWAYS_KEY}; +use fedimint_core::config::FederationId; use fedimint_core::core::{IntoDynInstance, ModuleInstanceId, OperationId}; use fedimint_core::db::{DatabaseTransaction, DatabaseVersion, IDatabaseTransactionOpsCoreTyped}; use fedimint_core::encoding::{Decodable, Encodable}; @@ -37,7 +37,6 @@ use fedimint_core::module::{ ApiVersion, CommonModuleInit, ModuleCommon, ModuleInit, MultiApiVersion, TransactionItemAmount, }; use fedimint_core::task::{self, timeout, MaybeSend, MaybeSync}; -use fedimint_core::time::now; use fedimint_core::util::{retry, FibonacciBackoff}; use fedimint_core::{ apply, async_trait_maybe_send, push_db_pair_items, Amount, OutPoint, TransactionId, @@ -67,9 +66,9 @@ use secp256k1_zkp::{All, Secp256k1}; use serde::{Deserialize, Serialize}; use strum::IntoEnumIterator; use thiserror::Error; -use tracing::{debug, error}; +use tracing::error; -use crate::db::{MetaOverrides, MetaOverridesKey, MetaOverridesPrefix, PaymentResultPrefix}; +use crate::db::PaymentResultPrefix; use crate::incoming::{ FundingOfferState, IncomingSmCommon, IncomingSmStates, IncomingStateMachine, }; @@ -86,8 +85,6 @@ use crate::receive::{ /// client can get refund const OUTGOING_LN_CONTRACT_TIMELOCK: u64 = 500; -const META_OVERRIDE_CACHE_DURATION: Duration = Duration::from_secs(10 * 60); - // 24 hours. Many wallets default to 1 hour, but it's a bad user experience if // invoices expire too quickly const DEFAULT_INVOICE_EXPIRY_TIME: Duration = Duration::from_secs(60 * 60 * 24); @@ -290,15 +287,8 @@ impl ModuleInit for LightningClientInit { "Payment Result" ); } - DbKeyPrefix::MetaOverrides => { - push_db_pair_items!( - dbtx, - MetaOverridesPrefix, - MetaOverridesKey, - MetaOverrides, - ln_client_items, - "Meta Overrides" - ); + DbKeyPrefix::MetaOverridesDeprecated => { + // Deprecated } DbKeyPrefix::LightningGateway => { push_db_pair_items!( @@ -458,7 +448,7 @@ impl LightningClientModule { // Only initialize the gateway cache if it is empty let gateways = ln_module.list_gateways().await; if gateways.is_empty() { - ln_module.update_gateway_cache(false).await?; + ln_module.update_gateway_cache().await?; } Ok(ln_module) @@ -899,8 +889,8 @@ impl LightningClientModule { /// from the federation. /// /// See also [`Self::update_gateway_cache_continuously`]. - pub async fn update_gateway_cache(&self, apply_meta: bool) -> anyhow::Result<()> { - let gateways = self.fetch_registered_gateways(apply_meta).await?; + pub async fn update_gateway_cache(&self) -> anyhow::Result<()> { + let gateways = self.module_api.fetch_gateways().await?; let mut dbtx = self.client_ctx.module_db().begin_transaction().await; // Remove all previous gateway entries @@ -922,7 +912,7 @@ impl LightningClientModule { /// Continuously update the gateway cache whenever a gateway expires. /// /// Client integrators are expected to call this function in a spawned task. - pub async fn update_gateway_cache_continuously(&self, apply_meta: bool) -> ! { + pub async fn update_gateway_cache_continuously(&self) -> ! { let mut first_time = true; const ABOUT_TO_EXPIRE: Duration = Duration::from_secs(30); @@ -949,7 +939,7 @@ impl LightningClientModule { .with_min_delay(Duration::from_secs(1)) .with_max_delay(Duration::from_secs(10 * 60)) .with_max_times(usize::MAX), - || self.update_gateway_cache(apply_meta), + || self.update_gateway_cache(), ) .await; first_time = false; @@ -966,174 +956,6 @@ impl LightningClientModule { .await } - /// Fetches the metadata overrides for a given federation - /// - /// # Arguments - /// - /// * `federation_id` - A `FederationId` for which we want to fetch meta - /// overrides. - /// * `override_src` - A configured `URL` from which meta overrides are - /// requested. - /// - /// Valid meta overrides fetched from this source are cached in the client - /// database for up to `META_OVERRIDE_CACHE_DURATION` - async fn fetch_meta_overrides( - &self, - federation_id: FederationId, - override_src: String, - ) -> anyhow::Result> { - debug!("Fetching meta overrides from {override_src}"); - - if let Some(cache) = self - .client_ctx - .module_db() - .begin_transaction() - .await - .get_value(&MetaOverridesKey {}) - .await - { - let elapsed = now().duration_since(cache.fetched_at).unwrap_or_default(); - if elapsed < META_OVERRIDE_CACHE_DURATION { - debug!("Using cached meta overrides"); - match serde_json::from_str(&cache.value) { - Ok(meta) => return Ok(meta), - Err(e) => { - error!("Error parsing cached meta overrides: {}", e); - debug!("Meta override cache returned invalid json: {}", cache.value); - } - } - } - debug!("Cached meta overrides are stale"); - }; - - let response = reqwest::Client::new() - .get(override_src.as_str()) - .send() - .await - .context("Meta override request failed")?; - debug!("Meta override source returned status: {response:?}"); - - let meta_value = match response.status() { - reqwest::StatusCode::OK => { - let txt = response.text().await.context(format!( - "Meta override source returned invalid body: {override_src}" - ))?; - let m: serde_json::Value = serde_json::from_str(&txt).map_err(|_| { - anyhow::anyhow!("Meta override source returned invalid json: {txt}") - })?; - if !m.is_object() { - return Err(anyhow::anyhow!("Meta override is not valid")); - } - - match m.get(&federation_id.to_string()) { - Some(meta_value) => { - debug!("Found meta overrides for federation: {federation_id}"); - meta_value.clone() - } - None => { - debug!("No meta overrides found for federation: {federation_id}"); - return Ok(BTreeMap::new()); - } - } - } - _ => Err(anyhow::anyhow!( - "Meta override source returned error code: {}", - response.status() - ))?, - }; - - let federation_meta: BTreeMap = serde_json::from_value(meta_value.clone()) - .context(format!( - "Meta override source returned invalid json: {meta_value}" - ))?; - - let mut dbtx = self.client_ctx.module_db().begin_transaction().await; - dbtx.insert_entry( - &MetaOverridesKey {}, - &MetaOverrides { - value: meta_value.to_string(), - fetched_at: fedimint_core::time::now(), - }, - ) - .await; - dbtx.commit_tx().await; - - Ok(federation_meta) - } - - /// Fetches gateways registered with the fed and applies gateway vetting - /// from 'vetted_gateways` meta field if configured - async fn fetch_registered_gateways( - &self, - apply_meta: bool, - ) -> anyhow::Result> { - let mut gateways = self.module_api.fetch_gateways().await?; - - if apply_meta && !gateways.is_empty() { - let config = self.client_ctx.get_config().clone(); - let global_meta: BTreeMap = config.global.meta.clone(); - let federation_id = config.global.calculate_federation_id(); - - let meta = match config.meta::(META_OVERRIDE_URL_KEY)? { - Some(override_src) => { - match self.fetch_meta_overrides(federation_id, override_src).await { - Ok(override_meta) => { - if override_meta.contains_key(META_VETTED_GATEWAYS_KEY) { - override_meta - } else { - global_meta - } - } - Err(e) => { - error!("Error fetching meta overrides: {}", e); - global_meta - } - } - } - None => { - debug!("No meta override source configured"); - global_meta - } - }; - - if meta.is_empty() { - debug!("No meta overrides found"); - return Ok(gateways); - } - - debug!("Applying vetted meta field to registered gateways"); - let vetted = meta.get(META_VETTED_GATEWAYS_KEY).and_then(|vetted| { - debug!("Found vetted gateways meta field: {vetted:?}"); - match serde_json::from_str::>(vetted) { - Ok(vetted) => Some(vetted), - Err(e) => { - error!("Error parsing vetted gateways meta field: {}", e); - None - } - } - }); - match vetted { - Some(vetted) => { - debug!("Found the following vetted gateways: {:?}", vetted); - let vetted_gids = vetted - .into_iter() - .map(|pk| PublicKey::from_str(&pk).map_err(anyhow::Error::from)) - .collect::, _>>()?; - - debug!("Vetted gateways: {:?}", vetted_gids); - for gateway in gateways.iter_mut() { - gateway.vetted = vetted_gids.contains(&gateway.info.gateway_id); - } - } - None => { - debug!("No vetted gateways meta field found"); - } - }; - } - - Ok(gateways) - } - /// Pays a LN invoice with our available funds using the supplied `gateway` /// if one was provided and the invoice is not an internal one. If none is /// supplied only internal payments are possible. diff --git a/modules/fedimint-ln-tests/tests/tests.rs b/modules/fedimint-ln-tests/tests/tests.rs index 2fba4459747..4e16036905a 100644 --- a/modules/fedimint-ln-tests/tests/tests.rs +++ b/modules/fedimint-ln-tests/tests/tests.rs @@ -676,10 +676,7 @@ mod fedimint_migration_tests { use fedimint_core::module::DynServerModuleInit; use fedimint_core::util::SafeUrl; use fedimint_core::{Amount, OutPoint, PeerId, TransactionId}; - use fedimint_ln_client::db::{ - MetaOverrides, MetaOverridesKey, MetaOverridesPrefix, PaymentResult, PaymentResultKey, - PaymentResultPrefix, - }; + use fedimint_ln_client::db::{PaymentResult, PaymentResultKey, PaymentResultPrefix}; use fedimint_ln_client::receive::{ LightningReceiveStateMachine, LightningReceiveStates, LightningReceiveSubmittedOffer, LightningReceiveSubmittedOfferV0, @@ -924,15 +921,6 @@ mod fedimint_migration_tests { ) .await; - dbtx.insert_new_entry( - &MetaOverridesKey, - &MetaOverrides { - value: "META OVERRIDE".to_string(), - fetched_at: fedimint_core::time::now(), - }, - ) - .await; - dbtx.commit_tx().await; } @@ -1185,18 +1173,8 @@ mod fedimint_migration_tests { ); info!("Validated PaymentResults"); } - fedimint_ln_client::db::DbKeyPrefix::MetaOverrides => { - let meta_overrides = dbtx - .find_by_prefix(&MetaOverridesPrefix) - .await - .collect::>() - .await; - let num_meta_overrides = meta_overrides.len(); - ensure!( - num_meta_overrides > 0, - "validate_migrations was not able to read any MetaOverrides" - ); - info!("Validated MetaOverrides"); + fedimint_ln_client::db::DbKeyPrefix::MetaOverridesDeprecated => { + // MetaOverrides is never read anywhere } fedimint_ln_client::db::DbKeyPrefix::LightningGateway => { let gateways = dbtx From c01b4713091512e6fb34e81f48d9693393e7ce27 Mon Sep 17 00:00:00 2001 From: maan2003 Date: Fri, 29 Mar 2024 18:26:35 +0530 Subject: [PATCH 05/18] feat: meta service implement meta caching and updating left for follow-up: - implement meta source for the meta module --- Cargo.lock | 79 +++++++++- fedimint-client/Cargo.toml | 1 + fedimint-client/src/db.rs | 35 +++++ fedimint-client/src/lib.rs | 32 ++++ fedimint-client/src/meta.rs | 286 ++++++++++++++++++++++++++++++++++++ 5 files changed, 425 insertions(+), 8 deletions(-) create mode 100644 fedimint-client/src/meta.rs diff --git a/Cargo.lock b/Cargo.lock index 712ae5b94e3..4df245354e8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1208,7 +1208,7 @@ checksum = "d3e11244e7fd8b0beee0a3c62137c4bd9f756fe2c492ccf93171f81467b59200" dependencies = [ "bitcoin 0.29.2", "log", - "reqwest", + "reqwest 0.11.26", "serde", ] @@ -1363,7 +1363,7 @@ dependencies = [ "lightning-invoice", "lnurl-rs", "rand", - "reqwest", + "reqwest 0.11.26", "serde", "serde_json", "thiserror", @@ -1392,6 +1392,7 @@ dependencies = [ "futures", "itertools 0.12.1", "rand", + "reqwest 0.12.2", "ring 0.17.8", "secp256k1-zkp", "serde", @@ -1693,7 +1694,7 @@ dependencies = [ "fedimint-core", "fedimint-ln-gateway", "fedimint-logging", - "reqwest", + "reqwest 0.11.26", "serde", "serde_json", "tokio", @@ -1728,7 +1729,7 @@ dependencies = [ "itertools 0.12.1", "lightning-invoice", "rand", - "reqwest", + "reqwest 0.11.26", "secp256k1 0.24.3", "secp256k1-zkp", "serde", @@ -1813,7 +1814,7 @@ dependencies = [ "lightning-invoice", "prost", "rand", - "reqwest", + "reqwest 0.11.26", "secp256k1 0.24.3", "secp256k1-zkp", "serde", @@ -2335,7 +2336,7 @@ dependencies = [ "hex", "http-body 0.4.6", "hyper 0.14.28", - "hyper-rustls", + "hyper-rustls 0.24.2", "prost", "rustls 0.21.10", "rustls-pemfile 1.0.4", @@ -3161,6 +3162,23 @@ dependencies = [ "tokio-rustls 0.24.1", ] +[[package]] +name = "hyper-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" +dependencies = [ + "futures-util", + "http 1.1.0", + "hyper 1.2.0", + "hyper-util", + "rustls 0.22.2", + "rustls-pki-types", + "tokio", + "tokio-rustls 0.25.0", + "tower-service", +] + [[package]] name = "hyper-timeout" version = "0.4.1" @@ -3180,6 +3198,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" dependencies = [ "bytes", + "futures-channel", "futures-util", "http 1.1.0", "http-body 1.0.0", @@ -3187,6 +3206,9 @@ dependencies = [ "pin-project-lite", "socket2", "tokio", + "tower", + "tower-service", + "tracing", ] [[package]] @@ -3640,7 +3662,7 @@ dependencies = [ "bitcoin 0.30.2", "cbc", "email_address", - "reqwest", + "reqwest 0.11.26", "serde", "serde_json", "url", @@ -4379,7 +4401,7 @@ dependencies = [ "http 0.2.12", "http-body 0.4.6", "hyper 0.14.28", - "hyper-rustls", + "hyper-rustls 0.24.2", "ipnet", "js-sys", "log", @@ -4406,6 +4428,47 @@ dependencies = [ "winreg", ] +[[package]] +name = "reqwest" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d66674f2b6fb864665eea7a3c1ac4e3dfacd2fda83cf6f935a612e01b0e3338" +dependencies = [ + "base64 0.21.7", + "bytes", + "futures-core", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "hyper 1.2.0", + "hyper-rustls 0.26.0", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls 0.22.2", + "rustls-pemfile 1.0.4", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-rustls 0.25.0", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots 0.26.1", + "winreg", +] + [[package]] name = "ring" version = "0.16.20" diff --git a/fedimint-client/Cargo.toml b/fedimint-client/Cargo.toml index 83f74d48d8a..4fbc37c6a00 100644 --- a/fedimint-client/Cargo.toml +++ b/fedimint-client/Cargo.toml @@ -42,6 +42,7 @@ thiserror = "1.0.58" tokio = { version = "1.36.0", features = [ "time", "macros" ] } tokio-stream = { version = "0.1.14", features = [ "time", "sync" ] } tracing = "0.1.40" +reqwest = { version = "0.12.2", features = ["json", "rustls-tls"], default-features = false } [target.'cfg(target_family = "wasm")'.dependencies] ring = { version = "0.17.8", features = ["wasm32_unknown_unknown_js"] } diff --git a/fedimint-client/src/db.rs b/fedimint-client/src/db.rs index 3a56a8c0b4b..b0020daff9d 100644 --- a/fedimint-client/src/db.rs +++ b/fedimint-client/src/db.rs @@ -1,4 +1,5 @@ use std::collections::BTreeMap; +use std::time::SystemTime; use fedimint_core::api::ApiVersionSet; use fedimint_core::config::{ClientConfig, FederationId}; @@ -39,6 +40,8 @@ pub enum DbKeyPrefix { ClientInitState = 0x31, ClientMetadata = 0x32, ClientLastBackup = 0x33, + ClientMetaField = 0x34, + ClientMetaServiceInfo = 0x35, /// Arbitrary data of the applications integrating Fedimint client and /// wanting to store some Federation-specific data in Fedimint client /// database. @@ -296,6 +299,38 @@ impl_db_record!( db_prefix = DbKeyPrefix::ClientLastBackup ); +#[derive(Encodable, Decodable, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] +pub struct MetaFieldKey(pub String); + +#[derive(Encodable, Decodable, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] +pub struct MetaFieldPrefix; + +#[derive(Encodable, Decodable, Debug, Clone)] +pub struct MetaFieldValue(pub String); + +#[derive(Encodable, Decodable, Debug)] +pub struct MetaServiceInfoKey; + +#[derive(Encodable, Decodable, Debug)] +pub struct MetaServiceInfo { + pub last_updated: SystemTime, + pub revision: u64, +} + +impl_db_record!( + key = MetaFieldKey, + value = MetaFieldValue, + db_prefix = DbKeyPrefix::ClientMetaField +); + +impl_db_record!( + key = MetaServiceInfoKey, + value = MetaServiceInfo, + db_prefix = DbKeyPrefix::ClientMetaServiceInfo +); + +impl_db_lookup!(key = MetaFieldKey, query_prefix = MetaFieldPrefix); + /// `ClientMigrationFn` is a function that modules can implement to "migrate" /// the database to the next database version. pub type ClientMigrationFn = diff --git a/fedimint-client/src/lib.rs b/fedimint-client/src/lib.rs index 8acb4996c8f..cbc2c4ebe13 100644 --- a/fedimint-client/src/lib.rs +++ b/fedimint-client/src/lib.rs @@ -112,6 +112,7 @@ pub use fedimint_derive_secret as derivable_secret; use fedimint_derive_secret::DerivableSecret; use fedimint_logging::{LOG_CLIENT, LOG_CLIENT_RECOVERY}; use futures::{Future, Stream, StreamExt}; +use meta::{LegacyMetaSource, MetaService}; use module::recovery::RecoveryProgress; use module::{DynClientModule, FinalClient}; use rand::thread_rng; @@ -160,6 +161,9 @@ pub mod sm; /// Structs and interfaces to construct Fedimint transactions pub mod transaction; +/// Management of meta fields +pub mod meta; + pub type InstancelessDynClientInput = ClientInput< Box, Box, @@ -732,6 +736,7 @@ pub struct Client { root_secret: DerivableSecret, operation_log: OperationLog, secp_ctx: Secp256k1, + meta_service: Arc, task_group: TaskGroup, @@ -965,6 +970,11 @@ impl Client { &self.operation_log } + /// Get the meta manager to read meta fields. + pub fn meta_service(&self) -> &Arc { + &self.meta_service + } + /// Adds funding to a transaction or removes over-funding via change. async fn finalize_transaction( &self, @@ -1739,17 +1749,20 @@ pub struct ClientBuilder { primary_module_instance: Option, admin_creds: Option, db: Database, + meta_service: Arc, stopped: bool, } impl ClientBuilder { fn new(db: Database) -> Self { + let meta_service = MetaService::new(LegacyMetaSource::default()); ClientBuilder { module_inits: Default::default(), primary_module_instance: Default::default(), admin_creds: None, db, stopped: false, + meta_service, } } @@ -1760,8 +1773,11 @@ impl ClientBuilder { admin_creds: None, db: client.db.clone(), stopped: false, + // non unique + meta_service: client.meta_service.clone(), } } + /// Replace module generator registry entirely pub fn with_module_inits(&mut self, module_inits: ClientModuleInitRegistry) { self.module_inits = module_inits; @@ -1792,6 +1808,10 @@ impl ClientBuilder { ) } + pub fn with_meta_service(&mut self, meta_service: Arc) { + self.meta_service = meta_service; + } + async fn migrate_database( &self, db: &Database, @@ -2282,7 +2302,19 @@ impl ClientBuilder { task_group, operation_log: OperationLog::new(db), client_recovery_progress_receiver, + meta_service: self.meta_service, }); + client_inner + .task_group + .spawn_cancellable("MetaService::update_continuously", { + let client_inner = client_inner.clone(); + async move { + client_inner + .meta_service + .update_continuously(&client_inner) + .await + } + }); let client_arc = ClientHandle::new(client_inner); diff --git a/fedimint-client/src/meta.rs b/fedimint-client/src/meta.rs new file mode 100644 index 00000000000..16f2173e175 --- /dev/null +++ b/fedimint-client/src/meta.rs @@ -0,0 +1,286 @@ +use std::collections::BTreeMap; +use std::sync::Arc; +use std::time::{Duration, SystemTime}; + +use anyhow::{bail, Context as _}; +use fedimint_core::db::{Database, DatabaseTransaction, IDatabaseTransactionOpsCoreTyped}; +use fedimint_core::task::waiter::Waiter; +use fedimint_core::task::{MaybeSend, MaybeSync}; +use fedimint_core::util::{retry, FibonacciBackoff}; +use fedimint_core::{apply, async_trait_maybe_send}; +use serde::de::DeserializeOwned; +use tracing::{debug, instrument, warn}; + +use crate::db::{ + MetaFieldKey, MetaFieldPrefix, MetaFieldValue, MetaServiceInfo, MetaServiceInfoKey, +}; +use crate::Client; + +#[apply(async_trait_maybe_send!)] +pub trait MetaSource: MaybeSend + MaybeSync + 'static { + /// Wait for next change in this source. + async fn wait_for_update(&self); + async fn fetch( + &self, + client: &Client, + fetch_kind: FetchKind, + last_revision: Option, + ) -> anyhow::Result; +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum FetchKind { + /// Meta source should return fast, retry less. + /// This blocks getting any meta values. + Initial, + /// Meta source can retry infinitely. + Background, +} + +#[derive(Debug, Clone)] +pub struct MetaValues { + values: BTreeMap, + revision: u64, +} + +#[derive(Debug, Clone, Copy)] +pub struct MetaValue { + pub fetch_time: SystemTime, + pub value: Option, +} + +/// Service for managing the caching of meta fields. +// a fancy DST to save one allocation. +pub struct MetaService { + initial_fetch_waiter: Waiter, + source: S, +} + +impl MetaService { + pub fn new(source: S) -> Arc + where + S: Sized, + { + // implicit cast `Arc>` to `Arc>` + Arc::new(MetaService { + initial_fetch_waiter: Waiter::new(), + source, + }) + } + + /// Get the value for the meta field. + /// + /// This may wait for significant time on first run. + pub async fn get_field( + &self, + db: &Database, + field: &str, + ) -> Option> { + if let Some(value) = self.get_field_from_db(db, field).await { + // might be from in old cache. + // TODO: maybe old cache should have a ttl? + Some(value) + } else { + // wait for initial value + self.initial_fetch_waiter.wait().await; + self.get_field_from_db(db, field).await + } + } + + async fn get_field_from_db( + &self, + db: &Database, + field: &str, + ) -> Option> { + let dbtx = &mut db.begin_transaction_nc().await; + let info = dbtx.get_value(&MetaServiceInfoKey).await?; + let value = dbtx + .get_value(&MetaFieldKey(field.to_string())) + .await + .and_then(|value| parse_meta_value_static::(&value.0).ok()); + Some(MetaValue { + fetch_time: info.last_updated, + value, + }) + } + + async fn current_revision(&self, dbtx: &mut DatabaseTransaction<'_>) -> Option { + dbtx.get_value(&MetaServiceInfoKey) + .await + .map(|x| x.revision) + } + + /// Update all source in background. + /// + /// Caller should run this method in a task. + pub(crate) async fn update_continuously(&self, client: &Client) -> ! { + let mut current_revision = self + .current_revision(&mut client.db().begin_transaction_nc().await) + .await; + let meta_values = self + .source + .fetch(client, FetchKind::Initial, current_revision) + .await; + let failed_initial = meta_values.is_err(); + match meta_values { + Ok(meta_values) => Self::save_meta_values(client, &meta_values).await, + Err(error) => warn!(%error, "failed to fetch source"), + }; + self.initial_fetch_waiter.done(); + + // don't wait if we failed first item + if !failed_initial { + self.source.wait_for_update().await; + } + + // now keep updating slowly + loop { + if let Ok(meta_values) = self + .source + .fetch(client, FetchKind::Background, current_revision) + .await + { + current_revision = Some(meta_values.revision); + Self::save_meta_values(client, &meta_values).await; + } + self.source.wait_for_update().await; + } + } + + async fn save_meta_values(client: &Client, meta_values: &MetaValues) { + let mut dbtx = client.db().begin_transaction().await; + dbtx.remove_by_prefix(&MetaFieldPrefix).await; + dbtx.insert_entry( + &MetaServiceInfoKey, + &MetaServiceInfo { + last_updated: fedimint_core::time::now(), + revision: meta_values.revision, + }, + ) + .await; + for (key, value) in &meta_values.values { + dbtx.insert_entry(key, value).await; + } + dbtx.commit_tx().await; + } +} + +/// Legacy non-meta module config source uses client config meta and +/// meta_override_url meta field. +#[derive(Clone, Debug, Default)] +#[non_exhaustive] +pub struct LegacyMetaSource { + reqwest: reqwest::Client, +} + +#[apply(async_trait_maybe_send!)] +impl MetaSource for LegacyMetaSource { + async fn wait_for_update(&self) { + fedimint_core::task::sleep(Duration::from_secs(10 * 60)).await + } + + async fn fetch( + &self, + client: &Client, + fetch_kind: FetchKind, + last_revision: Option, + ) -> anyhow::Result { + let config_iter = client + .config() + .global + .meta + .iter() + .map(|(key, value)| (MetaFieldKey(key.to_owned()), MetaFieldValue(value.clone()))); + let backoff = match fetch_kind { + // need to be fast the first time. + FetchKind::Initial => FibonacciBackoff::default() + .with_min_delay(Duration::from_millis(300)) + .with_max_delay(Duration::from_secs(3)) + .with_max_times(10), + FetchKind::Background => FibonacciBackoff::default() + .with_min_delay(Duration::from_secs(10)) + .with_max_delay(Duration::from_secs(10 * 60)) + .with_max_times(usize::MAX), + }; + let overrides = retry("fetch_meta_overrides", backoff, || { + fetch_meta_overrides(&self.reqwest, client, "meta_override_url") + }) + .await?; + Ok(MetaValues { + values: config_iter.chain(overrides).collect(), + revision: last_revision.map_or(0, |r| r + 1), + }) + } +} + +pub async fn fetch_meta_overrides( + reqwest: &reqwest::Client, + client: &Client, + field_name: &str, +) -> anyhow::Result> { + let Some(url) = client.config().meta::(field_name)? else { + return Ok(BTreeMap::new()); + }; + let response = reqwest + .get(&url) + .send() + .await + .context("Meta override source could not be fetched")?; + + debug!("Meta override source returned status: {response:?}"); + + if response.status() != reqwest::StatusCode::OK { + bail!( + "Meta override request returned non-OK status code: {}", + response.status() + ); + } + + let mut federation_map = response + .json::>>() + .await + .context("Meta override could not be parsed as JSON")?; + + let federation_id = client.federation_id().to_string(); + let meta_fields = federation_map + .remove(&federation_id) + .with_context(|| anyhow::format_err!("No entry for federation {federation_id} in {url}"))? + .into_iter() + .filter_map(|(key, value)| match value { + serde_json::Value::String(value_str) => { + Some((MetaFieldKey(key), MetaFieldValue(value_str))) + } + _ => { + warn!("Meta override map contained non-string key: {key}, ignoring"); + None + } + }) + .collect::>(); + + Ok(meta_fields) +} + +/// Tries to parse `str_value` as JSON. In the special case that `V` is `String` +/// we return the raw `str_value` if JSON parsing fails. This necessary since +/// the spec wasn't clear enough in the beginning. +#[instrument(err)] // log on every failure +pub fn parse_meta_value_static( + str_value: &str, +) -> anyhow::Result { + let res = serde_json::from_str(str_value) + .with_context(|| format!("Decoding meta field value '{str_value}' failed")); + + // In the past we encoded some string fields as "just a string" without quotes, + // this code ensures that old meta values still parse since config is hard to + // change + if res.is_err() && std::any::TypeId::of::() == std::any::TypeId::of::() { + let string_ret = Box::new(str_value.to_owned()); + let ret: Box = unsafe { + // We can transmute a String to V because we know that V==String + std::mem::transmute(string_ret) + }; + Ok(*ret) + } else { + res + } +} From feeb96683de28eb9eee4113cf422167e9d54c941 Mon Sep 17 00:00:00 2001 From: maan2003 Date: Mon, 1 Apr 2024 12:07:39 +0530 Subject: [PATCH 06/18] feat: subscriptions for meta fields --- fedimint-client/src/meta.rs | 61 +++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/fedimint-client/src/meta.rs b/fedimint-client/src/meta.rs index 16f2173e175..17460dd5ac5 100644 --- a/fedimint-client/src/meta.rs +++ b/fedimint-client/src/meta.rs @@ -1,14 +1,18 @@ use std::collections::BTreeMap; +use std::pin::pin; use std::sync::Arc; use std::time::{Duration, SystemTime}; use anyhow::{bail, Context as _}; +use async_stream::stream; use fedimint_core::db::{Database, DatabaseTransaction, IDatabaseTransactionOpsCoreTyped}; use fedimint_core::task::waiter::Waiter; use fedimint_core::task::{MaybeSend, MaybeSync}; use fedimint_core::util::{retry, FibonacciBackoff}; use fedimint_core::{apply, async_trait_maybe_send}; use serde::de::DeserializeOwned; +use tokio::sync::Notify; +use tokio_stream::{Stream, StreamExt as _}; use tracing::{debug, instrument, warn}; use crate::db::{ @@ -53,6 +57,7 @@ pub struct MetaValue { // a fancy DST to save one allocation. pub struct MetaService { initial_fetch_waiter: Waiter, + meta_update_notify: Notify, source: S, } @@ -64,6 +69,7 @@ impl MetaService { // implicit cast `Arc>` to `Arc>` Arc::new(MetaService { initial_fetch_waiter: Waiter::new(), + meta_update_notify: Notify::new(), source, }) } @@ -110,6 +116,53 @@ impl MetaService { .map(|x| x.revision) } + /// Wait until Meta Service is initialized, after this `get_field` will not + /// block. + pub async fn wait_initialization(&self) { + self.initial_fetch_waiter.wait().await + } + + /// NOTE: this subscription never ends even after update task is shutdown. + /// You should consume this stream in a spawn_cancellable. + pub fn subscribe_to_updates(&self) -> impl Stream + '_ { + stream! { + let mut notify = pin!(self.meta_update_notify.notified()); + loop { + notify.as_mut().await; + notify.set(self.meta_update_notify.notified()); + // enable waiting for next notification before yield so don't miss + // any notifications. + notify.as_mut().enable(); + yield (); + } + } + } + + /// NOTE: this subscription never ends even after update task is shutdown. + /// You should consume this stream in a spawn_cancellable. + /// + /// Stream will yield the first element immediately without blocking. + /// The first element will be initial value of the field. + /// + /// This may yield an outdated initial value if you didn't call + /// [`Self::wait_initialization`]. + pub fn subscribe_to_field<'a, V: DeserializeOwned + 'static>( + &'a self, + db: &'a Database, + name: &'a str, + ) -> impl Stream>> + 'a { + stream! { + let mut update_stream = pin!(self.subscribe_to_updates()); + loop { + let value = self.get_field_from_db(db, name).await; + yield value; + if update_stream.next().await.is_none() { + break; + } + } + } + } + /// Update all source in background. /// /// Caller should run this method in a task. @@ -123,7 +176,7 @@ impl MetaService { .await; let failed_initial = meta_values.is_err(); match meta_values { - Ok(meta_values) => Self::save_meta_values(client, &meta_values).await, + Ok(meta_values) => self.save_meta_values(client, &meta_values).await, Err(error) => warn!(%error, "failed to fetch source"), }; self.initial_fetch_waiter.done(); @@ -141,13 +194,13 @@ impl MetaService { .await { current_revision = Some(meta_values.revision); - Self::save_meta_values(client, &meta_values).await; + self.save_meta_values(client, &meta_values).await; } self.source.wait_for_update().await; } } - async fn save_meta_values(client: &Client, meta_values: &MetaValues) { + async fn save_meta_values(&self, client: &Client, meta_values: &MetaValues) { let mut dbtx = client.db().begin_transaction().await; dbtx.remove_by_prefix(&MetaFieldPrefix).await; dbtx.insert_entry( @@ -162,6 +215,8 @@ impl MetaService { dbtx.insert_entry(key, value).await; } dbtx.commit_tx().await; + // notify everyone about changes + self.meta_update_notify.notify_waiters(); } } From c049a7e3b9b051846b7d24b815df24876379b254 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dawid=20Ci=C4=99=C5=BCarkiewicz?= Date: Sun, 17 Mar 2024 16:31:30 -0700 Subject: [PATCH 07/18] feat(core): `Jit` values --- fedimint-core/src/task.rs | 3 + fedimint-core/src/task/jit.rs | 189 ++++++++++++++++++++++++++++++++++ 2 files changed, 192 insertions(+) create mode 100644 fedimint-core/src/task/jit.rs diff --git a/fedimint-core/src/task.rs b/fedimint-core/src/task.rs index 71cacb32099..c4932083ab7 100644 --- a/fedimint-core/src/task.rs +++ b/fedimint-core/src/task.rs @@ -2,6 +2,9 @@ pub mod waiter; +/// Just-in-time initialization +pub mod jit; + use std::collections::VecDeque; use std::future::Future; use std::pin::{pin, Pin}; diff --git a/fedimint-core/src/task/jit.rs b/fedimint-core/src/task/jit.rs new file mode 100644 index 00000000000..d45b09fc7cf --- /dev/null +++ b/fedimint-core/src/task/jit.rs @@ -0,0 +1,189 @@ +use std::convert::Infallible; +use std::fmt; +use std::sync::Arc; + +use fedimint_logging::LOG_TASK; +use futures::Future; +use tokio::select; +use tokio::sync::{self, oneshot}; +use tracing::trace; + +use super::MaybeSend; + +pub type Jit = JitCore; +pub type JitTry = JitCore; +pub type JitTryAnyhow = JitCore; + +/// Error that could have been returned before +/// +/// Newtype over `Option` that allows better user (error conversion mostly) +/// experience +#[derive(Debug)] +pub struct OneTimeError(Option); + +impl std::error::Error for OneTimeError +where + E: fmt::Debug, + E: fmt::Display, +{ + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + None + } + + fn cause(&self) -> Option<&dyn std::error::Error> { + self.source() + } +} + +impl fmt::Display for OneTimeError +where + E: fmt::Display, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if let Some(e) = self.0.as_ref() { + fmt::Display::fmt(&e, f) + } else { + f.write_str("Error: (missing, it was returned before)") + } + } +} + +/// A value that initializes eagerly in parallel in a falliable way +#[derive(Debug, Clone)] +pub struct JitCore { + // on last drop it lets the inner task to know it should stop, because we don't care anymore + _cancel_tx: sync::mpsc::Sender<()>, + // since joinhandles, are not portable, we use this to wait for the value + // Note: the `std::sync::Mutex` is used intentionally, since contention never actually happens + // and we want to avoid cancelation because of it + #[allow(clippy::type_complexity)] + val_rx: + Arc>>>>, + val: sync::OnceCell, +} + +impl JitCore +where + T: MaybeSend + 'static, + E: MaybeSend + 'static, +{ + /// Create `JitTry` value, and spawn a future `f` that computes its value + /// + /// Unlike normal Rust futures, the `f` executes eagerly (is spawned as a + /// tokio task). + pub fn new_try(f: impl FnOnce() -> Fut + 'static + MaybeSend) -> Self + where + Fut: Future> + 'static + MaybeSend, + { + let (cancel_tx, mut cancel_rx) = tokio::sync::mpsc::channel(1); + let (val_tx, val_rx) = oneshot::channel(); + let type_name = std::any::type_name::(); + super::imp::spawn( + &format!("JitTry {} value", std::any::type_name::()), + async move { + select! { + _ = cancel_rx.recv() => { + trace!(target: LOG_TASK, r#type = %type_name, "JitTry value future canceled"); + }, + val = f() => { + match val_tx.send(val) { + Ok(_) => { + trace!(target: LOG_TASK, r#type = %type_name, "JitTry value ready"); + }, + Err(_) => { + trace!(target: LOG_TASK, r#type = %type_name, "JitTry value ready, but ignored"); + }, + }; + }, + } + }, + ) + .expect("spawn not fail"); + + Self { + _cancel_tx: cancel_tx, + val_rx: Arc::new(Some(val_rx).into()), + val: sync::OnceCell::new(), + } + } + + /// Get the reference to the value, potentially blocking for the + /// initialization future to complete + pub async fn get_try(&self) -> std::result::Result<&T, OneTimeError> { + #[allow(clippy::await_holding_lock)] + self.val + .get_or_try_init(|| async { + let val_res = self + .val_rx + // this lock gets locked only once so it's kind of useless other than making + // Rust happy, but the overhead doesn't matter + .try_lock() + .expect("we can't ever have contention here") + .as_mut() + .ok_or_else(|| OneTimeError(None))? + .await + .unwrap_or_else(|_| { + panic!("Jit value {} panicked", std::any::type_name::()) + }); + self.val_rx.lock().expect("locking can't fail").take(); + val_res.map_err(|e| OneTimeError(Some(e))) + }) + .await + } +} +impl JitCore +where + T: MaybeSend + 'static, +{ + pub fn new(f: impl FnOnce() -> Fut + 'static + MaybeSend) -> Self + where + Fut: Future + 'static + MaybeSend, + T: 'static, + { + Self::new_try(|| async { Ok(f().await) }) + } + + pub async fn get(&self) -> &T { + self.get_try().await.expect("can't fail") + } +} +#[cfg(test)] +mod tests { + use std::time::Duration; + + use anyhow::bail; + + use super::{Jit, JitTry, JitTryAnyhow}; + + #[test_log::test(tokio::test)] + async fn sanity_jit() { + let v = Jit::new(|| async { + fedimint_core::task::sleep(Duration::from_millis(0)).await; + 3 + }); + + assert_eq!(*v.get().await, 3); + } + + #[test_log::test(tokio::test)] + async fn sanity_jit_try_ok() { + let v = JitTryAnyhow::new_try(|| async { + fedimint_core::task::sleep(Duration::from_millis(0)).await; + Ok(3) + }); + + assert_eq!(*v.get_try().await.expect("ok"), 3); + } + + #[test_log::test(tokio::test)] + async fn sanity_jit_try_err() { + let v = JitTry::new_try(|| async { + fedimint_core::task::sleep(Duration::from_millis(0)).await; + bail!("BOOM"); + #[allow(unreachable_code)] + Ok(3) + }); + + assert!(v.get_try().await.is_err()); + } +} From f7925579b749dda5888d87ecfe31fcc846c49fe6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dawid=20Ci=C4=99=C5=BCarkiewicz?= Date: Thu, 21 Mar 2024 21:16:40 -0700 Subject: [PATCH 08/18] chore: make `JitCore.get` `Send` and fix `Clone` --- fedimint-core/src/task/jit.rs | 84 +++++++++++++++++++++++++++-------- 1 file changed, 66 insertions(+), 18 deletions(-) diff --git a/fedimint-core/src/task/jit.rs b/fedimint-core/src/task/jit.rs index d45b09fc7cf..1f8de44c504 100644 --- a/fedimint-core/src/task/jit.rs +++ b/fedimint-core/src/task/jit.rs @@ -49,7 +49,7 @@ where } /// A value that initializes eagerly in parallel in a falliable way -#[derive(Debug, Clone)] +#[derive(Debug)] pub struct JitCore { // on last drop it lets the inner task to know it should stop, because we don't care anymore _cancel_tx: sync::mpsc::Sender<()>, @@ -59,13 +59,25 @@ pub struct JitCore { #[allow(clippy::type_complexity)] val_rx: Arc>>>>, - val: sync::OnceCell, + val: Arc>, } +impl Clone for JitCore +where + T: Clone, +{ + fn clone(&self) -> Self { + Self { + _cancel_tx: self._cancel_tx.clone(), + val_rx: self.val_rx.clone(), + val: self.val.clone(), + } + } +} impl JitCore where T: MaybeSend + 'static, - E: MaybeSend + 'static, + E: MaybeSend + 'static + fmt::Display, { /// Create `JitTry` value, and spawn a future `f` that computes its value /// @@ -103,30 +115,60 @@ where Self { _cancel_tx: cancel_tx, val_rx: Arc::new(Some(val_rx).into()), - val: sync::OnceCell::new(), + val: sync::OnceCell::new().into(), } } /// Get the reference to the value, potentially blocking for the /// initialization future to complete pub async fn get_try(&self) -> std::result::Result<&T, OneTimeError> { - #[allow(clippy::await_holding_lock)] + /// Temporarily taken data out of `arc`, that will be put back on drop, + /// unless canceled + /// + /// Used to achieve cancelation safety. + struct PutBack<'a, T> { + val: Option, + arc: &'a Arc>>, + } + + impl<'a, T> PutBack<'a, T> { + fn take(arc: &'a Arc>>) -> Self { + let val = arc.lock().expect("lock failed").take(); + Self { val, arc } + } + + fn cancel(mut self) { + self.val = None; + } + + fn get_mut(&mut self) -> Option<&mut T> { + self.val.as_mut() + } + } + impl<'a, T> Drop for PutBack<'a, T> { + fn drop(&mut self) { + let mut lock = self.arc.lock().expect("lock failed"); + let take = self.val.take(); + + *lock = take; + } + } self.val .get_or_try_init(|| async { - let val_res = self - .val_rx - // this lock gets locked only once so it's kind of useless other than making - // Rust happy, but the overhead doesn't matter - .try_lock() - .expect("we can't ever have contention here") - .as_mut() - .ok_or_else(|| OneTimeError(None))? - .await - .unwrap_or_else(|_| { + let mut recv = PutBack::take(&self.val_rx); + + let val_res = { + let Some(recv) = recv.get_mut() else { + return Err(OneTimeError(None)); + }; + recv.await.unwrap_or_else(|_| { panic!("Jit value {} panicked", std::any::type_name::()) - }); - self.val_rx.lock().expect("locking can't fail").take(); - val_res.map_err(|e| OneTimeError(Some(e))) + }) + }; + + recv.cancel(); + + val_res.map_err(|err| OneTimeError(Some(err))) }) .await } @@ -163,6 +205,8 @@ mod tests { }); assert_eq!(*v.get().await, 3); + assert_eq!(*v.get().await, 3); + assert_eq!(*v.clone().get().await, 3); } #[test_log::test(tokio::test)] @@ -173,6 +217,8 @@ mod tests { }); assert_eq!(*v.get_try().await.expect("ok"), 3); + assert_eq!(*v.get_try().await.expect("ok"), 3); + assert_eq!(*v.clone().get_try().await.expect("ok"), 3); } #[test_log::test(tokio::test)] @@ -185,5 +231,7 @@ mod tests { }); assert!(v.get_try().await.is_err()); + assert!(v.get_try().await.is_err()); + assert!(v.clone().get_try().await.is_err()); } } From 78576916684beba0a693a5897462b0591b09d8bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dawid=20Ci=C4=99=C5=BCarkiewicz?= Date: Fri, 5 Apr 2024 16:09:07 -0700 Subject: [PATCH 09/18] chore: unify tokio runtime primitives in a new module --- .config/semgrep.yaml | 7 +- Cargo.lock | 1 + Cargo.toml | 1 + fedimint-bitcoind/src/bitcoincore.rs | 3 +- fedimint-bitcoind/src/electrum.rs | 3 +- fedimint-client/src/lib.rs | 2 +- fedimint-client/src/meta.rs | 2 +- fedimint-client/src/module/init/recovery.rs | 2 +- fedimint-client/src/sm/executor.rs | 7 +- fedimint-client/src/transaction/sm.rs | 2 +- fedimint-core/Cargo.toml | 1 + fedimint-core/src/api.rs | 16 +- fedimint-core/src/db/mod.rs | 9 +- fedimint-core/src/lib.rs | 3 + fedimint-core/src/net/peers/fake.rs | 3 +- fedimint-core/src/runtime.rs | 164 ++++++++++++++ fedimint-core/src/task.rs | 207 +++--------------- fedimint-core/src/task/jit.rs | 11 +- fedimint-core/src/task/waiter.rs | 2 +- fedimint-core/src/util/mod.rs | 10 +- fedimint-load-test-tool/src/main.rs | 5 +- fedimint-rocksdb/src/lib.rs | 26 +-- .../src/atomic_broadcast/spawner.rs | 4 +- fedimint-server/src/config/api.rs | 3 +- fedimint-server/src/config/distributedgen.rs | 2 +- fedimint-server/src/consensus/server.rs | 8 +- fedimint-server/src/multiplexed.rs | 2 +- fedimint-server/src/net/connect.rs | 23 +- fedimint-server/src/net/peers.rs | 2 +- fedimint-server/src/net/peers_reliable.rs | 2 +- gateway/ln-gateway/src/lib.rs | 4 +- modules/fedimint-ln-client/src/incoming.rs | 4 +- modules/fedimint-ln-client/src/lib.rs | 6 +- modules/fedimint-mint-client/src/oob.rs | 4 +- modules/fedimint-mint-tests/tests/tests.rs | 20 +- 35 files changed, 292 insertions(+), 279 deletions(-) create mode 100644 fedimint-core/src/runtime.rs diff --git a/.config/semgrep.yaml b/.config/semgrep.yaml index 48c754d4270..d0a9fcd9fef 100644 --- a/.config/semgrep.yaml +++ b/.config/semgrep.yaml @@ -61,14 +61,14 @@ rules: - id: ban-tokio-spawn languages: - rust - message: "`tokio::spawn` won't set task name by default. use `fedimint_core::task::spawn` instead" + message: "`tokio::spawn` won't set task name by default. use `fedimint_core::runtime::spawn` instead" pattern: tokio::spawn severity: WARNING - id: ban-tokio-sleep languages: - rust - message: "`tokio::time::sleep` doesn't work in WASM. Use `fedimint_core::task::sleep` instead." + message: "`tokio::time::sleep` doesn't work in WASM. Use `fedimint_core::runtime::sleep` instead." pattern: tokio::time::sleep severity: WARNING @@ -108,6 +108,7 @@ rules: - pattern-either: - pattern: sleep(...) - pattern: fedimint_core::task::sleep(...) + - pattern: fedimint_core::runtime::sleep(...) paths: include: - fedimint-testing/ @@ -120,7 +121,7 @@ rules: - gateway/ln-gateway/tests/ - fedimint-client/src/backup/tests.rs - devimint/src/tests.rs - message: "Direct use of fedimint_core::task::sleep in tests is discouraged. Use fedimint_core::task::sleep_in_test instead." + message: "Direct use of fedimint_core::runtime::sleep in tests is discouraged. Use fedimint_core::task::sleep_in_test instead." severity: WARNING - id: ban-sleep-in-test-scripts diff --git a/Cargo.lock b/Cargo.lock index 4df245354e8..0abfa60b1fa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1446,6 +1446,7 @@ dependencies = [ "fedimint-tbs", "fedimint-threshold-crypto", "futures", + "futures-util", "getrandom", "gloo-timers 0.3.0", "hex", diff --git a/Cargo.toml b/Cargo.toml index c4f7d626fdb..f408f4da5e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -76,6 +76,7 @@ tonic_lnd = { version = "0.2.0", package="fedimint-tonic-lnd", features = ["ligh cln-rpc = { package = "fedimint-cln-rpc", version = "0.4.0" } clap = { version = "4.1.6", features = ["derive", "std", "help", "usage", "error-context", "suggestions", "env"], default-features = false } serde_json = "1.0.91" +futures-util = "0.3.30" # Workaround: https://github.com/rust-lang/cargo/issues/12457 which causes # https://github.com/ipetkov/crane/issues/370 diff --git a/fedimint-bitcoind/src/bitcoincore.rs b/fedimint-bitcoind/src/bitcoincore.rs index 7f2006c8e0e..96c3b295fac 100644 --- a/fedimint-bitcoind/src/bitcoincore.rs +++ b/fedimint-bitcoind/src/bitcoincore.rs @@ -9,7 +9,8 @@ use bitcoincore_rpc::{Auth, RpcApi}; use fedimint_core::bitcoinrpc::FM_BITCOIND_COOKIE_FILE_VAR_NAME; use fedimint_core::encoding::Decodable; use fedimint_core::module::registry::ModuleDecoderRegistry; -use fedimint_core::task::{block_in_place, TaskHandle}; +use fedimint_core::runtime::block_in_place; +use fedimint_core::task::TaskHandle; use fedimint_core::txoproof::TxOutProof; use fedimint_core::util::SafeUrl; use fedimint_core::{apply, async_trait_maybe_send, Feerate}; diff --git a/fedimint-bitcoind/src/electrum.rs b/fedimint-bitcoind/src/electrum.rs index 707189d73f4..ac8ff55f40d 100644 --- a/fedimint-bitcoind/src/electrum.rs +++ b/fedimint-bitcoind/src/electrum.rs @@ -5,7 +5,8 @@ use bitcoin::{BlockHash, Network, Script, Transaction, Txid}; use bitcoin_hashes::hex::ToHex; use electrum_client::ElectrumApi; use electrum_client::Error::Protocol; -use fedimint_core::task::{block_in_place, TaskHandle}; +use fedimint_core::runtime::block_in_place; +use fedimint_core::task::TaskHandle; use fedimint_core::txoproof::TxOutProof; use fedimint_core::util::SafeUrl; use fedimint_core::{apply, async_trait_maybe_send, Feerate}; diff --git a/fedimint-client/src/lib.rs b/fedimint-client/src/lib.rs index cbc2c4ebe13..63ac9ba1fb2 100644 --- a/fedimint-client/src/lib.rs +++ b/fedimint-client/src/lib.rs @@ -1598,7 +1598,7 @@ impl Client { if self.executor.get_active_states().await.is_empty() { break; } - fedimint_core::task::sleep(Duration::from_millis(100)).await; + fedimint_core::runtime::sleep(Duration::from_millis(100)).await; } Ok(()) } diff --git a/fedimint-client/src/meta.rs b/fedimint-client/src/meta.rs index 17460dd5ac5..822e02ae53f 100644 --- a/fedimint-client/src/meta.rs +++ b/fedimint-client/src/meta.rs @@ -231,7 +231,7 @@ pub struct LegacyMetaSource { #[apply(async_trait_maybe_send!)] impl MetaSource for LegacyMetaSource { async fn wait_for_update(&self) { - fedimint_core::task::sleep(Duration::from_secs(10 * 60)).await + fedimint_core::runtime::sleep(Duration::from_secs(10 * 60)).await } async fn fetch( diff --git a/fedimint-client/src/module/init/recovery.rs b/fedimint-client/src/module/init/recovery.rs index 468716b52fc..fdb566160dc 100644 --- a/fedimint-client/src/module/init/recovery.rs +++ b/fedimint-client/src/module/init/recovery.rs @@ -286,7 +286,7 @@ where retry_sleep = retry_sleep + thread_rng().gen_range(Duration::ZERO..=retry_sleep); } - fedimint_core::task::sleep(cmp::min(retry_sleep, MAX_SLEEP)) + fedimint_core::runtime::sleep(cmp::min(retry_sleep, MAX_SLEEP)) .await; } } diff --git a/fedimint-client/src/sm/executor.rs b/fedimint-client/src/sm/executor.rs index 0c271cae6f0..5c8bacf615c 100644 --- a/fedimint-client/src/sm/executor.rs +++ b/fedimint-client/src/sm/executor.rs @@ -1175,7 +1175,8 @@ mod tests { use fedimint_core::db::Database; use fedimint_core::encoding::{Decodable, Encodable}; use fedimint_core::module::registry::ModuleDecoderRegistry; - use fedimint_core::task::{self, TaskGroup}; + use fedimint_core::runtime; + use fedimint_core::task::TaskGroup; use tokio::sync::broadcast::Sender; use tracing::{info, trace}; @@ -1350,9 +1351,9 @@ mod tests { ); // TODO build await fn+timeout or allow manual driving of executor - task::sleep(Duration::from_secs(1)).await; + runtime::sleep(Duration::from_secs(1)).await; sender.send(0).unwrap(); - task::sleep(Duration::from_secs(2)).await; + runtime::sleep(Duration::from_secs(2)).await; assert!( executor diff --git a/fedimint-client/src/transaction/sm.rs b/fedimint-client/src/transaction/sm.rs index bd32c5fa6c3..92d94caceda 100644 --- a/fedimint-client/src/transaction/sm.rs +++ b/fedimint-client/src/transaction/sm.rs @@ -4,7 +4,7 @@ use std::time::Duration; use fedimint_core::core::{Decoder, IntoDynInstance, ModuleInstanceId, OperationId}; use fedimint_core::encoding::{Decodable, Encodable}; -use fedimint_core::task::sleep; +use fedimint_core::runtime::sleep; use fedimint_core::transaction::Transaction; use fedimint_core::TransactionId; use fedimint_logging::LOG_CLIENT_NET_API; diff --git a/fedimint-core/Cargo.toml b/fedimint-core/Cargo.toml index 33cf68eefa7..923bb37e08b 100644 --- a/fedimint-core/Cargo.toml +++ b/fedimint-core/Cargo.toml @@ -19,6 +19,7 @@ async-recursion = "1.0.5" anyhow = "1.0.81" async-trait = "0.1.77" futures = "0.3.30" +futures-util = { workspace = true } backtrace = "0.3.69" bincode = "1.3.3" bech32 = "0.9.1" diff --git a/fedimint-core/src/api.rs b/fedimint-core/src/api.rs index 895bc6764a0..5d234436adf 100644 --- a/fedimint-core/src/api.rs +++ b/fedimint-core/src/api.rs @@ -23,7 +23,7 @@ use fedimint_core::endpoint_constants::{ }; use fedimint_core::fmt_utils::AbbreviateDebug; use fedimint_core::module::SerdeModuleEncoding; -use fedimint_core::task::{MaybeSend, MaybeSync, RwLock, RwLockWriteGuard}; +use fedimint_core::task::{MaybeSend, MaybeSync}; use fedimint_core::time::now; use fedimint_core::{ apply, async_trait_maybe_send, dyn_newtype_define, ModuleDecoderRegistry, NumPeersExt, @@ -40,7 +40,7 @@ use jsonrpsee_ws_client::{WsClient, WsClientBuilder}; use serde::{Deserialize, Serialize}; use serde_json::Value; use thiserror::Error; -use tokio::sync::OnceCell; +use tokio::sync::{OnceCell, RwLock, RwLockWriteGuard}; use tracing::{debug, error, instrument, trace, warn}; use crate::admin_client::{ @@ -65,8 +65,8 @@ use crate::module::{ApiAuth, ApiRequestErased, ApiVersion, SupportedApiVersionsS use crate::query::{ DiscoverApiVersionSet, QueryStep, QueryStrategy, ThresholdConsensus, UnionResponsesSingle, }; +use crate::runtime; use crate::session_outcome::{AcceptedItem, SessionOutcome, SessionStatus}; -use crate::task; use crate::transaction::{SerdeTransaction, Transaction, TransactionError}; use crate::util::SafeUrl; @@ -283,7 +283,7 @@ pub trait FederationApiExt: IRawFederationApi { }; if let Some(timeout) = timeout { - match fedimint_core::task::timeout(timeout, request).await { + match fedimint_core::runtime::timeout(timeout, request).await { Ok(result) => result, Err(_timeout) => Err(JsonRpcClientError::RequestTimeout), } @@ -318,7 +318,7 @@ pub trait FederationApiExt: IRawFederationApi { }; let result = if let Some(timeout) = timeout { - match fedimint_core::task::timeout(timeout, request).await { + match fedimint_core::runtime::timeout(timeout, request).await { Ok(result) => result, Err(_timeout) => Err(JsonRpcClientError::RequestTimeout), } @@ -371,7 +371,7 @@ pub trait FederationApiExt: IRawFederationApi { async move { // Note: we need to sleep inside the retrying future, // so that `futures` is being polled continuously - task::sleep(Duration::from_millis(delay_ms)).await; + runtime::sleep(Duration::from_millis(delay_ms)).await; PeerResponse { peer: retry_peer, result: self @@ -509,7 +509,7 @@ impl DynGlobalApi { where R: OutputOutcome, { - fedimint_core::task::timeout(timeout, async move { + fedimint_core::runtime::timeout(timeout, async move { let outcome: SerdeOutputOutcome = self .inner .request_current_consensus( @@ -1667,7 +1667,7 @@ mod tests { error!(target: LOG_NET_API, "connect"); let id = CONNECTION_COUNT.fetch_add(1, Ordering::SeqCst); // slow down - task::sleep(Duration::from_millis(100)).await; + runtime::sleep(Duration::from_millis(100)).await; if FAIL.lock().unwrap().contains(&id) { Err(jsonrpsee_core::client::Error::Transport(anyhow!( "intentional error" diff --git a/fedimint-core/src/db/mod.rs b/fedimint-core/src/db/mod.rs index a943d78db1a..ff9ba1a9b10 100644 --- a/fedimint-core/src/db/mod.rs +++ b/fedimint-core/src/db/mod.rs @@ -480,7 +480,7 @@ impl Database { delay_ms = %delay, "Database commit failed in an autocommit block - retrying" ); - crate::task::sleep(Duration::from_millis(delay)).await; + crate::runtime::sleep(Duration::from_millis(delay)).await; } } } @@ -2019,7 +2019,7 @@ mod test_utils { use crate::module::registry::ModuleDecoderRegistry; pub async fn future_returns_shortly(fut: F) -> Option { - crate::task::timeout(Duration::from_millis(10), fut) + crate::runtime::timeout(Duration::from_millis(10), fut) .await .ok() } @@ -2798,7 +2798,7 @@ mod tests { use super::mem_impl::MemDatabase; use super::*; - use crate::task::spawn; + use crate::runtime::spawn; async fn waiter(db: &Database, key: TestKey) -> tokio::task::JoinHandle { let db = db.clone(); @@ -2807,8 +2807,7 @@ mod tests { let sub = db.wait_key_exists(&key); tx.send(()).unwrap(); sub.await - }) - .expect("some handle on non-wasm"); + }); rx.await.unwrap(); join_handle } diff --git a/fedimint-core/src/lib.rs b/fedimint-core/src/lib.rs index c78a9352b6a..33068ee4d00 100644 --- a/fedimint-core/src/lib.rs +++ b/fedimint-core/src/lib.rs @@ -44,6 +44,9 @@ pub mod macros; pub mod module; pub mod net; pub mod query; +/// Runtime (wasm32 vs native) differences handling +pub mod runtime; +/// Task handling, including wasm safe logic pub mod task; pub mod tiered; pub mod tiered_multi; diff --git a/fedimint-core/src/net/peers/fake.rs b/fedimint-core/src/net/peers/fake.rs index 5299c4632fc..3039ad30e2b 100644 --- a/fedimint-core/src/net/peers/fake.rs +++ b/fedimint-core/src/net/peers/fake.rs @@ -4,7 +4,8 @@ use std::time::Duration; use async_trait::async_trait; use fedimint_core::cancellable::{Cancellable, Cancelled}; use fedimint_core::net::peers::{IPeerConnections, PeerConnections}; -use fedimint_core::task::{sleep, TaskHandle}; +use fedimint_core::runtime::sleep; +use fedimint_core::task::TaskHandle; use fedimint_core::PeerId; use serde::de::DeserializeOwned; use serde::Serialize; diff --git a/fedimint-core/src/runtime.rs b/fedimint-core/src/runtime.rs new file mode 100644 index 00000000000..896f929d130 --- /dev/null +++ b/fedimint-core/src/runtime.rs @@ -0,0 +1,164 @@ +//! Copyright 2021 The Matrix.org Foundation C.I.C. +//! Abstraction over an executor so we can spawn tasks under WASM the same way +//! we do usually. + +// Adapted from https://github.com/matrix-org/matrix-rust-sdk + +use std::future::Future; +use std::time::Duration; + +use thiserror::Error; +use tokio::time::Instant; + +#[derive(Debug, Error)] +#[error("deadline has elapsed")] +pub struct Elapsed; + +pub use self::r#impl::*; + +#[cfg(not(target_family = "wasm"))] +mod r#impl { + pub use tokio::task::{JoinError, JoinHandle}; + + use super::*; + + pub fn spawn(name: &str, future: F) -> tokio::task::JoinHandle + where + F: Future + 'static + Send, + T: Send + 'static, + { + tokio::task::Builder::new() + .name(name) + .spawn(future) + .expect("spawn failed") + } + + pub(crate) fn spawn_local(name: &str, future: F) -> JoinHandle<()> + where + F: Future + 'static, + { + tokio::task::Builder::new() + .name(name) + .spawn_local(future) + .expect("spawn failed") + } + + pub fn block_in_place(f: F) -> R + where + F: FnOnce() -> R, + { + tokio::task::block_in_place(f) + } + + pub async fn sleep(duration: Duration) { + // nosemgrep: ban-tokio-sleep + tokio::time::sleep(duration).await + } + + pub async fn sleep_until(deadline: Instant) { + tokio::time::sleep_until(deadline).await + } + + pub async fn timeout(duration: Duration, future: T) -> Result + where + T: Future, + { + tokio::time::timeout(duration, future) + .await + .map_err(|_| Elapsed) + } +} + +#[cfg(target_family = "wasm")] +mod r#impl { + + pub use std::convert::Infallible as JoinError; + use std::pin::Pin; + use std::task::{Context, Poll}; + + use async_lock::{RwLock, RwLockReadGuard, RwLockWriteGuard}; + use futures_util::future::RemoteHandle; + use futures_util::FutureExt; + + use super::*; + + #[derive(Debug)] + pub struct JoinHandle { + handle: Option>, + } + + impl JoinHandle { + pub fn abort(mut self) { + drop(self.handle.take()); + } + } + + impl Drop for JoinHandle { + fn drop(&mut self) { + // don't abort the spawned future + if let Some(h) = self.handle.take() { + h.forget(); + } + } + } + impl Future for JoinHandle { + type Output = Result; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + if let Some(handle) = self.handle.as_mut() { + Pin::new(handle).poll(cx).map(Ok) + } else { + Poll::Pending + } + } + } + + pub fn spawn(name: &str, future: F) -> JoinHandle + where + F: Future + 'static, + { + let (fut, handle) = future.remote_handle(); + wasm_bindgen_futures::spawn_local(fut); + + JoinHandle { + handle: Some(handle), + } + } + + pub(crate) fn spawn_local(name: &str, future: F) -> JoinHandle<()> + where + // No Send needed on wasm + F: Future + 'static, + { + spawn(name, future) + } + + pub fn block_in_place(f: F) -> R + where + F: FnOnce() -> R, + { + // no such hint on wasm + f() + } + + pub async fn sleep(duration: Duration) { + gloo_timers::future::sleep(duration.min(Duration::from_millis(i32::MAX as _))).await + } + + pub async fn sleep_until(deadline: Instant) { + // nosemgrep: ban-system-time-now + // nosemgrep: ban-instant-now + sleep(deadline.saturating_duration_since(Instant::now())).await + } + + pub async fn timeout(duration: Duration, future: T) -> Result + where + T: Future, + { + futures::pin_mut!(future); + futures::select_biased! { + value = future.fuse() => Ok(value), + _ = sleep(duration).fuse() => Err(Elapsed), + } + } +} diff --git a/fedimint-core/src/task.rs b/fedimint-core/src/task.rs index c4932083ab7..6662f9cfc07 100644 --- a/fedimint-core/src/task.rs +++ b/fedimint-core/src/task.rs @@ -9,27 +9,19 @@ use std::collections::VecDeque; use std::future::Future; use std::pin::{pin, Pin}; use std::sync::Arc; -use std::time::{Duration, Instant, SystemTime}; +use std::time::{Duration, SystemTime}; use anyhow::bail; use fedimint_core::time::now; use fedimint_logging::{LOG_TASK, LOG_TEST}; use futures::future::{self, Either}; -pub use imp::*; -use thiserror::Error; use tokio::sync::{oneshot, watch}; -#[cfg(not(target_family = "wasm"))] -use tokio::task::{JoinError, JoinHandle}; use tracing::{debug, error, info, warn}; -#[cfg(target_family = "wasm")] -type JoinHandle = future::Ready>; -#[cfg(target_family = "wasm")] -type JoinError = anyhow::Error; - -#[derive(Debug, Error)] -#[error("deadline has elapsed")] -pub struct Elapsed; +use crate::runtime; +// TODO: stop using `task::*`, and use `runtime::*` in the code +// lots of churn though +pub use crate::runtime::*; #[derive(Debug)] struct TaskGroupInner { @@ -158,7 +150,7 @@ impl TaskGroup { _ = terminate => {}, } } - spawn("kill handlers", { + runtime::spawn("kill handlers", { let task_group = self.clone(); async move { wait_for_shutdown_signal().await; @@ -171,15 +163,14 @@ impl TaskGroup { }); } - #[cfg(not(target_family = "wasm"))] pub fn spawn( &self, name: impl Into, - f: impl FnOnce(TaskHandle) -> Fut + Send + 'static, + f: impl FnOnce(TaskHandle) -> Fut + MaybeSend + 'static, ) -> oneshot::Receiver where - Fut: Future + Send + 'static, - R: Send + 'static, + Fut: Future + MaybeSend + 'static, + R: MaybeSend + 'static, { use tracing::{info_span, Instrument, Span}; @@ -194,7 +185,7 @@ impl TaskGroup { let handle = self.make_handle(); let (tx, rx) = oneshot::channel(); - if let Some(handle) = self::imp::spawn(name.as_str(), { + let handle = crate::runtime::spawn(&name, { let name = name.clone(); async move { // if receiver is not interested, just drop the message @@ -204,19 +195,17 @@ impl TaskGroup { let _ = tx.send(r); } .instrument(span) - }) { - self.inner - .join - .lock() - .expect("lock poison") - .push_back((name, handle)); - } + }); + self.inner + .join + .lock() + .expect("lock poison") + .push_back((name, handle)); guard.completed = true; rx } - #[cfg(not(target_family = "wasm"))] pub async fn spawn_local( &self, name: impl Into, @@ -232,49 +221,15 @@ impl TaskGroup { }; let handle = self.make_handle(); - if let Some(handle) = self::imp::spawn_local(name.as_str(), async move { + let handle = runtime::spawn_local(name.as_str(), async move { f(handle).await; - }) { - self.inner - .join - .lock() - .expect("lock poison") - .push_back((name, handle)); - } - guard.completed = true; - } - // TODO: Send vs lack of Send bound; do something about it - #[cfg(target_family = "wasm")] - pub fn spawn( - &self, - name: impl Into, - f: impl FnOnce(TaskHandle) -> Fut + 'static, - ) -> oneshot::Receiver - where - Fut: Future + 'static, - R: 'static, - { - let name = name.into(); - let mut guard = TaskPanicGuard { - name: name.clone(), - inner: self.inner.clone(), - completed: false, - }; - let handle = self.make_handle(); - - let (tx, rx) = oneshot::channel(); - if let Some(handle) = self::imp::spawn(name.as_str(), async move { - let _ = tx.send(f(handle).await); - }) { - self.inner - .join - .lock() - .expect("lock poison") - .push_back((name, handle)); - } + }); + self.inner + .join + .lock() + .expect("lock poison") + .push_back((name, handle)); guard.completed = true; - - rx } /// Spawn a task that will get cancelled automatically on TaskGroup @@ -337,14 +292,14 @@ impl TaskGroup { #[cfg(not(target_family = "wasm"))] let join_future: Pin + Send>> = if let Some(timeout) = timeout { - Box::pin(self::timeout(timeout, join)) + Box::pin(runtime::timeout(timeout, join)) } else { Box::pin(async move { Ok(join.await) }) }; #[cfg(target_family = "wasm")] let join_future: Pin>> = if let Some(timeout) = timeout { - Box::pin(self::timeout(timeout, join)) + Box::pin(runtime::timeout(timeout, join)) } else { Box::pin(async move { Ok(join.await) }) }; @@ -357,7 +312,7 @@ impl TaskGroup { error!(target: LOG_TASK, task=%name, error=%e, "Task panicked"); errors.push(e); } - Err(Elapsed) => { + Err(_) => { warn!( target: LOG_TASK, task=%name, "Timeout waiting for task to shut down" @@ -453,116 +408,6 @@ impl Future for TaskShutdownToken { } } -#[cfg(not(target_family = "wasm"))] -mod imp { - pub use tokio::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard}; - - use super::*; - - pub fn spawn(name: &str, future: F) -> Option> - where - F: Future + Send + 'static, - { - Some( - tokio::task::Builder::new() - .name(name) - .spawn(future) - .expect("spawn failed"), - ) - } - - pub(crate) fn spawn_local(name: &str, future: F) -> Option> - where - F: Future + 'static, - { - Some( - tokio::task::Builder::new() - .name(name) - .spawn_local(future) - .expect("spawn failed"), - ) - } - - pub fn block_in_place(f: F) -> R - where - F: FnOnce() -> R, - { - tokio::task::block_in_place(f) - } - - pub async fn sleep(duration: Duration) { - // nosemgrep: ban-tokio-sleep - tokio::time::sleep(duration).await - } - - pub async fn sleep_until(deadline: Instant) { - tokio::time::sleep_until(deadline.into()).await - } - - pub async fn timeout(duration: Duration, future: T) -> Result - where - T: Future, - { - tokio::time::timeout(duration, future) - .await - .map_err(|_| Elapsed) - } -} - -#[cfg(target_family = "wasm")] -mod imp { - pub use async_lock::{RwLock, RwLockReadGuard, RwLockWriteGuard}; - use futures::FutureExt; - - use super::*; - - pub fn spawn(_name: &str, future: F) -> Option> - where - // No Send needed on wasm - F: Future + 'static, - { - wasm_bindgen_futures::spawn_local(future); - None - } - - pub(crate) fn spawn_local(_name: &str, future: F) -> Option> - where - // No Send needed on wasm - F: Future + 'static, - { - self::spawn(_name, future) - } - - pub fn block_in_place(f: F) -> R - where - F: FnOnce() -> R, - { - // no such hint on wasm - f() - } - - pub async fn sleep(duration: Duration) { - gloo_timers::future::sleep(duration.min(Duration::from_millis(i32::MAX as _))).await - } - - pub async fn sleep_until(deadline: Instant) { - // nosemgrep: ban-system-time-now - // nosemgrep: ban-instant-now - sleep(deadline.saturating_duration_since(Instant::now())).await - } - - pub async fn timeout(duration: Duration, future: T) -> Result - where - T: Future, - { - futures::pin_mut!(future); - futures::select_biased! { - value = future.fuse() => Ok(value), - _ = sleep(duration).fuse() => Err(Elapsed), - } - } -} - /// async trait that use MaybeSend /// /// # Example diff --git a/fedimint-core/src/task/jit.rs b/fedimint-core/src/task/jit.rs index 1f8de44c504..1f30e6336ef 100644 --- a/fedimint-core/src/task/jit.rs +++ b/fedimint-core/src/task/jit.rs @@ -90,7 +90,7 @@ where let (cancel_tx, mut cancel_rx) = tokio::sync::mpsc::channel(1); let (val_tx, val_rx) = oneshot::channel(); let type_name = std::any::type_name::(); - super::imp::spawn( + crate::runtime::spawn( &format!("JitTry {} value", std::any::type_name::()), async move { select! { @@ -109,8 +109,7 @@ where }, } }, - ) - .expect("spawn not fail"); + ); Self { _cancel_tx: cancel_tx, @@ -200,7 +199,7 @@ mod tests { #[test_log::test(tokio::test)] async fn sanity_jit() { let v = Jit::new(|| async { - fedimint_core::task::sleep(Duration::from_millis(0)).await; + fedimint_core::runtime::sleep(Duration::from_millis(0)).await; 3 }); @@ -212,7 +211,7 @@ mod tests { #[test_log::test(tokio::test)] async fn sanity_jit_try_ok() { let v = JitTryAnyhow::new_try(|| async { - fedimint_core::task::sleep(Duration::from_millis(0)).await; + fedimint_core::runtime::sleep(Duration::from_millis(0)).await; Ok(3) }); @@ -224,7 +223,7 @@ mod tests { #[test_log::test(tokio::test)] async fn sanity_jit_try_err() { let v = JitTry::new_try(|| async { - fedimint_core::task::sleep(Duration::from_millis(0)).await; + fedimint_core::runtime::sleep(Duration::from_millis(0)).await; bail!("BOOM"); #[allow(unreachable_code)] Ok(3) diff --git a/fedimint-core/src/task/waiter.rs b/fedimint-core/src/task/waiter.rs index 45293b0946d..79e9e575189 100644 --- a/fedimint-core/src/task/waiter.rs +++ b/fedimint-core/src/task/waiter.rs @@ -100,7 +100,7 @@ mod tests { assert!(!waiter.is_done()); tokio::join!( async { - fedimint_core::task::sleep(Duration::from_millis(10)).await; + fedimint_core::runtime::sleep(Duration::from_millis(10)).await; waiter.done(); }, waiter.wait(), diff --git a/fedimint-core/src/util/mod.rs b/fedimint-core/src/util/mod.rs index 02f2c49e961..f0a01dd5523 100644 --- a/fedimint-core/src/util/mod.rs +++ b/fedimint-core/src/util/mod.rs @@ -19,8 +19,8 @@ use tokio::io::AsyncWriteExt; use tracing::{debug, warn, Instrument, Span}; use url::{Host, ParseError, Url}; -use crate::task::{self, MaybeSend}; -use crate::{apply, async_trait_maybe_send, maybe_add_send}; +use crate::task::MaybeSend; +use crate::{apply, async_trait_maybe_send, maybe_add_send, runtime}; /// Future that is `Send` unless targeting WASM pub type BoxFuture<'a, T> = Pin + 'a)>>; @@ -348,7 +348,7 @@ where "{} failed, retrying", op_name, ); - task::sleep(interval).await; + runtime::sleep(interval).await; } else { warn!( target: LOG_CORE, @@ -370,11 +370,11 @@ mod tests { use std::time::Duration; use anyhow::anyhow; - use fedimint_core::task::Elapsed; + use fedimint_core::runtime::Elapsed; use futures::FutureExt; use super::*; - use crate::task::timeout; + use crate::runtime::timeout; #[test] fn test_safe_url() { diff --git a/fedimint-load-test-tool/src/main.rs b/fedimint-load-test-tool/src/main.rs index 445563a162f..66dc34881d2 100644 --- a/fedimint-load-test-tool/src/main.rs +++ b/fedimint-load-test-tool/src/main.rs @@ -18,7 +18,7 @@ use fedimint_core::api::InviteCode; use fedimint_core::config::ClientConfig; use fedimint_core::endpoint_constants::SESSION_COUNT_ENDPOINT; use fedimint_core::module::ApiRequestErased; -use fedimint_core::task::spawn; +use fedimint_core::runtime::spawn; use fedimint_core::util::{BoxFuture, SafeUrl}; use fedimint_core::Amount; use fedimint_ln_client::{LightningClientModule, LnReceiveState}; @@ -294,8 +294,7 @@ async fn main() -> anyhow::Result<()> { let summary_handle = spawn("handle metrics summary", { let opts = opts.clone(); async move { handle_metrics_summary(opts, event_receiver).await } - }) - .expect("some handle on non-wasm"); + }); let futures = match opts.command.clone() { Command::TestConnect { invite_code, diff --git a/fedimint-rocksdb/src/lib.rs b/fedimint-rocksdb/src/lib.rs index 55e862e17ab..b49e03b8b5e 100644 --- a/fedimint-rocksdb/src/lib.rs +++ b/fedimint-rocksdb/src/lib.rs @@ -142,7 +142,7 @@ impl IRawDatabase for RocksDbReadOnly { #[async_trait] impl<'a> IDatabaseTransactionOpsCore for RocksDbTransaction<'a> { async fn raw_insert_bytes(&mut self, key: &[u8], value: &[u8]) -> Result>> { - fedimint_core::task::block_in_place(|| { + fedimint_core::runtime::block_in_place(|| { let val = self.0.get(key).unwrap(); self.0.put(key, value)?; Ok(val) @@ -150,11 +150,11 @@ impl<'a> IDatabaseTransactionOpsCore for RocksDbTransaction<'a> { } async fn raw_get_bytes(&mut self, key: &[u8]) -> Result>> { - fedimint_core::task::block_in_place(|| Ok(self.0.snapshot().get(key)?)) + fedimint_core::runtime::block_in_place(|| Ok(self.0.snapshot().get(key)?)) } async fn raw_remove_entry(&mut self, key: &[u8]) -> Result>> { - fedimint_core::task::block_in_place(|| { + fedimint_core::runtime::block_in_place(|| { let val = self.0.get(key).unwrap(); self.0.delete(key)?; Ok(val) @@ -170,14 +170,14 @@ impl<'a> IDatabaseTransactionOpsCore for RocksDbTransaction<'a> { I::Item: Send, { stream::unfold(iter, |mut iter| async move { - tokio::task::block_in_place(move || { + fedimint_core::runtime::block_in_place(move || { let item = iter.next(); item.map(move |item| (item, iter)) }) }) } - Ok(fedimint_core::task::block_in_place(|| { + Ok(fedimint_core::runtime::block_in_place(|| { let prefix = key_prefix.to_vec(); let mut options = rocksdb::ReadOptions::default(); options.set_iterate_range(rocksdb::PrefixRange(prefix.clone())); @@ -196,7 +196,7 @@ impl<'a> IDatabaseTransactionOpsCore for RocksDbTransaction<'a> { } async fn raw_remove_by_prefix(&mut self, key_prefix: &[u8]) -> anyhow::Result<()> { - fedimint_core::task::block_in_place(|| { + fedimint_core::runtime::block_in_place(|| { // Note: delete_range is not supported in Transactions :/ let mut options = rocksdb::ReadOptions::default(); options.set_iterate_range(rocksdb::PrefixRange(key_prefix.to_owned())); @@ -236,7 +236,7 @@ impl<'a> IDatabaseTransactionOpsCore for RocksDbTransaction<'a> { } else { rocksdb::IteratorMode::End }; - Ok(fedimint_core::task::block_in_place(|| { + Ok(fedimint_core::runtime::block_in_place(|| { let mut options = rocksdb::ReadOptions::default(); options.set_iterate_range(rocksdb::PrefixRange(prefix.clone())); let iter = self.0.snapshot().iterator_opt(iterator_mode, options); @@ -254,13 +254,13 @@ impl<'a> IDatabaseTransactionOpsCore for RocksDbTransaction<'a> { #[async_trait] impl<'a> IDatabaseTransactionOps for RocksDbTransaction<'a> { async fn rollback_tx_to_savepoint(&mut self) -> Result<()> { - Ok(fedimint_core::task::block_in_place(|| { + Ok(fedimint_core::runtime::block_in_place(|| { self.0.rollback_to_savepoint() })?) } async fn set_tx_savepoint(&mut self) -> Result<()> { - fedimint_core::task::block_in_place(|| self.0.set_savepoint()); + fedimint_core::runtime::block_in_place(|| self.0.set_savepoint()); Ok(()) } @@ -269,7 +269,7 @@ impl<'a> IDatabaseTransactionOps for RocksDbTransaction<'a> { #[async_trait] impl<'a> IRawDatabaseTransaction for RocksDbTransaction<'a> { async fn commit_tx(self) -> Result<()> { - fedimint_core::task::block_in_place(|| { + fedimint_core::runtime::block_in_place(|| { self.0.commit()?; Ok(()) }) @@ -283,7 +283,7 @@ impl<'a> IDatabaseTransactionOpsCore for RocksDbReadOnlyTransaction<'a> { } async fn raw_get_bytes(&mut self, key: &[u8]) -> Result>> { - fedimint_core::task::block_in_place(|| Ok(self.0.get(key)?)) + fedimint_core::runtime::block_in_place(|| Ok(self.0.get(key)?)) } async fn raw_remove_entry(&mut self, _key: &[u8]) -> Result>> { @@ -291,7 +291,7 @@ impl<'a> IDatabaseTransactionOpsCore for RocksDbReadOnlyTransaction<'a> { } async fn raw_find_by_prefix(&mut self, key_prefix: &[u8]) -> Result> { - Ok(fedimint_core::task::block_in_place(|| { + Ok(fedimint_core::runtime::block_in_place(|| { let prefix = key_prefix.to_vec(); let rocksdb_iter = self .0 @@ -322,7 +322,7 @@ impl<'a> IDatabaseTransactionOpsCore for RocksDbReadOnlyTransaction<'a> { } else { rocksdb::IteratorMode::End }; - Ok(fedimint_core::task::block_in_place(|| { + Ok(fedimint_core::runtime::block_in_place(|| { let mut options = rocksdb::ReadOptions::default(); options.set_iterate_range(rocksdb::PrefixRange(prefix.clone())); let iter = self.0.snapshot().iterator_opt(iterator_mode, options); diff --git a/fedimint-server/src/atomic_broadcast/spawner.rs b/fedimint-server/src/atomic_broadcast/spawner.rs index 639bf523f35..86e0a71b54f 100644 --- a/fedimint-server/src/atomic_broadcast/spawner.rs +++ b/fedimint-server/src/atomic_broadcast/spawner.rs @@ -18,7 +18,7 @@ impl Default for Spawner { impl aleph_bft::SpawnHandle for Spawner { fn spawn(&self, name: &str, task: impl futures::Future + Send + 'static) { - fedimint_core::task::spawn(name, task); + fedimint_core::runtime::spawn(name, task); } fn spawn_essential( @@ -28,7 +28,7 @@ impl aleph_bft::SpawnHandle for Spawner { ) -> aleph_bft::TaskHandle { let (res_tx, res_rx) = futures::channel::oneshot::channel(); - fedimint_core::task::spawn(name, async move { + fedimint_core::runtime::spawn(name, async move { task.await; if let Err(_err) = res_tx.send(()) { warn!(target: LOG_CONSENSUS, "Unable to send essential spawned task completion. Are we shutting down?"); diff --git a/fedimint-server/src/config/api.rs b/fedimint-server/src/config/api.rs index 8313c5593a2..01427324c9c 100644 --- a/fedimint-server/src/config/api.rs +++ b/fedimint-server/src/config/api.rs @@ -908,7 +908,8 @@ mod tests { use fedimint_core::db::mem_impl::MemDatabase; use fedimint_core::db::IRawDatabaseExt; use fedimint_core::module::ApiAuth; - use fedimint_core::task::{sleep, spawn, TaskGroup}; + use fedimint_core::runtime::spawn; + use fedimint_core::task::{sleep, TaskGroup}; use fedimint_core::util::SafeUrl; use fedimint_core::Amount; use fedimint_dummy_common::config::{ diff --git a/fedimint-server/src/config/distributedgen.rs b/fedimint-server/src/config/distributedgen.rs index 59297dcdd23..fe78edae4b2 100644 --- a/fedimint-server/src/config/distributedgen.rs +++ b/fedimint-server/src/config/distributedgen.rs @@ -15,7 +15,7 @@ use fedimint_core::encoding::{Decodable, Encodable}; use fedimint_core::module::registry::ModuleDecoderRegistry; use fedimint_core::module::PeerHandle; use fedimint_core::net::peers::MuxPeerConnections; -use fedimint_core::task::spawn; +use fedimint_core::runtime::spawn; use fedimint_core::{BitcoinHash, NumPeersExt, PeerId}; use rand::rngs::OsRng; use rand::{RngCore, SeedableRng}; diff --git a/fedimint-server/src/consensus/server.rs b/fedimint-server/src/consensus/server.rs index be82a457501..78ee1317e28 100644 --- a/fedimint-server/src/consensus/server.rs +++ b/fedimint-server/src/consensus/server.rs @@ -22,15 +22,16 @@ use fedimint_core::module::registry::{ }; use fedimint_core::module::{ApiRequestErased, SerdeModuleEncoding}; use fedimint_core::query::FilterMap; +use fedimint_core::runtime::spawn; use fedimint_core::session_outcome::{ AcceptedItem, SchnorrSignature, SessionOutcome, SignedSessionOutcome, }; -use fedimint_core::task::{sleep, spawn, RwLock, TaskGroup, TaskHandle}; +use fedimint_core::task::{sleep, TaskGroup, TaskHandle}; use fedimint_core::timing::TimeReporter; use fedimint_core::util::SafeUrl; use fedimint_core::{timing, NumPeers, PeerId}; use futures::StreamExt; -use tokio::sync::watch; +use tokio::sync::{watch, RwLock}; use tracing::{debug, info, warn}; use crate::atomic_broadcast::data_provider::{DataProvider, UnitData}; @@ -412,8 +413,7 @@ impl ConsensusServer { Spawner::new(), aleph_bft_types::Terminator::create_root(terminator_receiver, "Terminator"), ), - ) - .expect("some handle on non-wasm"); + ); // this is the minimum number of batches data that will be ordered before we // reach the exponential_slowdown_offset since at least f + 1 batches are diff --git a/fedimint-server/src/multiplexed.rs b/fedimint-server/src/multiplexed.rs index 00e4eee7f90..a8f52893d86 100644 --- a/fedimint-server/src/multiplexed.rs +++ b/fedimint-server/src/multiplexed.rs @@ -5,7 +5,7 @@ use std::hash::Hash; use async_trait::async_trait; use fedimint_core::cancellable::{Cancellable, Cancelled}; use fedimint_core::net::peers::{IMuxPeerConnections, PeerConnections}; -use fedimint_core::task::spawn; +use fedimint_core::runtime::spawn; use fedimint_core::PeerId; use fedimint_logging::LOG_NET_PEER; use serde::de::DeserializeOwned; diff --git a/fedimint-server/src/net/connect.rs b/fedimint-server/src/net/connect.rs index de4dec25356..e573c3dda62 100644 --- a/fedimint-server/src/net/connect.rs +++ b/fedimint-server/src/net/connect.rs @@ -256,7 +256,8 @@ pub mod mock { use std::time::Duration; use anyhow::{anyhow, Error}; - use fedimint_core::task::{sleep, spawn}; + use fedimint_core::runtime::spawn; + use fedimint_core::task::sleep; use fedimint_core::util::SafeUrl; use fedimint_core::{task, PeerId}; use futures::{pin_mut, FutureExt, SinkExt, Stream, StreamExt}; @@ -726,8 +727,7 @@ pub mod mock { let mut listener = Connector::::listen(&conn_a, bind_addr).await.unwrap(); let conn_a_fut = spawn("listener next await", async move { listener.next().await.unwrap().unwrap() - }) - .expect("some handle on non-wasm"); + }); let (auth_peer_b, mut conn_b) = Connector::::connect_framed(&conn_b, url, peer_a) .await @@ -803,8 +803,7 @@ pub mod mock { .unwrap(); let conn_a_fut = spawn("listener next await", async move { listener.next().await.unwrap().unwrap() - }) - .expect("some handle on non-wasm"); + }); let (auth_peer_b, mut conn_b) = Connector::>::connect_framed(&conn_b, url, peer_a) .await @@ -834,7 +833,7 @@ pub mod mock { mod tests { use std::net::SocketAddr; - use fedimint_core::task::spawn; + use fedimint_core::runtime::spawn; use fedimint_core::util::SafeUrl; use fedimint_core::PeerId; use futures::{SinkExt, StreamExt}; @@ -891,8 +890,7 @@ mod tests { assert_eq!(received, 42); conn.send(21).await.unwrap(); assert!(conn.next().await.unwrap().is_err()); - }) - .expect("some handle on non-wasm"); + }); let (peer_of_a, mut client_a): (_, AnyFramedTransport) = connectors[2] .connect_framed(url.clone(), PeerId::from(0)) @@ -929,8 +927,7 @@ mod tests { conn_res.err().unwrap().to_string().as_str(), "invalid peer certificate signature" ); - }) - .expect("some handle on non-wasm"); + }); let err_anytime = async { let (_peer, mut conn): (_, AnyFramedTransport) = malicious_wrong_key @@ -964,8 +961,7 @@ mod tests { conn_res.err().unwrap().to_string().as_str(), "received fatal alert: BadCertificate" ); - }) - .expect("some handle on non-wasm"); + }); let err_anytime = async { let (_peer, mut conn): (_, AnyFramedTransport) = @@ -1001,8 +997,7 @@ mod tests { conn_res.err().unwrap().to_string().as_str(), "received fatal alert: BadCertificate" ); - }) - .expect("some handle on non-wasm"); + }); let err_anytime = async { let (_peer, mut conn): (_, AnyFramedTransport) = diff --git a/fedimint-server/src/net/peers.rs b/fedimint-server/src/net/peers.rs index 985ce0e784a..a91503dfa24 100644 --- a/fedimint-server/src/net/peers.rs +++ b/fedimint-server/src/net/peers.rs @@ -470,7 +470,7 @@ where Err(e) => self.disconnect_err(e, 0), } }, - _ = sleep_until(connected.next_ping.into()) => { + _ = sleep_until(connected.next_ping) => { trace!(target: LOG_NET_PEER, our_id = ?self.our_id, peer = ?self.peer_id, "Sending ping"); self.send_message_connected(connected, PeerMessage::Ping) .await diff --git a/fedimint-server/src/net/peers_reliable.rs b/fedimint-server/src/net/peers_reliable.rs index e81a7d9d33e..1f7d2bbf01c 100644 --- a/fedimint-server/src/net/peers_reliable.rs +++ b/fedimint-server/src/net/peers_reliable.rs @@ -366,7 +366,7 @@ where Some(msg_res) = connected.connection.next() => { self.receive_message(connected, msg_res).await }, - _ = sleep_until(connected.next_ping.into()) => { + _ = sleep_until(connected.next_ping) => { self.send_ping(connected).await }, _ = task_handle.make_shutdown_rx().await => { diff --git a/gateway/ln-gateway/src/lib.rs b/gateway/ln-gateway/src/lib.rs index 86487f7a746..46e0c6e565c 100644 --- a/gateway/ln-gateway/src/lib.rs +++ b/gateway/ln-gateway/src/lib.rs @@ -44,7 +44,7 @@ use fedimint_core::db::{ }; use fedimint_core::fmt_utils::OptStacktrace; use fedimint_core::module::CommonModuleInit; -use fedimint_core::task::{sleep, RwLock, TaskGroup, TaskHandle, TaskShutdownToken}; +use fedimint_core::task::{sleep, TaskGroup, TaskHandle, TaskShutdownToken}; use fedimint_core::time::now; use fedimint_core::util::{SafeUrl, Spanned}; use fedimint_core::{ @@ -74,7 +74,7 @@ use state_machine::pay::OutgoingPaymentError; use state_machine::GatewayClientModule; use strum::IntoEnumIterator; use thiserror::Error; -use tokio::sync::{Mutex, MutexGuard}; +use tokio::sync::{Mutex, MutexGuard, RwLock}; use tracing::{debug, error, info, info_span, warn, Instrument}; use crate::db::{get_gatewayd_database_migrations, FederationConfig, FederationIdKeyPrefix}; diff --git a/modules/fedimint-ln-client/src/incoming.rs b/modules/fedimint-ln-client/src/incoming.rs index 0408a142138..85a5cafadcd 100644 --- a/modules/fedimint-ln-client/src/incoming.rs +++ b/modules/fedimint-ln-client/src/incoming.rs @@ -16,7 +16,7 @@ use fedimint_client::transaction::ClientInput; use fedimint_client::DynGlobalClientContext; use fedimint_core::core::OperationId; use fedimint_core::encoding::{Decodable, Encodable}; -use fedimint_core::task::sleep; +use fedimint_core::runtime::sleep; use fedimint_core::{Amount, OutPoint, TransactionId}; use fedimint_ln_common::contracts::incoming::IncomingContractAccount; use fedimint_ln_common::contracts::{ContractId, Preimage}; @@ -185,7 +185,7 @@ impl FundingOfferState { } } // give some time for other things to run - fedimint_core::task::sleep(Duration::from_secs(sleep)).await; + fedimint_core::runtime::sleep(Duration::from_secs(sleep)).await; } unreachable!("there is too many u64s to ever get here") diff --git a/modules/fedimint-ln-client/src/lib.rs b/modules/fedimint-ln-client/src/lib.rs index 538b7dee058..ed75de039a4 100644 --- a/modules/fedimint-ln-client/src/lib.rs +++ b/modules/fedimint-ln-client/src/lib.rs @@ -36,10 +36,10 @@ use fedimint_core::encoding::{Decodable, Encodable}; use fedimint_core::module::{ ApiVersion, CommonModuleInit, ModuleCommon, ModuleInit, MultiApiVersion, TransactionItemAmount, }; -use fedimint_core::task::{self, timeout, MaybeSend, MaybeSync}; +use fedimint_core::task::{timeout, MaybeSend, MaybeSync}; use fedimint_core::util::{retry, FibonacciBackoff}; use fedimint_core::{ - apply, async_trait_maybe_send, push_db_pair_items, Amount, OutPoint, TransactionId, + apply, async_trait_maybe_send, push_db_pair_items, runtime, Amount, OutPoint, TransactionId, }; use fedimint_ln_common::config::{FeeToAmount, LightningClientConfig}; use fedimint_ln_common::contracts::incoming::{IncomingContract, IncomingContractOffer}; @@ -930,7 +930,7 @@ impl LightningClientModule { } else { EMPTY_GATEWAY_SLEEP }); - task::sleep(sleep_time).await; + runtime::sleep(sleep_time).await; // should never fail with usize::MAX attempts. let _ = retry( diff --git a/modules/fedimint-mint-client/src/oob.rs b/modules/fedimint-mint-client/src/oob.rs index c7ac3ead551..cdee4b9def4 100644 --- a/modules/fedimint-mint-client/src/oob.rs +++ b/modules/fedimint-mint-client/src/oob.rs @@ -6,7 +6,7 @@ use fedimint_client::transaction::ClientInput; use fedimint_client::DynGlobalClientContext; use fedimint_core::core::OperationId; use fedimint_core::encoding::{Decodable, Encodable}; -use fedimint_core::{task, Amount, TransactionId}; +use fedimint_core::{runtime, Amount, TransactionId}; use fedimint_mint_common::MintInput; use crate::input::{ @@ -141,7 +141,7 @@ async fn transition_user_cancel( async fn await_timeout_cancel(deadline: SystemTime) { if let Ok(time_until_deadline) = deadline.duration_since(fedimint_core::time::now()) { - task::sleep(time_until_deadline).await; + runtime::sleep(time_until_deadline).await; } } diff --git a/modules/fedimint-mint-tests/tests/tests.rs b/modules/fedimint-mint-tests/tests/tests.rs index 9ac8c20ee6d..cdea1237ac0 100644 --- a/modules/fedimint-mint-tests/tests/tests.rs +++ b/modules/fedimint-mint-tests/tests/tests.rs @@ -106,8 +106,9 @@ async fn sends_ecash_oob_highly_parallel() -> anyhow::Result<()> { let mut spend_tasks = vec![]; for num_spend in 0..NUM_PAR { let task_client1 = client1.clone(); - spend_tasks.push( - fedimint_core::task::spawn(&format!("spend_ecash_{num_spend}"), async move { + spend_tasks.push(fedimint_core::runtime::spawn( + &format!("spend_ecash_{num_spend}"), + async move { info!("Starting spend {num_spend}"); let client1_mint = task_client1.get_first_module::(); let (op, notes) = client1_mint @@ -121,9 +122,8 @@ async fn sends_ecash_oob_highly_parallel() -> anyhow::Result<()> { .into_stream(); assert_eq!(sub1.ok().await.unwrap(), SpendOOBState::Created); notes - }) - .expect("Returns a handle if not run in WASM"), - ); + }, + )); } let note_bags = futures::stream::iter(spend_tasks) @@ -141,8 +141,9 @@ async fn sends_ecash_oob_highly_parallel() -> anyhow::Result<()> { let mut reissue_tasks = vec![]; for (num_reissue, notes) in note_bags.into_iter().enumerate() { let task_client2 = client2.clone(); - reissue_tasks.push( - fedimint_core::task::spawn(&format!("reissue_ecash_{num_reissue}"), async move { + reissue_tasks.push(fedimint_core::runtime::spawn( + &format!("reissue_ecash_{num_reissue}"), + async move { info!("Starting reissue {num_reissue}"); let client2_mint = task_client2.get_first_module::(); let op = client2_mint @@ -160,9 +161,8 @@ async fn sends_ecash_oob_highly_parallel() -> anyhow::Result<()> { info!("Reissuance {num_reissue} accepted"); assert_eq!(sub2.ok().await.unwrap(), ReissueExternalNotesState::Done); info!("Reissuance {num_reissue} finished"); - }) - .expect("Returns a handle if not run in WASM"), - ); + }, + )); } for task in reissue_tasks { From a2eb774d86972d23b5564a5d9b26f1393d167ae4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dawid=20Ci=C4=99=C5=BCarkiewicz?= Date: Fri, 5 Apr 2024 18:15:06 -0700 Subject: [PATCH 10/18] chore: no block_in_place and block_on on wasm --- .config/semgrep.yaml | 18 ++++++++++++++++++ devimint/src/external.rs | 3 +-- devimint/src/federation.rs | 5 +++-- devimint/src/util.rs | 3 +-- fedimint-cli/src/db_locked.rs | 3 ++- fedimint-client/src/lib.rs | 8 +++++--- fedimint-client/src/sm/executor.rs | 14 ++++++++++---- fedimint-core/src/runtime.rs | 18 ++++++++++-------- fedimint-testing/src/btc/real.rs | 4 ++-- fedimint-testing/src/fixtures.rs | 5 +++-- fedimint-testing/src/gateway.rs | 3 +-- modules/fedimint-wallet-client/Cargo.toml | 7 ++++++- 12 files changed, 62 insertions(+), 29 deletions(-) diff --git a/.config/semgrep.yaml b/.config/semgrep.yaml index d0a9fcd9fef..cb7e2ff701a 100644 --- a/.config/semgrep.yaml +++ b/.config/semgrep.yaml @@ -72,6 +72,24 @@ rules: pattern: tokio::time::sleep severity: WARNING +- id: ban-raw-block-on + languages: + - rust + message: Use `fedimint_core::runtime::block_on()` instead. + pattern-either: + - pattern: futures::executor::block_on + - pattern: tokio::runtime::Handle::block_on + - pattern: tokio::runtime::Handle::current + severity: WARNING + +- id: ban-raw-block-in-place + languages: + - rust + message: Use `fedimint_core::runtime::block_in_place()` instead. + pattern-either: + - pattern: tokio::task::block_in_place + severity: WARNING + - id: ban-raw-url languages: - rust diff --git a/devimint/src/external.rs b/devimint/src/external.rs index 01da4966e90..345bf056aa8 100644 --- a/devimint/src/external.rs +++ b/devimint/src/external.rs @@ -9,11 +9,10 @@ use bitcoincore_rpc::bitcoin::hashes::hex::ToHex; use bitcoincore_rpc::{bitcoin, RpcApi}; use cln_rpc::ClnRpc; use fedimint_core::encoding::Encodable; -use fedimint_core::task::{block_in_place, sleep}; +use fedimint_core::task::{block_in_place, block_on, sleep}; use fedimint_core::util::write_overwrite_async; use fedimint_logging::LOG_DEVIMINT; use fedimint_testing::gateway::LightningNodeType; -use futures::executor::block_on; use tokio::fs; use tokio::sync::{MappedMutexGuard, Mutex, MutexGuard}; use tokio::time::Instant; diff --git a/devimint/src/federation.rs b/devimint/src/federation.rs index ceebdd4eb1e..f46652efcbf 100644 --- a/devimint/src/federation.rs +++ b/devimint/src/federation.rs @@ -14,6 +14,7 @@ use fedimint_core::config::{load_from_file, ClientConfig, ServerModuleConfigGenP use fedimint_core::core::LEGACY_HARDCODED_INSTANCE_ID_WALLET; use fedimint_core::module::registry::ModuleDecoderRegistry; use fedimint_core::module::{ApiAuth, ModuleCommon}; +use fedimint_core::runtime::block_in_place; use fedimint_core::util::SafeUrl; use fedimint_core::PeerId; use fedimint_logging::LOG_DEVIMINT; @@ -79,7 +80,7 @@ impl Client { /// Create a [`Client`] that starts with a fresh state. pub async fn create(name: &str) -> Result { - tokio::task::block_in_place(|| { + block_in_place(|| { let _lock = Self::client_name_lock(name); for i in 0u64.. { let client = Self { @@ -97,7 +98,7 @@ impl Client { /// Open or create a [`Client`] that starts with a fresh state. pub async fn open_or_create(name: &str) -> Result { - tokio::task::block_in_place(|| { + block_in_place(|| { let _lock = Self::client_name_lock(name); let client = Self { name: format!("{name}-0"), diff --git a/devimint/src/util.rs b/devimint/src/util.rs index be9f32a0c0e..d4835044840 100644 --- a/devimint/src/util.rs +++ b/devimint/src/util.rs @@ -9,10 +9,9 @@ use std::{env, unreachable}; use anyhow::{anyhow, bail, format_err, Context, Result}; use fedimint_core::envs::is_env_var_set; -use fedimint_core::task::{self, block_in_place}; +use fedimint_core::task::{self, block_in_place, block_on}; use fedimint_core::time::now; use fedimint_logging::LOG_DEVIMINT; -use futures::executor::block_on; use semver::Version; use serde::de::DeserializeOwned; use tokio::fs::OpenOptions; diff --git a/fedimint-cli/src/db_locked.rs b/fedimint-cli/src/db_locked.rs index 52343b1c218..316e634e042 100644 --- a/fedimint-cli/src/db_locked.rs +++ b/fedimint-cli/src/db_locked.rs @@ -2,6 +2,7 @@ use std::path::Path; use anyhow::Context; use fedimint_core::db::IRawDatabase; +use fedimint_core::task::block_in_place; use fedimint_core::{apply, async_trait_maybe_send}; use fedimint_logging::LOG_CLIENT; use tracing::{debug, info}; @@ -27,7 +28,7 @@ pub struct LockedBuilder { impl LockedBuilder { /// Create a [`Self`] by acquiring a lock file pub async fn new(lock_path: &Path) -> anyhow::Result { - tokio::task::block_in_place(|| { + block_in_place(|| { let file = std::fs::OpenOptions::new() .write(true) .create(true) diff --git a/fedimint-client/src/lib.rs b/fedimint-client/src/lib.rs index 63ac9ba1fb2..f9bfb56255c 100644 --- a/fedimint-client/src/lib.rs +++ b/fedimint-client/src/lib.rs @@ -106,7 +106,8 @@ use fedimint_core::transaction::Transaction; use fedimint_core::util::{BoxStream, NextOrPending}; use fedimint_core::{ apply, async_trait_maybe_send, dyn_newtype_define, fedimint_build_code_version_env, - maybe_add_send, maybe_add_send_sync, Amount, NumPeers, OutPoint, PeerId, TransactionId, + maybe_add_send, maybe_add_send_sync, runtime, Amount, NumPeers, OutPoint, PeerId, + TransactionId, }; pub use fedimint_derive_secret as derivable_secret; use fedimint_derive_secret::DerivableSecret; @@ -671,6 +672,7 @@ impl Drop for ClientHandle { #[cfg(target_family = "wasm")] let can_block = false; #[cfg(not(target_family = "wasm"))] + // nosemgrep: ban-raw-block-on let can_block = RuntimeHandle::current().runtime_flavor() != RuntimeFlavor::CurrentThread; if !can_block { let inner = self.inner.take().expect("Must have inner client set"); @@ -685,8 +687,8 @@ impl Drop for ClientHandle { debug!(target: LOG_CLIENT, "Shutting down the Client on last handle drop"); #[cfg(not(target_family = "wasm"))] - tokio::task::block_in_place(|| { - RuntimeHandle::current().block_on(self.shutdown_inner()); + runtime::block_in_place(|| { + runtime::block_on(self.shutdown_inner()); }); } } diff --git a/fedimint-client/src/sm/executor.rs b/fedimint-client/src/sm/executor.rs index 5c8bacf615c..8435c507c97 100644 --- a/fedimint-client/src/sm/executor.rs +++ b/fedimint-client/src/sm/executor.rs @@ -736,13 +736,19 @@ impl ExecutorInner { impl Debug for ExecutorInner { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - let (active, inactive) = futures::executor::block_on(async { - let active_states = self.get_active_states().await; - let inactive_states = self.get_inactive_states().await; - (active_states, inactive_states) + #[cfg(not(target_family = "wasm"))] + let (active, inactive) = fedimint_core::runtime::block_in_place(move || { + fedimint_core::runtime::block_on(async { + let active_states = self.get_active_states().await; + let inactive_states = self.get_inactive_states().await; + + (active_states, inactive_states) + }) }); writeln!(f, "ExecutorInner {{")?; + #[cfg(not(target_family = "wasm"))] writeln!(f, " active_states: {active:?}")?; + #[cfg(not(target_family = "wasm"))] writeln!(f, " inactive_states: {inactive:?}")?; writeln!(f, "}}")?; diff --git a/fedimint-core/src/runtime.rs b/fedimint-core/src/runtime.rs index 896f929d130..1b24eab9b01 100644 --- a/fedimint-core/src/runtime.rs +++ b/fedimint-core/src/runtime.rs @@ -43,13 +43,23 @@ mod r#impl { .expect("spawn failed") } + // note: this call does not exist on wasm and you need to handle it + // conditionally at the call site of packages that compile on wasm pub fn block_in_place(f: F) -> R where F: FnOnce() -> R, { + // nosemgrep: ban-raw-block-in-place tokio::task::block_in_place(f) } + // note: this call does not exist on wasm and you need to handle it + // conditionally at the call site of packages that compile on wasm + pub fn block_on(future: F) -> F::Output { + // nosemgrep: ban-raw-block-on + tokio::runtime::Handle::current().block_on(future) + } + pub async fn sleep(duration: Duration) { // nosemgrep: ban-tokio-sleep tokio::time::sleep(duration).await @@ -133,14 +143,6 @@ mod r#impl { spawn(name, future) } - pub fn block_in_place(f: F) -> R - where - F: FnOnce() -> R, - { - // no such hint on wasm - f() - } - pub async fn sleep(duration: Duration) { gloo_timers::future::sleep(duration.min(Duration::from_millis(i32::MAX as _))).await } diff --git a/fedimint-testing/src/btc/real.rs b/fedimint-testing/src/btc/real.rs index 06257e6318d..5ad271d8847 100644 --- a/fedimint-testing/src/btc/real.rs +++ b/fedimint-testing/src/btc/real.rs @@ -9,7 +9,7 @@ use bitcoincore_rpc::{Client, RpcApi}; use fedimint_bitcoind::DynBitcoindRpc; use fedimint_core::encoding::Decodable; use fedimint_core::module::registry::ModuleDecoderRegistry; -use fedimint_core::task::sleep_in_test; +use fedimint_core::task::{block_in_place, sleep_in_test}; use fedimint_core::txoproof::TxOutProof; use fedimint_core::util::SafeUrl; use fedimint_core::{task, Amount}; @@ -187,7 +187,7 @@ pub struct RealBitcoinTestLocked { impl BitcoinTest for RealBitcoinTest { async fn lock_exclusive(&self) -> Box { trace!("Trying to acquire global bitcoin lock"); - let _guard = tokio::task::block_in_place(|| { + let _guard = block_in_place(|| { let lock_file_path = std::env::temp_dir().join("fm-test-bitcoind-lock"); fs_lock::FileLock::new_exclusive( std::fs::OpenOptions::new() diff --git a/fedimint-testing/src/fixtures.rs b/fedimint-testing/src/fixtures.rs index f9b5f87d58f..1c9e2a9f6ad 100644 --- a/fedimint-testing/src/fixtures.rs +++ b/fedimint-testing/src/fixtures.rs @@ -13,6 +13,7 @@ use fedimint_core::config::{ }; use fedimint_core::core::{ModuleInstanceId, ModuleKind}; use fedimint_core::module::{DynServerModuleInit, IServerModuleInit}; +use fedimint_core::runtime::block_in_place; use fedimint_core::task::{MaybeSend, MaybeSync, TaskGroup}; use fedimint_core::util::SafeUrl; use fedimint_logging::{TracingSetup, LOG_TEST}; @@ -138,7 +139,7 @@ impl Fixtures { FederationTest::new( num_peers, num_offline, - tokio::task::block_in_place(|| fedimint_portalloc::port_alloc(num_peers * 2)) + block_in_place(|| fedimint_portalloc::port_alloc(num_peers * 2)) .expect("Failed to allocate a port range"), self.params.clone(), ServerModuleInitRegistry::from(self.servers.clone()), @@ -163,7 +164,7 @@ impl Fixtures { let clients = self.clients.clone().into_iter(); GatewayTest::new( - tokio::task::block_in_place(|| fedimint_portalloc::port_alloc(1)) + block_in_place(|| fedimint_portalloc::port_alloc(1)) .expect("Failed to allocate a port range"), cli_password, ln, diff --git a/fedimint-testing/src/gateway.rs b/fedimint-testing/src/gateway.rs index acb8e6a9600..97850f5c8e3 100644 --- a/fedimint-testing/src/gateway.rs +++ b/fedimint-testing/src/gateway.rs @@ -11,10 +11,9 @@ use fedimint_core::config::FederationId; use fedimint_core::db::mem_impl::MemDatabase; use fedimint_core::db::Database; use fedimint_core::module::registry::ModuleDecoderRegistry; -use fedimint_core::task::{block_in_place, sleep_in_test, TaskGroup}; +use fedimint_core::task::{block_in_place, block_on, sleep_in_test, TaskGroup}; use fedimint_core::util::SafeUrl; use fedimint_logging::LOG_TEST; -use futures::executor::block_on; use lightning_invoice::RoutingFees; use ln_gateway::client::GatewayClientBuilder; use ln_gateway::lightning::{ILnRpcClient, LightningBuilder}; diff --git a/modules/fedimint-wallet-client/Cargo.toml b/modules/fedimint-wallet-client/Cargo.toml index 1492e758852..657da84b731 100644 --- a/modules/fedimint-wallet-client/Cargo.toml +++ b/modules/fedimint-wallet-client/Cargo.toml @@ -22,7 +22,6 @@ async-stream = "0.3.5" async-trait = "0.1.77" bitcoin = { version = "0.29.2", features = [ "rand", "serde"] } erased-serde = "0.4" -fedimint-bitcoind = { version = "=0.3.0-rc.3", path = "../../fedimint-bitcoind", default-features = false, features = ["esplora-client", "bitcoincore-rpc"] } fedimint-client = { version = "=0.3.0-rc.3", path = "../../fedimint-client" } fedimint-core = { version = "=0.3.0-rc.3", path = "../../fedimint-core" } fedimint-wallet-common = { version = "=0.3.0-rc.3", path = "../fedimint-wallet-common" } @@ -41,5 +40,11 @@ tracing ="0.1.40" url = "2.5.0" validator = { version = "0.17", features = ["derive"] } +[target.'cfg(not(target_family = "wasm"))'.dependencies] +fedimint-bitcoind = { version = "=0.3.0-rc.3", path = "../../fedimint-bitcoind", default-features = false, features = ["esplora-client", "bitcoincore-rpc"] } + +[target.'cfg(target_family = "wasm")'.dependencies] +fedimint-bitcoind = { version = "=0.3.0-rc.3", path = "../../fedimint-bitcoind", default-features = false, features = ["esplora-client"] } + [dev-dependencies] tracing-subscriber = { version = "0.3.18", features = [ "env-filter" ] } From 9e9c368203a7d7965b53b6aa3728d8032058439f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dawid=20Ci=C4=99=C5=BCarkiewicz?= Date: Fri, 5 Apr 2024 23:40:58 -0700 Subject: [PATCH 11/18] fix: don't do db ops in `Debug` --- fedimint-client/src/sm/executor.rs | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/fedimint-client/src/sm/executor.rs b/fedimint-client/src/sm/executor.rs index 8435c507c97..8ee9cc87254 100644 --- a/fedimint-client/src/sm/executor.rs +++ b/fedimint-client/src/sm/executor.rs @@ -736,23 +736,7 @@ impl ExecutorInner { impl Debug for ExecutorInner { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - #[cfg(not(target_family = "wasm"))] - let (active, inactive) = fedimint_core::runtime::block_in_place(move || { - fedimint_core::runtime::block_on(async { - let active_states = self.get_active_states().await; - let inactive_states = self.get_inactive_states().await; - - (active_states, inactive_states) - }) - }); - writeln!(f, "ExecutorInner {{")?; - #[cfg(not(target_family = "wasm"))] - writeln!(f, " active_states: {active:?}")?; - #[cfg(not(target_family = "wasm"))] - writeln!(f, " inactive_states: {inactive:?}")?; - writeln!(f, "}}")?; - - Ok(()) + writeln!(f, "ExecutorInner {{}}") } } From 15be5eab603746203dec5c00d87de2f000573104 Mon Sep 17 00:00:00 2001 From: maan2003 Date: Sun, 7 Apr 2024 15:33:56 +0530 Subject: [PATCH 12/18] feat: simplify JitCore (take 2) &mut Future impls Future we don't need to model None case, oneshot::Receiver already does that in case Future completed once. --- fedimint-core/src/runtime.rs | 2 +- fedimint-core/src/task/jit.rs | 128 +++++++++++----------------------- 2 files changed, 41 insertions(+), 89 deletions(-) diff --git a/fedimint-core/src/runtime.rs b/fedimint-core/src/runtime.rs index 1b24eab9b01..abb8306e3b0 100644 --- a/fedimint-core/src/runtime.rs +++ b/fedimint-core/src/runtime.rs @@ -98,7 +98,7 @@ mod r#impl { } impl JoinHandle { - pub fn abort(mut self) { + pub fn abort(&mut self) { drop(self.handle.take()); } } diff --git a/fedimint-core/src/task/jit.rs b/fedimint-core/src/task/jit.rs index 1f30e6336ef..84ba1ef878f 100644 --- a/fedimint-core/src/task/jit.rs +++ b/fedimint-core/src/task/jit.rs @@ -2,11 +2,9 @@ use std::convert::Infallible; use std::fmt; use std::sync::Arc; -use fedimint_logging::LOG_TASK; +use fedimint_core::runtime::JoinHandle; use futures::Future; -use tokio::select; -use tokio::sync::{self, oneshot}; -use tracing::trace; +use tokio::sync; use super::MaybeSend; @@ -51,15 +49,13 @@ where /// A value that initializes eagerly in parallel in a falliable way #[derive(Debug)] pub struct JitCore { - // on last drop it lets the inner task to know it should stop, because we don't care anymore - _cancel_tx: sync::mpsc::Sender<()>, - // since joinhandles, are not portable, we use this to wait for the value - // Note: the `std::sync::Mutex` is used intentionally, since contention never actually happens - // and we want to avoid cancelation because of it - #[allow(clippy::type_complexity)] - val_rx: - Arc>>>>, - val: Arc>, + inner: Arc>, +} + +#[derive(Debug)] +struct JitInner { + handle: sync::Mutex>>, + val: sync::OnceCell>, } impl Clone for JitCore @@ -68,12 +64,15 @@ where { fn clone(&self) -> Self { Self { - _cancel_tx: self._cancel_tx.clone(), - val_rx: self.val_rx.clone(), - val: self.val.clone(), + inner: self.inner.clone(), } } } +impl Drop for JitInner { + fn drop(&mut self) { + self.handle.get_mut().abort(); + } +} impl JitCore where T: MaybeSend + 'static, @@ -87,89 +86,42 @@ where where Fut: Future> + 'static + MaybeSend, { - let (cancel_tx, mut cancel_rx) = tokio::sync::mpsc::channel(1); - let (val_tx, val_rx) = oneshot::channel(); - let type_name = std::any::type_name::(); - crate::runtime::spawn( + let handle = crate::runtime::spawn( &format!("JitTry {} value", std::any::type_name::()), - async move { - select! { - _ = cancel_rx.recv() => { - trace!(target: LOG_TASK, r#type = %type_name, "JitTry value future canceled"); - }, - val = f() => { - match val_tx.send(val) { - Ok(_) => { - trace!(target: LOG_TASK, r#type = %type_name, "JitTry value ready"); - }, - Err(_) => { - trace!(target: LOG_TASK, r#type = %type_name, "JitTry value ready, but ignored"); - }, - }; - }, - } - }, + async move { f().await }, ); Self { - _cancel_tx: cancel_tx, - val_rx: Arc::new(Some(val_rx).into()), - val: sync::OnceCell::new().into(), + inner: JitInner { + handle: handle.into(), + val: sync::OnceCell::new(), + } + .into(), } } /// Get the reference to the value, potentially blocking for the /// initialization future to complete - pub async fn get_try(&self) -> std::result::Result<&T, OneTimeError> { - /// Temporarily taken data out of `arc`, that will be put back on drop, - /// unless canceled - /// - /// Used to achieve cancelation safety. - struct PutBack<'a, T> { - val: Option, - arc: &'a Arc>>, - } - - impl<'a, T> PutBack<'a, T> { - fn take(arc: &'a Arc>>) -> Self { - let val = arc.lock().expect("lock failed").take(); - Self { val, arc } - } - - fn cancel(mut self) { - self.val = None; - } - - fn get_mut(&mut self) -> Option<&mut T> { - self.val.as_mut() - } - } - impl<'a, T> Drop for PutBack<'a, T> { - fn drop(&mut self) { - let mut lock = self.arc.lock().expect("lock failed"); - let take = self.val.take(); - - *lock = take; - } - } - self.val - .get_or_try_init(|| async { - let mut recv = PutBack::take(&self.val_rx); - - let val_res = { - let Some(recv) = recv.get_mut() else { - return Err(OneTimeError(None)); - }; - recv.await.unwrap_or_else(|_| { - panic!("Jit value {} panicked", std::any::type_name::()) + pub async fn get_try(&self) -> Result<&T, OneTimeError> { + let mut init_error = None; + let value = self + .inner + .val + .get_or_init(|| async { + let handle: &mut _ = &mut *self.inner.handle.lock().await; + handle + .await + .unwrap_or_else(|_| panic!("Jit value {} panicked", std::any::type_name::())) + .map_err(|err| { + init_error = Some(err); + // return () }) - }; - - recv.cancel(); - - val_res.map_err(|err| OneTimeError(Some(err))) }) - .await + .await; + if let Some(err) = init_error { + return Err(OneTimeError(Some(err))); + } + value.as_ref().map_err(|_| OneTimeError(None)) } } impl JitCore From 67962072524b7b4d1f6395db22da542a35804043 Mon Sep 17 00:00:00 2001 From: maan2003 Date: Fri, 5 Apr 2024 10:13:46 +0530 Subject: [PATCH 13/18] fix: panic in update_gateway_cache if called concurrently --- fedimint-core/src/util/mod.rs | 1 + fedimint-core/src/util/update_merge.rs | 47 ++++++++++++++++++++++++++ modules/fedimint-ln-client/src/lib.rs | 37 ++++++++++++-------- 3 files changed, 70 insertions(+), 15 deletions(-) create mode 100644 fedimint-core/src/util/update_merge.rs diff --git a/fedimint-core/src/util/mod.rs b/fedimint-core/src/util/mod.rs index f0a01dd5523..b1b5355164e 100644 --- a/fedimint-core/src/util/mod.rs +++ b/fedimint-core/src/util/mod.rs @@ -1,5 +1,6 @@ /// Copied from `tokio_stream` 0.1.12 to use our optional Send bounds pub mod broadcaststream; +pub mod update_merge; use std::convert::Infallible; use std::fmt::{Debug, Display, Formatter}; diff --git a/fedimint-core/src/util/update_merge.rs b/fedimint-core/src/util/update_merge.rs new file mode 100644 index 00000000000..cf28ede6ced --- /dev/null +++ b/fedimint-core/src/util/update_merge.rs @@ -0,0 +1,47 @@ +use futures::Future; +use tokio::sync::Mutex; + +#[derive(Debug)] +pub struct UpdateMerge { + last_failed: Mutex, +} + +impl Default for UpdateMerge { + fn default() -> Self { + UpdateMerge { + last_failed: Mutex::new(false), + } + } +} +impl UpdateMerge { + /// Merges concurrent futures execution. + /// + /// If two `merge` are called concurrently, the calls are merged. + /// But if the first call fails, the second call is still run again. + /// + /// The future `fut` is never executed concurrently. + pub async fn merge(&self, fut: impl Future>) -> Result<(), E> { + let mut guard = if let Ok(guard) = self.last_failed.try_lock() { + // not running => run now + guard + } else { + // already running concurrently + // wait for other call to return + let guard = self.last_failed.lock().await; + match *guard { + // last call completed successfully + // => merge the call + false => return Ok(()), + // last call failed + // => run again + true => guard, + } + }; + // future may panic, use mark as failed initially + *guard = true; + // run the future and save last call status + let result = fut.await; + *guard = result.is_err(); + result + } +} diff --git a/modules/fedimint-ln-client/src/lib.rs b/modules/fedimint-ln-client/src/lib.rs index ed75de039a4..1823fbb1c7d 100644 --- a/modules/fedimint-ln-client/src/lib.rs +++ b/modules/fedimint-ln-client/src/lib.rs @@ -37,6 +37,7 @@ use fedimint_core::module::{ ApiVersion, CommonModuleInit, ModuleCommon, ModuleInit, MultiApiVersion, TransactionItemAmount, }; use fedimint_core::task::{timeout, MaybeSend, MaybeSync}; +use fedimint_core::util::update_merge::UpdateMerge; use fedimint_core::util::{retry, FibonacciBackoff}; use fedimint_core::{ apply, async_trait_maybe_send, push_db_pair_items, runtime, Amount, OutPoint, TransactionId, @@ -361,6 +362,7 @@ pub struct LightningClientModule { module_api: DynModuleApi, preimage_auth: KeyPair, client_ctx: ClientContext, + update_gateway_cache_merge: UpdateMerge, } impl ClientModule for LightningClientModule { @@ -443,6 +445,7 @@ impl LightningClientModule { .to_secp_key(&secp), secp, client_ctx: args.context(), + update_gateway_cache_merge: UpdateMerge::default(), }; // Only initialize the gateway cache if it is empty @@ -890,23 +893,27 @@ impl LightningClientModule { /// /// See also [`Self::update_gateway_cache_continuously`]. pub async fn update_gateway_cache(&self) -> anyhow::Result<()> { - let gateways = self.module_api.fetch_gateways().await?; - let mut dbtx = self.client_ctx.module_db().begin_transaction().await; - - // Remove all previous gateway entries - dbtx.remove_by_prefix(&LightningGatewayKeyPrefix).await; - - for gw in gateways.iter() { - dbtx.insert_entry( - &LightningGatewayKey(gw.info.gateway_id), - &gw.clone().anchor(), - ) - .await; - } + self.update_gateway_cache_merge + .merge(async { + let gateways = self.module_api.fetch_gateways().await?; + let mut dbtx = self.client_ctx.module_db().begin_transaction().await; + + // Remove all previous gateway entries + dbtx.remove_by_prefix(&LightningGatewayKeyPrefix).await; + + for gw in gateways.iter() { + dbtx.insert_entry( + &LightningGatewayKey(gw.info.gateway_id), + &gw.clone().anchor(), + ) + .await; + } - dbtx.commit_tx().await; + dbtx.commit_tx().await; - Ok(()) + Ok(()) + }) + .await } /// Continuously update the gateway cache whenever a gateway expires. From 8d23c6e8b04ea9df4fd8970f2013cb1e4671dad5 Mon Sep 17 00:00:00 2001 From: Brad Stachurski Date: Tue, 2 Apr 2024 23:12:59 +0000 Subject: [PATCH 14/18] fix(devimint): use Version instead of VersionReq for comparisons --- devimint/src/federation.rs | 6 ++-- devimint/src/tests.rs | 59 +++++++++++++++++++------------------- 2 files changed, 32 insertions(+), 33 deletions(-) diff --git a/devimint/src/federation.rs b/devimint/src/federation.rs index f46652efcbf..2ac77373c8c 100644 --- a/devimint/src/federation.rs +++ b/devimint/src/federation.rs @@ -25,7 +25,7 @@ use fedimintd::FM_EXTRA_DKG_META_VAR; use fs_lock::FileLock; use futures::future::join_all; use rand::Rng; -use semver::VersionReq; +use semver::Version; use tokio::time::Instant; use tracing::{debug, info}; @@ -144,7 +144,7 @@ impl Client { // TODO(support:v0.2): remove pub async fn use_gateway(&self, gw: &super::gatewayd::Gatewayd) -> Result<()> { let fedimint_cli_version = crate::util::FedimintCli::version_or_default().await; - if VersionReq::parse("<0.3.0-alpha")?.matches(&fedimint_cli_version) { + if fedimint_cli_version < Version::parse("0.3.0-alpha")? { let gateway_id = gw.gateway_id().await?; cmd!(self, "switch-gateway", gateway_id.clone()) .run() @@ -399,7 +399,7 @@ impl Federation { let start_time = Instant::now(); debug!(target: LOG_DEVIMINT, "Awaiting LN gateways registration"); let fedimint_cli_version = crate::util::FedimintCli::version_or_default().await; - let command = if VersionReq::parse("<0.3.0-alpha")?.matches(&fedimint_cli_version) { + let command = if fedimint_cli_version < Version::parse("0.3.0-alpha")? { "list-gateways" } else { "update-gateway-cache" diff --git a/devimint/src/tests.rs b/devimint/src/tests.rs index 54a42f57feb..70cee865f18 100644 --- a/devimint/src/tests.rs +++ b/devimint/src/tests.rs @@ -17,7 +17,7 @@ use fedimint_core::encoding::Decodable; use fedimint_core::Amount; use fedimint_logging::LOG_DEVIMINT; use ln_gateway::rpc::GatewayInfo; -use semver::VersionReq; +use semver::Version; use serde_json::json; use tokio::fs; use tokio::net::TcpStream; @@ -308,7 +308,7 @@ pub async fn latency_tests(dev_fed: DevFed, r#type: LatencyTest) -> Result<()> { .unwrap(); let fedimint_cli_version = crate::util::FedimintCli::version_or_default().await; let start_time = Instant::now(); - if VersionReq::parse(">=0.3.0-alpha")?.matches(&fedimint_cli_version) { + if fedimint_cli_version >= Version::parse("0.3.0-alpha")? { let restore_client = Client::create("restore").await?; cmd!( restore_client, @@ -420,9 +420,9 @@ pub async fn cli_tests(dev_fed: DevFed) -> Result<()> { let invite = fed.invite_code()?; let fedimint_cli_version = crate::util::FedimintCli::version_or_default().await; - let version_req = VersionReq::parse(">=0.3.0-alpha")?; + let version_req = Version::parse("0.3.0-alpha")?; - let invite_code = if version_req.matches(&fedimint_cli_version) { + let invite_code = if fedimint_cli_version >= version_req { cmd!(client, "dev", "decode", "invite-code", invite.clone()) } else { cmd!(client, "dev", "decode-invite-code", invite.clone()) @@ -430,7 +430,7 @@ pub async fn cli_tests(dev_fed: DevFed) -> Result<()> { .out_json() .await?; - let encode_invite_output = if version_req.matches(&fedimint_cli_version) { + let encode_invite_output = if fedimint_cli_version >= version_req { cmd!( client, "dev", @@ -542,7 +542,7 @@ pub async fn cli_tests(dev_fed: DevFed) -> Result<()> { // The code path is backwards-compatible, however this test will fail if we // check against earlier fedimintd versions. let fedimintd_version = crate::util::FedimintdCmd::version_or_default().await; - if VersionReq::parse(">=0.3.0-alpha")?.matches(&fedimintd_version) { + if fedimintd_version >= Version::parse("0.3.0-alpha")? { // # Test the correct descriptor is used let config = cmd!(client, "config").out_json().await?; let guardian_count = config["global"]["api_endpoints"].as_object().unwrap().len(); @@ -647,23 +647,22 @@ pub async fn cli_tests(dev_fed: DevFed) -> Result<()> { .as_str() .map(|s| s.to_owned()) .unwrap(); - let client_reissue_amt = - if VersionReq::parse(">=0.3.0-alpha")?.matches(&fedimint_cli_version) { - cmd!(client, "module", "mint", "reissue", reissue_notes) - } else { - cmd!( - client, - "module", - "--module", - "mint", - "reissue", - reissue_notes - ) - } - .out_json() - .await? - .as_u64() - .unwrap(); + let client_reissue_amt = if fedimint_cli_version >= Version::parse("0.3.0-alpha")? { + cmd!(client, "module", "mint", "reissue", reissue_notes) + } else { + cmd!( + client, + "module", + "--module", + "mint", + "reissue", + reissue_notes + ) + } + .out_json() + .await? + .as_u64() + .unwrap(); assert_eq!(client_reissue_amt, reissue_amount); // Before doing a normal payment, let's start with a HOLD invoice and only @@ -1252,7 +1251,7 @@ pub async fn cli_tests_backup_and_restore( // Testing restore in different setups would require multiple clients, // which is a larger refactor. { - let post_balance = if VersionReq::parse(">=0.3.0-alpha")?.matches(&fedimint_cli_version) { + let post_balance = if fedimint_cli_version >= Version::parse("0.3.0-alpha")? { let client = Client::create("restore-without-backup").await?; let _ = cmd!( client, @@ -1300,7 +1299,7 @@ pub async fn cli_tests_backup_and_restore( // with a backup { - let post_balance = if VersionReq::parse(">=0.3.0-alpha")?.matches(&fedimint_cli_version) { + let post_balance = if fedimint_cli_version >= Version::parse("0.3.0-alpha")? { let _ = cmd!(reference_client, "backup",).out_json().await?; let client = Client::create("restore-with-backup").await?; @@ -1630,7 +1629,7 @@ async fn ln_pay( // TODO(support:v0.2): 0.3 removed the active gateway concept and requires a // `gateway-id` parameter for lightning sends - let value = if VersionReq::parse("<0.3.0-alpha")?.matches(&fedimint_cli_version) { + let value = if fedimint_cli_version < Version::parse("0.3.0-alpha")? { if finish_in_background { cmd!(client, "ln-pay", invoice, "--finish-in-background",) .out_json() @@ -1671,7 +1670,7 @@ async fn ln_invoice( let fedimint_cli_version = crate::util::FedimintCli::version_or_default().await; // TODO(support:v0.2): 0.3 removed the active gateway concept and requires a // `gateway-id` parameter for lightning receives - let ln_response_val = if VersionReq::parse("<0.3.0-alpha")?.matches(&fedimint_cli_version) { + let ln_response_val = if fedimint_cli_version < Version::parse("0.3.0-alpha")? { cmd!( client, "ln-invoice", @@ -1921,8 +1920,8 @@ pub async fn guardian_backup_test(dev_fed: DevFed, process_mgr: &ProcessManager) let fedimintd_version = crate::util::FedimintdCmd::version_or_default().await; // TODO(support:v0.2): remove - if VersionReq::parse("<0.3.0-alpha")?.matches(&fedimint_cli_version) - || VersionReq::parse("<0.3.0-alpha")?.matches(&fedimintd_version) + if fedimint_cli_version < Version::parse("0.3.0-alpha")? + || fedimintd_version < Version::parse("0.3.0-alpha")? { info!("Guardian backups didn't exist pre-0.3.0, so can't be tested, exiting"); return Ok(()); @@ -2122,7 +2121,7 @@ pub async fn cannot_replay_tx_test(dev_fed: DevFed) -> Result<()> { ); // TODO(support:v0.2): remove - if VersionReq::parse(">=0.3.0-alpha")?.matches(&fedimint_cli_version) { + if fedimint_cli_version >= Version::parse("0.3.0-alpha")? { cmd!(double_spend_client, "reissue", double_spend_notes) .assert_error_contains("The transaction had an invalid input") .await?; From 1dd9488e2c3c71f9e5fc9c2fc0d712669f8be982 Mon Sep 17 00:00:00 2001 From: Brad Stachurski Date: Thu, 4 Apr 2024 15:18:38 +0000 Subject: [PATCH 15/18] refactor(devimint): define version constants --- Cargo.lock | 1 + devimint/Cargo.toml | 1 + devimint/src/federation.rs | 6 +++--- devimint/src/lib.rs | 1 + devimint/src/tests.rs | 27 ++++++++++++--------------- devimint/src/version_constants.rs | 7 +++++++ 6 files changed, 25 insertions(+), 18 deletions(-) create mode 100644 devimint/src/version_constants.rs diff --git a/Cargo.lock b/Cargo.lock index 0abfa60b1fa..b8e9d0b6018 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1067,6 +1067,7 @@ dependencies = [ "fs-lock", "futures", "hex", + "lazy_static", "nix", "rand", "semver", diff --git a/devimint/Cargo.toml b/devimint/Cargo.toml index 776cedcdfbb..d85426d946a 100644 --- a/devimint/Cargo.toml +++ b/devimint/Cargo.toml @@ -34,6 +34,7 @@ fedimint-server = { path = "../fedimint-server" } fedimint-testing = { path = "../fedimint-testing" } futures = "0.3.30" hex = "0.4.3" +lazy_static = "1.4.0" ln-gateway = { package = "fedimint-ln-gateway", path = "../gateway/ln-gateway" } nix = { version = "0.28.0", features = ["signal"] } rand = "0.8.5" diff --git a/devimint/src/federation.rs b/devimint/src/federation.rs index 2ac77373c8c..989603b262f 100644 --- a/devimint/src/federation.rs +++ b/devimint/src/federation.rs @@ -25,7 +25,6 @@ use fedimintd::FM_EXTRA_DKG_META_VAR; use fs_lock::FileLock; use futures::future::join_all; use rand::Rng; -use semver::Version; use tokio::time::Instant; use tracing::{debug, info}; @@ -33,6 +32,7 @@ use super::external::Bitcoind; use super::util::{cmd, parse_map, Command, ProcessHandle, ProcessManager}; use super::vars::utf8; use crate::util::{poll, FedimintdCmd}; +use crate::version_constants::VERSION_0_3_0_ALPHA; use crate::{poll_eq, vars}; #[derive(Clone)] @@ -144,7 +144,7 @@ impl Client { // TODO(support:v0.2): remove pub async fn use_gateway(&self, gw: &super::gatewayd::Gatewayd) -> Result<()> { let fedimint_cli_version = crate::util::FedimintCli::version_or_default().await; - if fedimint_cli_version < Version::parse("0.3.0-alpha")? { + if fedimint_cli_version < *VERSION_0_3_0_ALPHA { let gateway_id = gw.gateway_id().await?; cmd!(self, "switch-gateway", gateway_id.clone()) .run() @@ -399,7 +399,7 @@ impl Federation { let start_time = Instant::now(); debug!(target: LOG_DEVIMINT, "Awaiting LN gateways registration"); let fedimint_cli_version = crate::util::FedimintCli::version_or_default().await; - let command = if fedimint_cli_version < Version::parse("0.3.0-alpha")? { + let command = if fedimint_cli_version < *VERSION_0_3_0_ALPHA { "list-gateways" } else { "update-gateway-cache" diff --git a/devimint/src/lib.rs b/devimint/src/lib.rs index f11293dc9b5..6a7a6c3033a 100644 --- a/devimint/src/lib.rs +++ b/devimint/src/lib.rs @@ -13,3 +13,4 @@ pub mod gatewayd; pub mod tests; pub mod util; pub mod vars; +pub mod version_constants; diff --git a/devimint/src/tests.rs b/devimint/src/tests.rs index 70cee865f18..3c57dc547ea 100644 --- a/devimint/src/tests.rs +++ b/devimint/src/tests.rs @@ -17,7 +17,6 @@ use fedimint_core::encoding::Decodable; use fedimint_core::Amount; use fedimint_logging::LOG_DEVIMINT; use ln_gateway::rpc::GatewayInfo; -use semver::Version; use serde_json::json; use tokio::fs; use tokio::net::TcpStream; @@ -27,6 +26,7 @@ use tracing::{debug, info}; use crate::cli::{cleanup_on_exit, exec_user_command, setup, write_ready_file, CommonArgs}; use crate::federation::{Client, Federation}; use crate::util::{poll, poll_with_timeout, LoadTestTool, ProcessManager}; +use crate::version_constants::VERSION_0_3_0_ALPHA; use crate::{cmd, dev_fed, poll_eq, DevFed, Gatewayd, LightningNode, Lightningd, Lnd}; pub struct Stats { @@ -308,7 +308,7 @@ pub async fn latency_tests(dev_fed: DevFed, r#type: LatencyTest) -> Result<()> { .unwrap(); let fedimint_cli_version = crate::util::FedimintCli::version_or_default().await; let start_time = Instant::now(); - if fedimint_cli_version >= Version::parse("0.3.0-alpha")? { + if fedimint_cli_version >= *VERSION_0_3_0_ALPHA { let restore_client = Client::create("restore").await?; cmd!( restore_client, @@ -420,9 +420,8 @@ pub async fn cli_tests(dev_fed: DevFed) -> Result<()> { let invite = fed.invite_code()?; let fedimint_cli_version = crate::util::FedimintCli::version_or_default().await; - let version_req = Version::parse("0.3.0-alpha")?; - let invite_code = if fedimint_cli_version >= version_req { + let invite_code = if fedimint_cli_version >= *VERSION_0_3_0_ALPHA { cmd!(client, "dev", "decode", "invite-code", invite.clone()) } else { cmd!(client, "dev", "decode-invite-code", invite.clone()) @@ -430,7 +429,7 @@ pub async fn cli_tests(dev_fed: DevFed) -> Result<()> { .out_json() .await?; - let encode_invite_output = if fedimint_cli_version >= version_req { + let encode_invite_output = if fedimint_cli_version >= *VERSION_0_3_0_ALPHA { cmd!( client, "dev", @@ -542,7 +541,7 @@ pub async fn cli_tests(dev_fed: DevFed) -> Result<()> { // The code path is backwards-compatible, however this test will fail if we // check against earlier fedimintd versions. let fedimintd_version = crate::util::FedimintdCmd::version_or_default().await; - if fedimintd_version >= Version::parse("0.3.0-alpha")? { + if fedimintd_version >= *VERSION_0_3_0_ALPHA { // # Test the correct descriptor is used let config = cmd!(client, "config").out_json().await?; let guardian_count = config["global"]["api_endpoints"].as_object().unwrap().len(); @@ -647,7 +646,7 @@ pub async fn cli_tests(dev_fed: DevFed) -> Result<()> { .as_str() .map(|s| s.to_owned()) .unwrap(); - let client_reissue_amt = if fedimint_cli_version >= Version::parse("0.3.0-alpha")? { + let client_reissue_amt = if fedimint_cli_version >= *VERSION_0_3_0_ALPHA { cmd!(client, "module", "mint", "reissue", reissue_notes) } else { cmd!( @@ -1251,7 +1250,7 @@ pub async fn cli_tests_backup_and_restore( // Testing restore in different setups would require multiple clients, // which is a larger refactor. { - let post_balance = if fedimint_cli_version >= Version::parse("0.3.0-alpha")? { + let post_balance = if fedimint_cli_version >= *VERSION_0_3_0_ALPHA { let client = Client::create("restore-without-backup").await?; let _ = cmd!( client, @@ -1299,7 +1298,7 @@ pub async fn cli_tests_backup_and_restore( // with a backup { - let post_balance = if fedimint_cli_version >= Version::parse("0.3.0-alpha")? { + let post_balance = if fedimint_cli_version >= *VERSION_0_3_0_ALPHA { let _ = cmd!(reference_client, "backup",).out_json().await?; let client = Client::create("restore-with-backup").await?; @@ -1629,7 +1628,7 @@ async fn ln_pay( // TODO(support:v0.2): 0.3 removed the active gateway concept and requires a // `gateway-id` parameter for lightning sends - let value = if fedimint_cli_version < Version::parse("0.3.0-alpha")? { + let value = if fedimint_cli_version < *VERSION_0_3_0_ALPHA { if finish_in_background { cmd!(client, "ln-pay", invoice, "--finish-in-background",) .out_json() @@ -1670,7 +1669,7 @@ async fn ln_invoice( let fedimint_cli_version = crate::util::FedimintCli::version_or_default().await; // TODO(support:v0.2): 0.3 removed the active gateway concept and requires a // `gateway-id` parameter for lightning receives - let ln_response_val = if fedimint_cli_version < Version::parse("0.3.0-alpha")? { + let ln_response_val = if fedimint_cli_version < *VERSION_0_3_0_ALPHA { cmd!( client, "ln-invoice", @@ -1920,9 +1919,7 @@ pub async fn guardian_backup_test(dev_fed: DevFed, process_mgr: &ProcessManager) let fedimintd_version = crate::util::FedimintdCmd::version_or_default().await; // TODO(support:v0.2): remove - if fedimint_cli_version < Version::parse("0.3.0-alpha")? - || fedimintd_version < Version::parse("0.3.0-alpha")? - { + if fedimint_cli_version < *VERSION_0_3_0_ALPHA || fedimintd_version < *VERSION_0_3_0_ALPHA { info!("Guardian backups didn't exist pre-0.3.0, so can't be tested, exiting"); return Ok(()); } @@ -2121,7 +2118,7 @@ pub async fn cannot_replay_tx_test(dev_fed: DevFed) -> Result<()> { ); // TODO(support:v0.2): remove - if fedimint_cli_version >= Version::parse("0.3.0-alpha")? { + if fedimint_cli_version >= *VERSION_0_3_0_ALPHA { cmd!(double_spend_client, "reissue", double_spend_notes) .assert_error_contains("The transaction had an invalid input") .await?; diff --git a/devimint/src/version_constants.rs b/devimint/src/version_constants.rs new file mode 100644 index 00000000000..aa29014fdae --- /dev/null +++ b/devimint/src/version_constants.rs @@ -0,0 +1,7 @@ +use lazy_static::lazy_static; +use semver::Version; + +lazy_static! { + pub static ref VERSION_0_3_0_ALPHA: Version = + Version::parse("0.3.0-alpha").expect("version is parsable"); +} From 6d7771c3cadc295c9d1e38a8367a3cfc07ad12bb Mon Sep 17 00:00:00 2001 From: maan2003 Date: Tue, 9 Apr 2024 11:13:36 +0530 Subject: [PATCH 16/18] chore: bump version to 0.3.1-rc.0 --- Cargo.lock | 100 ++++++++++----------- Cargo.toml | 2 +- crypto/aead/Cargo.toml | 2 +- crypto/derive-secret/Cargo.toml | 8 +- crypto/hkdf/Cargo.toml | 2 +- crypto/tbs/Cargo.toml | 2 +- devimint/Cargo.toml | 4 +- fedimint-bip39/Cargo.toml | 6 +- fedimint-bitcoind/Cargo.toml | 6 +- fedimint-build/Cargo.toml | 2 +- fedimint-cli/Cargo.toml | 32 +++---- fedimint-client/Cargo.toml | 12 +-- fedimint-core/Cargo.toml | 8 +- fedimint-dbtool/Cargo.toml | 30 +++---- fedimint-derive/Cargo.toml | 2 +- fedimint-load-test-tool/Cargo.toml | 20 ++--- fedimint-logging/Cargo.toml | 2 +- fedimint-metrics/Cargo.toml | 4 +- fedimint-rocksdb/Cargo.toml | 4 +- fedimint-server/Cargo.toml | 14 +-- fedimint-testing/Cargo.toml | 18 ++-- fedimint-wasm-tests/Cargo.toml | 2 +- fedimintd/Cargo.toml | 34 +++---- fuzz/Cargo.toml | 4 +- gateway/cli/Cargo.toml | 10 +-- gateway/ln-gateway/Cargo.toml | 22 ++--- modules/fedimint-dummy-client/Cargo.toml | 8 +- modules/fedimint-dummy-common/Cargo.toml | 4 +- modules/fedimint-dummy-server/Cargo.toml | 6 +- modules/fedimint-dummy-tests/Cargo.toml | 2 +- modules/fedimint-empty-client/Cargo.toml | 8 +- modules/fedimint-empty-common/Cargo.toml | 4 +- modules/fedimint-empty-server/Cargo.toml | 6 +- modules/fedimint-ln-client/Cargo.toml | 8 +- modules/fedimint-ln-common/Cargo.toml | 6 +- modules/fedimint-ln-server/Cargo.toml | 12 +-- modules/fedimint-ln-tests/Cargo.toml | 2 +- modules/fedimint-meta-client/Cargo.toml | 8 +- modules/fedimint-meta-common/Cargo.toml | 4 +- modules/fedimint-meta-server/Cargo.toml | 8 +- modules/fedimint-mint-client/Cargo.toml | 14 +-- modules/fedimint-mint-common/Cargo.toml | 6 +- modules/fedimint-mint-server/Cargo.toml | 12 +-- modules/fedimint-mint-tests/Cargo.toml | 4 +- modules/fedimint-unknown-common/Cargo.toml | 4 +- modules/fedimint-unknown-server/Cargo.toml | 6 +- modules/fedimint-wallet-client/Cargo.toml | 12 +-- modules/fedimint-wallet-common/Cargo.toml | 4 +- modules/fedimint-wallet-server/Cargo.toml | 12 +-- modules/fedimint-wallet-tests/Cargo.toml | 2 +- recoverytool/Cargo.toml | 20 ++--- utils/portalloc/Cargo.toml | 4 +- 52 files changed, 269 insertions(+), 269 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b8e9d0b6018..8d19fa79cfe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1038,7 +1038,7 @@ dependencies = [ [[package]] name = "devimint" -version = "0.3.0-rc.2" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "axum 0.7.4", @@ -1263,7 +1263,7 @@ checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "fedimint-aead" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "argon2", @@ -1295,7 +1295,7 @@ dependencies = [ [[package]] name = "fedimint-bip39" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "bip39", "fedimint-client", @@ -1305,7 +1305,7 @@ dependencies = [ [[package]] name = "fedimint-bitcoind" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "async-trait", @@ -1326,14 +1326,14 @@ dependencies = [ [[package]] name = "fedimint-build" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "serde_json", ] [[package]] name = "fedimint-cli" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "async-trait", @@ -1377,7 +1377,7 @@ dependencies = [ [[package]] name = "fedimint-client" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "aquamarine", @@ -1427,7 +1427,7 @@ dependencies = [ [[package]] name = "fedimint-core" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "async-lock", @@ -1484,7 +1484,7 @@ dependencies = [ [[package]] name = "fedimint-dbtool" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "bitcoin_hashes 0.11.0", @@ -1517,7 +1517,7 @@ dependencies = [ [[package]] name = "fedimint-derive" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "itertools 0.12.1", "proc-macro2", @@ -1527,7 +1527,7 @@ dependencies = [ [[package]] name = "fedimint-derive-secret" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "fedimint-core", @@ -1539,7 +1539,7 @@ dependencies = [ [[package]] name = "fedimint-dummy-client" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "async-trait", @@ -1560,7 +1560,7 @@ dependencies = [ [[package]] name = "fedimint-dummy-common" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "async-trait", @@ -1580,7 +1580,7 @@ dependencies = [ [[package]] name = "fedimint-dummy-server" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "async-trait", @@ -1601,7 +1601,7 @@ dependencies = [ [[package]] name = "fedimint-dummy-tests" -version = "0.3.0-rc.2" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "fedimint-client", @@ -1624,7 +1624,7 @@ dependencies = [ [[package]] name = "fedimint-empty-client" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "async-trait", @@ -1642,7 +1642,7 @@ dependencies = [ [[package]] name = "fedimint-empty-common" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "async-trait", @@ -1658,7 +1658,7 @@ dependencies = [ [[package]] name = "fedimint-empty-server" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "async-trait", @@ -1675,7 +1675,7 @@ dependencies = [ [[package]] name = "fedimint-fuzz" -version = "0.3.0-rc.2" +version = "0.3.1-rc.0" dependencies = [ "fedimint-core", "honggfuzz", @@ -1683,7 +1683,7 @@ dependencies = [ [[package]] name = "fedimint-gateway-cli" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "async-trait", @@ -1706,14 +1706,14 @@ dependencies = [ [[package]] name = "fedimint-hkdf" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "bitcoin_hashes 0.11.0", ] [[package]] name = "fedimint-ln-client" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "aquamarine", @@ -1747,7 +1747,7 @@ dependencies = [ [[package]] name = "fedimint-ln-common" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "aquamarine", @@ -1778,7 +1778,7 @@ dependencies = [ [[package]] name = "fedimint-ln-gateway" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "aquamarine", @@ -1835,7 +1835,7 @@ dependencies = [ [[package]] name = "fedimint-ln-server" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "assert_matches", @@ -1869,7 +1869,7 @@ dependencies = [ [[package]] name = "fedimint-ln-tests" -version = "0.3.0-rc.2" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "assert_matches", @@ -1901,7 +1901,7 @@ dependencies = [ [[package]] name = "fedimint-load-test-tool" -version = "0.3.0-rc.2" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "base64 0.22.0", @@ -1932,7 +1932,7 @@ dependencies = [ [[package]] name = "fedimint-logging" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "console-subscriber", @@ -1945,7 +1945,7 @@ dependencies = [ [[package]] name = "fedimint-meta-client" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "async-trait", @@ -1969,7 +1969,7 @@ dependencies = [ [[package]] name = "fedimint-meta-common" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "async-trait", @@ -1991,7 +1991,7 @@ dependencies = [ [[package]] name = "fedimint-meta-server" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "async-trait", @@ -2013,7 +2013,7 @@ dependencies = [ [[package]] name = "fedimint-metrics" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "axum 0.7.4", @@ -2026,7 +2026,7 @@ dependencies = [ [[package]] name = "fedimint-mint-client" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "aquamarine", @@ -2062,7 +2062,7 @@ dependencies = [ [[package]] name = "fedimint-mint-common" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "async-trait", @@ -2086,7 +2086,7 @@ dependencies = [ [[package]] name = "fedimint-mint-server" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "assert_matches", @@ -2117,7 +2117,7 @@ dependencies = [ [[package]] name = "fedimint-mint-tests" -version = "0.3.0-rc.2" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "bitcoin_hashes 0.11.0", @@ -2147,7 +2147,7 @@ dependencies = [ [[package]] name = "fedimint-portalloc" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "dirs", @@ -2161,7 +2161,7 @@ dependencies = [ [[package]] name = "fedimint-recoverytool" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "bitcoin 0.29.2", @@ -2188,7 +2188,7 @@ dependencies = [ [[package]] name = "fedimint-rocksdb" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "async-trait", @@ -2203,7 +2203,7 @@ dependencies = [ [[package]] name = "fedimint-server" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "aleph-bft-types", "anyhow", @@ -2259,7 +2259,7 @@ dependencies = [ [[package]] name = "fedimint-tbs" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "bitcoin_hashes 0.11.0", "bls12_381", @@ -2273,7 +2273,7 @@ dependencies = [ [[package]] name = "fedimint-testing" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "async-stream", @@ -2351,7 +2351,7 @@ dependencies = [ [[package]] name = "fedimint-unknown-common" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "async-trait", @@ -2367,7 +2367,7 @@ dependencies = [ [[package]] name = "fedimint-unknown-server" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "async-trait", @@ -2386,7 +2386,7 @@ dependencies = [ [[package]] name = "fedimint-wallet-client" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "aquamarine", @@ -2417,7 +2417,7 @@ dependencies = [ [[package]] name = "fedimint-wallet-common" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "async-trait", @@ -2444,7 +2444,7 @@ dependencies = [ [[package]] name = "fedimint-wallet-server" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "async-trait", @@ -2474,7 +2474,7 @@ dependencies = [ [[package]] name = "fedimint-wallet-tests" -version = "0.3.0-rc.2" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "assert_matches", @@ -2505,7 +2505,7 @@ dependencies = [ [[package]] name = "fedimint-wasm-tests" -version = "0.0.0" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "fedimint-client", @@ -2527,7 +2527,7 @@ dependencies = [ [[package]] name = "fedimintd" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" dependencies = [ "anyhow", "async-trait", diff --git a/Cargo.toml b/Cargo.toml index f408f4da5e5..ac2c5060e8f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,7 +55,7 @@ resolver = "2" [workspace.package] name = "fedimint" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" [workspace.metadata] name = "fedimint" diff --git a/crypto/aead/Cargo.toml b/crypto/aead/Cargo.toml index 0f87267f971..34782e1baa5 100644 --- a/crypto/aead/Cargo.toml +++ b/crypto/aead/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-aead" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "aead utilities on top of ring" diff --git a/crypto/derive-secret/Cargo.toml b/crypto/derive-secret/Cargo.toml index 196f70177ca..a912c23c7d3 100644 --- a/crypto/derive-secret/Cargo.toml +++ b/crypto/derive-secret/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-derive-secret" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "Fedimint derivable secret implementation" @@ -19,8 +19,8 @@ path = "src/lib.rs" [dependencies] anyhow = "1.0.81" -fedimint-core = { version = "=0.3.0-rc.3", path = "../../fedimint-core" } -hkdf = { package = "fedimint-hkdf", version = "=0.3.0-rc.3", path = "../../crypto/hkdf" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../../fedimint-core" } +hkdf = { package = "fedimint-hkdf", version = "=0.3.1-rc.0", path = "../../crypto/hkdf" } ring = "0.17.8" secp256k1-zkp = { version = "0.7.0", features = [ "serde", "bitcoin_hashes" ] } -tbs = { package = "fedimint-tbs", version = "=0.3.0-rc.3", path = "../../crypto/tbs" } +tbs = { package = "fedimint-tbs", version = "=0.3.1-rc.0", path = "../../crypto/tbs" } diff --git a/crypto/hkdf/Cargo.toml b/crypto/hkdf/Cargo.toml index b15be6d793d..22920c8563b 100644 --- a/crypto/hkdf/Cargo.toml +++ b/crypto/hkdf/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-hkdf" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "RFC5869 HKDF implementation on top of bitcoin_hashes" diff --git a/crypto/tbs/Cargo.toml b/crypto/tbs/Cargo.toml index 3af5df182d0..1ff521ebb2e 100644 --- a/crypto/tbs/Cargo.toml +++ b/crypto/tbs/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-tbs" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "tbs is a helper cryptography library for threshold blind signatures" diff --git a/devimint/Cargo.toml b/devimint/Cargo.toml index d85426d946a..1164f46f597 100644 --- a/devimint/Cargo.toml +++ b/devimint/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "devimint" -version = "0.3.0-rc.2" +version = "0.3.1-rc.0" edition = "2021" license = "MIT" publish = false @@ -51,4 +51,4 @@ fedimint-portalloc = { path = "../utils/portalloc" } fs-lock = "0.1.3" [build-dependencies] -fedimint-build = { version = "=0.3.0-rc.3", path = "../fedimint-build" } +fedimint-build = { version = "=0.3.1-rc.0", path = "../fedimint-build" } diff --git a/fedimint-bip39/Cargo.toml b/fedimint-bip39/Cargo.toml index fc8328e7ddd..fe582a5476b 100644 --- a/fedimint-bip39/Cargo.toml +++ b/fedimint-bip39/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-bip39" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" edition = "2021" license = "MIT" readme = "../README.md" @@ -18,6 +18,6 @@ path = "./src/lib.rs" [dependencies] bip39 = { version = "2.0.0", features = ["rand"] } -fedimint-client = { version = "=0.3.0-rc.3", path = "../fedimint-client" } -fedimint-core = { version = "=0.3.0-rc.3", path = "../fedimint-core" } +fedimint-client = { version = "=0.3.1-rc.0", path = "../fedimint-client" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../fedimint-core" } rand = "0.8.5" diff --git a/fedimint-bitcoind/Cargo.toml b/fedimint-bitcoind/Cargo.toml index d94dffdf24e..639531cc7c5 100644 --- a/fedimint-bitcoind/Cargo.toml +++ b/fedimint-bitcoind/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-bitcoind" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "Bitcoin Core connectivity used by Fedimint" @@ -25,8 +25,8 @@ bitcoincore-rpc = { version = "0.16.0", optional = true } electrum-client = {version = "0.12.1", optional = true } esplora-client = { version = "0.5.0", default-features = false, features = ["async", "async-https-rustls"], optional = true } lazy_static = "1.4.0" -fedimint-core = { version = "=0.3.0-rc.3", path = "../fedimint-core" } -fedimint-logging = { version = "=0.3.0-rc.3", path = "../fedimint-logging" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../fedimint-core" } +fedimint-logging = { version = "=0.3.1-rc.0", path = "../fedimint-logging" } rand = "0.8" serde = { version = "1.0.197", features = [ "derive" ] } serde_json = "1.0.114" diff --git a/fedimint-build/Cargo.toml b/fedimint-build/Cargo.toml index a30988dc9be..836dd16df18 100644 --- a/fedimint-build/Cargo.toml +++ b/fedimint-build/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-build" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "Fedimint build script utilities for including git version information in builds" diff --git a/fedimint-cli/Cargo.toml b/fedimint-cli/Cargo.toml index 89cfe4c85ed..bd8a176336b 100644 --- a/fedimint-cli/Cargo.toml +++ b/fedimint-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-cli" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimint-cli is a command line interface wrapper for the client library." @@ -32,20 +32,20 @@ clap = { version = "4.5.2", features = ["derive", "std", "help", "usage", "error futures = "0.3.30" itertools = "0.12.1" lightning-invoice = { version = "0.26.0", features = [ "serde" ] } -fedimint-aead = { version = "=0.3.0-rc.3", path = "../crypto/aead" } -fedimint-bip39 = { version = "=0.3.0-rc.3", path = "../fedimint-bip39" } -fedimint-client = { version = "=0.3.0-rc.3", path = "../fedimint-client" } -fedimint-core = { version = "=0.3.0-rc.3", path = "../fedimint-core" } -fedimint-rocksdb = { version = "=0.3.0-rc.3", path = "../fedimint-rocksdb" } -fedimint-mint-client = { version = "=0.3.0-rc.3", path = "../modules/fedimint-mint-client" } -fedimint-mint-common = { version = "=0.3.0-rc.3", path = "../modules/fedimint-mint-common" } -fedimint-ln-client = { version = "=0.3.0-rc.3", path = "../modules/fedimint-ln-client" } -fedimint-ln-common = { version = "=0.3.0-rc.3", path = "../modules/fedimint-ln-common" } -fedimint-wallet-client = { version = "=0.3.0-rc.3", path = "../modules/fedimint-wallet-client" } -fedimint-logging = { version = "=0.3.0-rc.3", path = "../fedimint-logging" } -fedimint-server = { version = "=0.3.0-rc.3", path = "../fedimint-server" } -fedimint-meta-client = { version = "=0.3.0-rc.3", path = "../modules/fedimint-meta-client", features = [ "cli" ] } -fedimint-meta-common = { version = "=0.3.0-rc.3", path = "../modules/fedimint-meta-common" } +fedimint-aead = { version = "=0.3.1-rc.0", path = "../crypto/aead" } +fedimint-bip39 = { version = "=0.3.1-rc.0", path = "../fedimint-bip39" } +fedimint-client = { version = "=0.3.1-rc.0", path = "../fedimint-client" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../fedimint-core" } +fedimint-rocksdb = { version = "=0.3.1-rc.0", path = "../fedimint-rocksdb" } +fedimint-mint-client = { version = "=0.3.1-rc.0", path = "../modules/fedimint-mint-client" } +fedimint-mint-common = { version = "=0.3.1-rc.0", path = "../modules/fedimint-mint-common" } +fedimint-ln-client = { version = "=0.3.1-rc.0", path = "../modules/fedimint-ln-client" } +fedimint-ln-common = { version = "=0.3.1-rc.0", path = "../modules/fedimint-ln-common" } +fedimint-wallet-client = { version = "=0.3.1-rc.0", path = "../modules/fedimint-wallet-client" } +fedimint-logging = { version = "=0.3.1-rc.0", path = "../fedimint-logging" } +fedimint-server = { version = "=0.3.1-rc.0", path = "../fedimint-server" } +fedimint-meta-client = { version = "=0.3.1-rc.0", path = "../modules/fedimint-meta-client", features = [ "cli" ] } +fedimint-meta-common = { version = "=0.3.1-rc.0", path = "../modules/fedimint-meta-common" } fs-lock = "0.1.3" rand = "0.8" serde = { version = "1.0.197", features = [ "derive" ] } @@ -60,4 +60,4 @@ lnurl-rs = { version = "0.4.1", features = ["async"], default-features = false } reqwest = { version = "0.11.26", features = [ "json", "rustls-tls" ], default-features = false } [build-dependencies] -fedimint-build = { version = "=0.3.0-rc.3", path = "../fedimint-build" } +fedimint-build = { version = "=0.3.1-rc.0", path = "../fedimint-build" } diff --git a/fedimint-client/Cargo.toml b/fedimint-client/Cargo.toml index 4fbc37c6a00..83273dc14fa 100644 --- a/fedimint-client/Cargo.toml +++ b/fedimint-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-client" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimint-client provides a library for sending transactions to the federation." @@ -26,10 +26,10 @@ async-stream = "0.3.5" async-trait = "0.1.77" bitcoin = "0.29.2" bitcoin_hashes = "0.11.0" -fedimint-core = { version = "=0.3.0-rc.3", path = "../fedimint-core/" } -fedimint-derive-secret = { version = "=0.3.0-rc.3", path = "../crypto/derive-secret" } -fedimint-aead = { version = "=0.3.0-rc.3", path = "../crypto/aead" } -fedimint-logging = { version = "=0.3.0-rc.3", path = "../fedimint-logging" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../fedimint-core/" } +fedimint-derive-secret = { version = "=0.3.1-rc.0", path = "../crypto/derive-secret" } +fedimint-aead = { version = "=0.3.1-rc.0", path = "../crypto/aead" } +fedimint-logging = { version = "=0.3.1-rc.0", path = "../fedimint-logging" } futures = "0.3.30" itertools = "0.12.1" rand = "0.8.5" @@ -51,4 +51,4 @@ ring = { version = "0.17.8", features = ["wasm32_unknown_unknown_js"] } tracing-test = "0.2.4" [build-dependencies] -fedimint-build = { version = "=0.3.0-rc.3", path = "../fedimint-build" } +fedimint-build = { version = "=0.3.1-rc.0", path = "../fedimint-build" } diff --git a/fedimint-core/Cargo.toml b/fedimint-core/Cargo.toml index 923bb37e08b..1d9282757b1 100644 --- a/fedimint-core/Cargo.toml +++ b/fedimint-core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-core" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimint-core provides common code used by both client and server." @@ -33,7 +33,7 @@ strum = "0.26" strum_macros = "0.26" hex = { version = "0.4.3", features = [ "serde"] } sha3 = "0.10.8" -tbs = { package = "fedimint-tbs", version = "=0.3.0-rc.3", path = "../crypto/tbs" } +tbs = { package = "fedimint-tbs", version = "=0.3.1-rc.0", path = "../crypto/tbs" } tokio = { version = "1.36.0", features = ["sync", "io-util"] } thiserror = "1.0.58" tracing ="0.1.40" @@ -45,8 +45,8 @@ bitcoin_hashes = { version = "0.11", features = ["serde"] } erased-serde = "0.4" lightning = "0.0.118" lightning-invoice = "0.26.0" -fedimint-derive = { version = "=0.3.0-rc.3", path = "../fedimint-derive" } -fedimint-logging = { version = "=0.3.0-rc.3", path = "../fedimint-logging" } +fedimint-derive = { version = "=0.3.1-rc.0", path = "../fedimint-derive" } +fedimint-logging = { version = "=0.3.1-rc.0", path = "../fedimint-logging" } rand = "0.8.5" miniscript = { version = "10.0.0", features = [ "compiler", "serde" ] } secp256k1-zkp = { version = "0.7.0", features = [ "use-serde", "bitcoin_hashes", "global-context" ] } diff --git a/fedimint-dbtool/Cargo.toml b/fedimint-dbtool/Cargo.toml index 8f1602546e2..b5eeb1f5631 100644 --- a/fedimint-dbtool/Cargo.toml +++ b/fedimint-dbtool/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-dbtool" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" edition = "2021" license = "MIT" readme = "README.md" @@ -18,25 +18,25 @@ name = "fedimint-dbtool" [dependencies] anyhow = "1.0.81" -fedimint-aead = { version = "=0.3.0-rc.3", path = "../crypto/aead" } +fedimint-aead = { version = "=0.3.1-rc.0", path = "../crypto/aead" } bitcoin_hashes = "0.11.0" bytes = "1.5.0" clap = { version = "4.5.2", features = ["derive", "env"] } -fedimint-core = { version = "=0.3.0-rc.3", path = "../fedimint-core" } -fedimint-client = { version = "=0.3.0-rc.3", path = "../fedimint-client" } -fedimint-server = { version = "=0.3.0-rc.3", path = "../fedimint-server" } -fedimint-rocksdb = { version = "=0.3.0-rc.3", path = "../fedimint-rocksdb" } -fedimint-mint-server = { version = "=0.3.0-rc.3", path = "../modules/fedimint-mint-server" } -fedimint-mint-client = { version = "=0.3.0-rc.3", path = "../modules/fedimint-mint-client" } -fedimint-ln-server = { version = "=0.3.0-rc.3", path = "../modules/fedimint-ln-server" } -fedimint-ln-client = { version = "=0.3.0-rc.3", path = "../modules/fedimint-ln-client" } -fedimint-logging = { version = "=0.3.0-rc.3", path = "../fedimint-logging" } -fedimint-wallet-server = { version = "=0.3.0-rc.3", path = "../modules/fedimint-wallet-server" } -fedimint-wallet-client = { version = "=0.3.0-rc.3", path = "../modules/fedimint-wallet-client" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../fedimint-core" } +fedimint-client = { version = "=0.3.1-rc.0", path = "../fedimint-client" } +fedimint-server = { version = "=0.3.1-rc.0", path = "../fedimint-server" } +fedimint-rocksdb = { version = "=0.3.1-rc.0", path = "../fedimint-rocksdb" } +fedimint-mint-server = { version = "=0.3.1-rc.0", path = "../modules/fedimint-mint-server" } +fedimint-mint-client = { version = "=0.3.1-rc.0", path = "../modules/fedimint-mint-client" } +fedimint-ln-server = { version = "=0.3.1-rc.0", path = "../modules/fedimint-ln-server" } +fedimint-ln-client = { version = "=0.3.1-rc.0", path = "../modules/fedimint-ln-client" } +fedimint-logging = { version = "=0.3.1-rc.0", path = "../fedimint-logging" } +fedimint-wallet-server = { version = "=0.3.1-rc.0", path = "../modules/fedimint-wallet-server" } +fedimint-wallet-client = { version = "=0.3.1-rc.0", path = "../modules/fedimint-wallet-client" } futures = "0.3.30" erased-serde = "0.4" hex = { version = "0.4.3", features = ["serde"] } -ln-gateway = { package = "fedimint-ln-gateway", version = "=0.3.0-rc.3", path = "../gateway/ln-gateway" } +ln-gateway = { package = "fedimint-ln-gateway", version = "=0.3.1-rc.0", path = "../gateway/ln-gateway" } serde = { version = "1.0.197", features = ["derive"] } serde_json = "1.0.114" strum = "0.26" @@ -45,4 +45,4 @@ tokio = "1.36.0" tracing = "0.1.40" [build-dependencies] -fedimint-build = { version = "=0.3.0-rc.3", path = "../fedimint-build" } +fedimint-build = { version = "=0.3.1-rc.0", path = "../fedimint-build" } diff --git a/fedimint-derive/Cargo.toml b/fedimint-derive/Cargo.toml index 629ccb642f5..58be20008e0 100644 --- a/fedimint-derive/Cargo.toml +++ b/fedimint-derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-derive" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimint-derive provides helper macros for serialization." diff --git a/fedimint-load-test-tool/Cargo.toml b/fedimint-load-test-tool/Cargo.toml index 698dcc7357c..ef95d9ff1f3 100644 --- a/fedimint-load-test-tool/Cargo.toml +++ b/fedimint-load-test-tool/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-load-test-tool" -version = "0.3.0-rc.2" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimint-load-test-tool is a tool to load test the fedimint server and gateway." @@ -16,15 +16,15 @@ anyhow = "1" base64 = "0.22.0" bitcoin = "0.29.2" clap = { version = "4.5.2", features = ["derive", "std", "help", "usage", "error-context", "suggestions", "env" ], default-features = false } -devimint = { version = "0.3.0-rc.2", path = "../devimint" } -fedimint-client = { version = "=0.3.0-rc.3", path = "../fedimint-client" } -fedimint-core = { version = "=0.3.0-rc.3", path = "../fedimint-core" } -fedimint-ln-client = { version = "=0.3.0-rc.3", path = "../modules/fedimint-ln-client" } +devimint = { version = "0.3.1-rc.0", path = "../devimint" } +fedimint-client = { version = "=0.3.1-rc.0", path = "../fedimint-client" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../fedimint-core" } +fedimint-ln-client = { version = "=0.3.1-rc.0", path = "../modules/fedimint-ln-client" } fedimint-ln-common = { path = "../modules/fedimint-ln-common" } -fedimint-logging = { version = "=0.3.0-rc.3", path = "../fedimint-logging" } -fedimint-mint-client = { version = "=0.3.0-rc.3", path = "../modules/fedimint-mint-client" } -fedimint-rocksdb = { version = "=0.3.0-rc.3", path = "../fedimint-rocksdb" } -fedimint-wallet-client = { version = "=0.3.0-rc.3", path = "../modules/fedimint-wallet-client" } +fedimint-logging = { version = "=0.3.1-rc.0", path = "../fedimint-logging" } +fedimint-mint-client = { version = "=0.3.1-rc.0", path = "../modules/fedimint-mint-client" } +fedimint-rocksdb = { version = "=0.3.1-rc.0", path = "../fedimint-rocksdb" } +fedimint-wallet-client = { version = "=0.3.1-rc.0", path = "../modules/fedimint-wallet-client" } futures = "0.3" jsonrpsee-core = { version = "0.22.2", features = [ "client" ] } jsonrpsee-types = { version = "0.22.2" } @@ -40,4 +40,4 @@ url = { version = "2.5.0", features = ["serde"] } jsonrpsee-ws-client = { version = "0.22.2", features = ["webpki-tls"], default-features = false } [build-dependencies] -fedimint-build = { version = "=0.3.0-rc.3", path = "../fedimint-build" } +fedimint-build = { version = "=0.3.1-rc.0", path = "../fedimint-build" } diff --git a/fedimint-logging/Cargo.toml b/fedimint-logging/Cargo.toml index 2fe0edfa7bc..ff4c6ace4e2 100644 --- a/fedimint-logging/Cargo.toml +++ b/fedimint-logging/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-logging" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "contains some utilities for logging and tracing" diff --git a/fedimint-metrics/Cargo.toml b/fedimint-metrics/Cargo.toml index d18dd512af9..a4046739d28 100644 --- a/fedimint-metrics/Cargo.toml +++ b/fedimint-metrics/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-metrics" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" edition = "2021" license = "MIT" readme = "README.md" @@ -17,7 +17,7 @@ path = "./src/lib.rs" [dependencies] anyhow = { version = "1.0.81", features = ["backtrace"] } axum = "0.7.4" -fedimint-core = { version = "=0.3.0-rc.3", path = "../fedimint-core" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../fedimint-core" } lazy_static = "1.4.0" prometheus = "0.13.3" tokio = "1" diff --git a/fedimint-rocksdb/Cargo.toml b/fedimint-rocksdb/Cargo.toml index 2e379459753..ad5d2c5e5ae 100644 --- a/fedimint-rocksdb/Cargo.toml +++ b/fedimint-rocksdb/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-rocksdb" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimint-rocksdb provides a rocksdb-backed database implementation for Fedimint." @@ -20,7 +20,7 @@ path = "src/lib.rs" [dependencies] anyhow = "1.0.81" async-trait = "0.1.77" -fedimint-core = { version = "=0.3.0-rc.3", path = "../fedimint-core" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../fedimint-core" } futures = "0.3.30" rocksdb = { version = "0.22.0" } tracing = "0.1.40" diff --git a/fedimint-server/Cargo.toml b/fedimint-server/Cargo.toml index 6e701472d5b..9746628ff73 100644 --- a/fedimint-server/Cargo.toml +++ b/fedimint-server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-server" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimint-server' facilitates federated consensus with atomic broadcast and distributed configuration." @@ -18,7 +18,7 @@ name = "fedimint_server" path = "src/lib.rs" [dependencies] -fedimint-aead = { version = "=0.3.0-rc.3", path = "../crypto/aead" } +fedimint-aead = { version = "=0.3.1-rc.0", path = "../crypto/aead" } anyhow = "1.0.81" async-channel = "2.2.0" async-trait = "0.1.77" @@ -29,9 +29,9 @@ bytes = "1.5.0" futures = "0.3.30" hex = "0.4.3" itertools = "0.12.1" -fedimint-core = { version = "=0.3.0-rc.3", path = "../fedimint-core" } -fedimint-logging = { version = "=0.3.0-rc.3", path = "../fedimint-logging" } -fedimint-metrics = { version = "=0.3.0-rc.3", path = "../fedimint-metrics" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../fedimint-core" } +fedimint-logging = { version = "=0.3.1-rc.0", path = "../fedimint-logging" } +fedimint-metrics = { version = "=0.3.1-rc.0", path = "../fedimint-metrics" } lazy_static = "1.4.0" pin-project = "1.1.5" rand = "0.8" @@ -44,7 +44,7 @@ sha3 = "0.10.8" strum = "0.26" strum_macros = "0.26" tar = "0.4.40" -tbs = { package = "fedimint-tbs", version = "=0.3.0-rc.3", path = "../crypto/tbs" } +tbs = { package = "fedimint-tbs", version = "=0.3.1-rc.0", path = "../crypto/tbs" } thiserror = "1.0.58" tower = { version = "0.4.13", default-features = false } tracing ="0.1.40" @@ -72,4 +72,4 @@ fedimint-portalloc = { path = "../utils/portalloc" } test-log = { version = "0.2", features = [ "trace" ], default-features = false } [build-dependencies] -fedimint-build = { version = "=0.3.0-rc.3", path = "../fedimint-build" } +fedimint-build = { version = "=0.3.1-rc.0", path = "../fedimint-build" } diff --git a/fedimint-testing/Cargo.toml b/fedimint-testing/Cargo.toml index 5b1a6f333eb..a1b356f5222 100644 --- a/fedimint-testing/Cargo.toml +++ b/fedimint-testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-testing" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimint-testing provides a library of shared objects and utilities for testing fedimint components" @@ -25,15 +25,15 @@ bitcoin = "0.29.2" bitcoincore-rpc = "0.16.0" clap = { version = "4.5.2", features = ["derive", "std", "help", "usage", "error-context", "suggestions" ], default-features = false } cln-rpc = { workspace = true } -fedimint-core = { version = "=0.3.0-rc.3", path = "../fedimint-core" } -fedimint-client = { version = "=0.3.0-rc.3", path = "../fedimint-client" } -fedimint-server = { version = "=0.3.0-rc.3", path = "../fedimint-server" } -fedimint-bitcoind = { version = "=0.3.0-rc.3", path = "../fedimint-bitcoind" } -fedimint-logging = { version = "=0.3.0-rc.3", path = "../fedimint-logging" } -fedimint-rocksdb = { version = "=0.3.0-rc.3", path = "../fedimint-rocksdb" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../fedimint-core" } +fedimint-client = { version = "=0.3.1-rc.0", path = "../fedimint-client" } +fedimint-server = { version = "=0.3.1-rc.0", path = "../fedimint-server" } +fedimint-bitcoind = { version = "=0.3.1-rc.0", path = "../fedimint-bitcoind" } +fedimint-logging = { version = "=0.3.1-rc.0", path = "../fedimint-logging" } +fedimint-rocksdb = { version = "=0.3.1-rc.0", path = "../fedimint-rocksdb" } fs-lock = "0.1.3" lazy_static = "1.4.0" -ln-gateway = { version = "=0.3.0-rc.3", package = "fedimint-ln-gateway", path = "../gateway/ln-gateway" } +ln-gateway = { version = "=0.3.1-rc.0", package = "fedimint-ln-gateway", path = "../gateway/ln-gateway" } futures = "0.3" lightning-invoice = "0.26.0" tempfile = "3.10.1" @@ -47,4 +47,4 @@ tokio = { version = "1.36.0", features = ["full", "tracing"] } tokio-stream = "0.1.14" tonic_lnd = { workspace = true } url = "2.5.0" -fedimint-portalloc = { version = "=0.3.0-rc.3", path = "../utils/portalloc" } +fedimint-portalloc = { version = "=0.3.1-rc.0", path = "../utils/portalloc" } diff --git a/fedimint-wasm-tests/Cargo.toml b/fedimint-wasm-tests/Cargo.toml index 546f91fcdb8..7bbfd3984c7 100644 --- a/fedimint-wasm-tests/Cargo.toml +++ b/fedimint-wasm-tests/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-wasm-tests" -version = "0.0.0" +version = "0.3.1-rc.0" edition = "2021" license = "MIT" description = "Wasm tests for the fedimint." diff --git a/fedimintd/Cargo.toml b/fedimintd/Cargo.toml index fa7a1b5aae6..ffe54e39f45 100644 --- a/fedimintd/Cargo.toml +++ b/fedimintd/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimintd" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimintd is the main consensus code for processing transactions and REST API" @@ -24,7 +24,7 @@ name = "fedimintd" path = "src/lib.rs" [dependencies] -fedimint-aead = { version = "=0.3.0-rc.3", path = "../crypto/aead" } +fedimint-aead = { version = "=0.3.1-rc.0", path = "../crypto/aead" } ring = "0.17.8" anyhow = "1.0.81" async-trait = "0.1.77" @@ -35,26 +35,26 @@ clap = { version = "4.5.2", features = ["derive", "std", "help", "usage", "error futures = "0.3.30" itertools = "0.12.1" jsonrpsee = { version = "0.22.2", features = ["server"] } -fedimint-bitcoind = { version = "=0.3.0-rc.3", path = "../fedimint-bitcoind" } -fedimint-core = { version = "=0.3.0-rc.3", path = "../fedimint-core" } -fedimint-ln-common = { version = "=0.3.0-rc.3", path = "../modules/fedimint-ln-common" } -fedimint-ln-server = { version = "=0.3.0-rc.3", path = "../modules/fedimint-ln-server" } -fedimint-logging = { version = "=0.3.0-rc.3", path = "../fedimint-logging", features = ["telemetry"] } -fedimint-metrics = { version = "=0.3.0-rc.3", path = "../fedimint-metrics" } -fedimint-mint-server = { version = "=0.3.0-rc.3", path = "../modules/fedimint-mint-server" } -fedimint-meta-server = { version = "=0.3.0-rc.3", path = "../modules/fedimint-meta-server" } -fedimint-rocksdb = { version = "=0.3.0-rc.3", path = "../fedimint-rocksdb" } -fedimint-server = { version = "=0.3.0-rc.3", path = "../fedimint-server" } -fedimint-wallet-server = { version = "=0.3.0-rc.3", path = "../modules/fedimint-wallet-server" } -fedimint-unknown-server = { version = "=0.3.0-rc.3", path = "../modules/fedimint-unknown-server" } -fedimint-unknown-common = { version = "=0.3.0-rc.3", path = "../modules/fedimint-unknown-common" } +fedimint-bitcoind = { version = "=0.3.1-rc.0", path = "../fedimint-bitcoind" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../fedimint-core" } +fedimint-ln-common = { version = "=0.3.1-rc.0", path = "../modules/fedimint-ln-common" } +fedimint-ln-server = { version = "=0.3.1-rc.0", path = "../modules/fedimint-ln-server" } +fedimint-logging = { version = "=0.3.1-rc.0", path = "../fedimint-logging", features = ["telemetry"] } +fedimint-metrics = { version = "=0.3.1-rc.0", path = "../fedimint-metrics" } +fedimint-mint-server = { version = "=0.3.1-rc.0", path = "../modules/fedimint-mint-server" } +fedimint-meta-server = { version = "=0.3.1-rc.0", path = "../modules/fedimint-meta-server" } +fedimint-rocksdb = { version = "=0.3.1-rc.0", path = "../fedimint-rocksdb" } +fedimint-server = { version = "=0.3.1-rc.0", path = "../fedimint-server" } +fedimint-wallet-server = { version = "=0.3.1-rc.0", path = "../modules/fedimint-wallet-server" } +fedimint-unknown-server = { version = "=0.3.1-rc.0", path = "../modules/fedimint-unknown-server" } +fedimint-unknown-common = { version = "=0.3.1-rc.0", path = "../modules/fedimint-unknown-common" } rand = "0.8" rcgen = "=0.12.1" secp256k1-zkp = { version = "0.7.0", features = [ "global-context", "bitcoin_hashes" ] } serde = { version = "1.0.197", features = [ "derive" ] } serde_json = "1.0.114" sha3 = "0.10.8" -tbs = { package = "fedimint-tbs", version = "=0.3.0-rc.3", path = "../crypto/tbs" } +tbs = { package = "fedimint-tbs", version = "=0.3.1-rc.0", path = "../crypto/tbs" } thiserror = "1.0.58" tokio = { version = "1.36.0", features = ["full", "tracing"] } tokio-rustls = "0.23.4" @@ -72,4 +72,4 @@ tower = { version = "0.4", features = ["util"] } console-subscriber = "0.2.0" [build-dependencies] -fedimint-build = { version = "=0.3.0-rc.3", path = "../fedimint-build" } +fedimint-build = { version = "=0.3.1-rc.0", path = "../fedimint-build" } diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 51921d3a82d..6b135f07287 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -2,7 +2,7 @@ name = "fedimint-fuzz" edition = "2021" authors = ["The Fedimint Developers"] -version = "0.3.0-rc.2" +version = "0.3.1-rc.0" publish = false license = "MIT" readme = "../README.md" @@ -13,7 +13,7 @@ cargo-fuzz = true [dependencies] honggfuzz = { version = "0.5.55", default-features = false } -fedimint-core = { version = "=0.3.0-rc.3", path = "../fedimint-core" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../fedimint-core" } # cargo-deny just needs at least one `bin` defined [lib] diff --git a/gateway/cli/Cargo.toml b/gateway/cli/Cargo.toml index 19557f5bbbc..236b352be01 100644 --- a/gateway/cli/Cargo.toml +++ b/gateway/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-gateway-cli" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" edition = "2021" license = "MIT" readme = "../../README.md" @@ -23,9 +23,9 @@ axum = "0.7.4" axum-macros = "0.4.1" bitcoin = { version = "0.29.2", features = ["serde"] } clap = { version = "4.5.2", features = ["derive", "std", "help", "usage", "error-context", "suggestions"], default-features = false } -ln-gateway = { version = "=0.3.0-rc.3", package = "fedimint-ln-gateway", path= "../ln-gateway" } -fedimint-core = { version = "=0.3.0-rc.3", path = "../../fedimint-core" } -fedimint-logging = { version = "=0.3.0-rc.3", path = "../../fedimint-logging" } +ln-gateway = { version = "=0.3.1-rc.0", package = "fedimint-ln-gateway", path= "../ln-gateway" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../../fedimint-core" } +fedimint-logging = { version = "=0.3.1-rc.0", path = "../../fedimint-logging" } reqwest = { version = "0.11.26", features = [ "json", "rustls-tls" ], default-features = false } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.114" @@ -35,4 +35,4 @@ url = { version = "2.5.0", features = ["serde"] } clap_complete = "4.5.1" [build-dependencies] -fedimint-build = { version = "=0.3.0-rc.3", path = "../../fedimint-build" } +fedimint-build = { version = "=0.3.1-rc.0", path = "../../fedimint-build" } diff --git a/gateway/ln-gateway/Cargo.toml b/gateway/ln-gateway/Cargo.toml index 0d698e14a8c..7b507efd975 100644 --- a/gateway/ln-gateway/Cargo.toml +++ b/gateway/ln-gateway/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-ln-gateway" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimint-ln-gateway sends/receives Lightning Network payments on behalf of Fedimint clients" @@ -39,15 +39,15 @@ clap = { version = "4.5.2", features = ["derive", "std", "help", "usage", "error # cln-plugin made semver incompatible change cln-plugin = "=0.1.7" cln-rpc = { workspace = true } -fedimint-client = { version = "=0.3.0-rc.3", path = "../../fedimint-client" } -fedimint-core = { version = "=0.3.0-rc.3", path = "../../fedimint-core" } -fedimint-logging = { version = "=0.3.0-rc.3", path = "../../fedimint-logging" } -fedimint-rocksdb = { version = "=0.3.0-rc.3", path = "../../fedimint-rocksdb" } -fedimint-ln-client = { version = "=0.3.0-rc.3", path = "../../modules/fedimint-ln-client" } -fedimint-ln-common = { version = "=0.3.0-rc.3", path = "../../modules/fedimint-ln-common" } -fedimint-mint-client = { version = "=0.3.0-rc.3", path = "../../modules/fedimint-mint-client" } -fedimint-dummy-client = { version = "=0.3.0-rc.3", path = "../../modules/fedimint-dummy-client" } -fedimint-wallet-client = { version = "=0.3.0-rc.3", path = "../../modules/fedimint-wallet-client" } +fedimint-client = { version = "=0.3.1-rc.0", path = "../../fedimint-client" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../../fedimint-core" } +fedimint-logging = { version = "=0.3.1-rc.0", path = "../../fedimint-logging" } +fedimint-rocksdb = { version = "=0.3.1-rc.0", path = "../../fedimint-rocksdb" } +fedimint-ln-client = { version = "=0.3.1-rc.0", path = "../../modules/fedimint-ln-client" } +fedimint-ln-common = { version = "=0.3.1-rc.0", path = "../../modules/fedimint-ln-common" } +fedimint-mint-client = { version = "=0.3.1-rc.0", path = "../../modules/fedimint-mint-client" } +fedimint-dummy-client = { version = "=0.3.1-rc.0", path = "../../modules/fedimint-dummy-client" } +fedimint-wallet-client = { version = "=0.3.1-rc.0", path = "../../modules/fedimint-wallet-client" } futures = "0.3.30" erased-serde = "0.4" lightning-invoice = "0.26.0" @@ -85,5 +85,5 @@ threshold_crypto = { workspace = true } assert_matches = "1.5.0" [build-dependencies] -fedimint-build = { version = "=0.3.0-rc.3", path = "../../fedimint-build" } +fedimint-build = { version = "=0.3.1-rc.0", path = "../../fedimint-build" } tonic-build = "0.11.0" diff --git a/modules/fedimint-dummy-client/Cargo.toml b/modules/fedimint-dummy-client/Cargo.toml index 65a9d7c900b..66f44f4e96b 100644 --- a/modules/fedimint-dummy-client/Cargo.toml +++ b/modules/fedimint-dummy-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-dummy-client" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimint-dummy is a dummy example fedimint module." @@ -18,9 +18,9 @@ path = "src/lib.rs" [dependencies] async-trait = "0.1.77" anyhow = "1.0.81" -fedimint-dummy-common = { version = "=0.3.0-rc.3", path = "../fedimint-dummy-common" } -fedimint-client = { version = "=0.3.0-rc.3", path = "../../fedimint-client" } -fedimint-core = { version = "=0.3.0-rc.3", path = "../../fedimint-core" } +fedimint-dummy-common = { version = "=0.3.1-rc.0", path = "../fedimint-dummy-common" } +fedimint-client = { version = "=0.3.1-rc.0", path = "../../fedimint-client" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../../fedimint-core" } futures = "0.3" erased-serde = "0.4" rand = "0.8.5" diff --git a/modules/fedimint-dummy-common/Cargo.toml b/modules/fedimint-dummy-common/Cargo.toml index 28f14d3ec0b..37fb027921d 100644 --- a/modules/fedimint-dummy-common/Cargo.toml +++ b/modules/fedimint-dummy-common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-dummy-common" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimint-dummy is a dummy example fedimint module." @@ -21,7 +21,7 @@ async-trait = "0.1.77" bitcoin_hashes = "0.11.0" erased-serde = "0.4" futures = "0.3" -fedimint-core = { version = "=0.3.0-rc.3", path = "../../fedimint-core" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../../fedimint-core" } rand = "0.8" serde = { version = "1.0.197", features = [ "derive" ] } secp256k1 = "0.24.3" diff --git a/modules/fedimint-dummy-server/Cargo.toml b/modules/fedimint-dummy-server/Cargo.toml index 0a87412f715..3483496f8ed 100644 --- a/modules/fedimint-dummy-server/Cargo.toml +++ b/modules/fedimint-dummy-server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-dummy-server" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimint-dummy is a dummy example fedimint module." @@ -21,8 +21,8 @@ async-trait = "0.1.77" bitcoin_hashes = "0.11.0" erased-serde = "0.4" futures = "0.3" -fedimint-core = { version = "=0.3.0-rc.3", path = "../../fedimint-core" } -fedimint-dummy-common = { version = "=0.3.0-rc.3", path = "../fedimint-dummy-common" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../../fedimint-core" } +fedimint-dummy-common = { version = "=0.3.1-rc.0", path = "../fedimint-dummy-common" } rand = "0.8" serde = { version = "1.0.197", features = [ "derive" ] } secp256k1 = "0.24.3" diff --git a/modules/fedimint-dummy-tests/Cargo.toml b/modules/fedimint-dummy-tests/Cargo.toml index e67ada2990d..ab3c200294a 100644 --- a/modules/fedimint-dummy-tests/Cargo.toml +++ b/modules/fedimint-dummy-tests/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-dummy-tests" -version = "0.3.0-rc.2" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimint-dummy is a dummy example fedimint module." diff --git a/modules/fedimint-empty-client/Cargo.toml b/modules/fedimint-empty-client/Cargo.toml index c3a8a7cb7aa..1d3912103cc 100644 --- a/modules/fedimint-empty-client/Cargo.toml +++ b/modules/fedimint-empty-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-empty-client" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimint-empty is an empty fedimint module, good template for a new module." @@ -18,9 +18,9 @@ path = "src/lib.rs" [dependencies] async-trait = "0.1.77" anyhow = "1.0.81" -fedimint-empty-common = { version = "=0.3.0-rc.3", path = "../fedimint-empty-common" } -fedimint-client = { version = "=0.3.0-rc.3", path = "../../fedimint-client" } -fedimint-core = { version = "=0.3.0-rc.3", path = "../../fedimint-core" } +fedimint-empty-common = { version = "=0.3.1-rc.0", path = "../fedimint-empty-common" } +fedimint-client = { version = "=0.3.1-rc.0", path = "../../fedimint-client" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../../fedimint-core" } futures = "0.3" erased-serde = "0.4" serde = {version = "1.0.197", features = [ "derive" ] } diff --git a/modules/fedimint-empty-common/Cargo.toml b/modules/fedimint-empty-common/Cargo.toml index feffcc7da84..ebdbce2fd48 100644 --- a/modules/fedimint-empty-common/Cargo.toml +++ b/modules/fedimint-empty-common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-empty-common" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimint-empty is a empty fedimint module, good template for a new module." @@ -20,7 +20,7 @@ anyhow = "1.0.81" async-trait = "0.1.77" erased-serde = "0.4" futures = "0.3" -fedimint-core = { version = "=0.3.0-rc.3", path = "../../fedimint-core" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../../fedimint-core" } serde = { version = "1.0.197", features = [ "derive" ] } strum = "0.26" strum_macros = "0.26" diff --git a/modules/fedimint-empty-server/Cargo.toml b/modules/fedimint-empty-server/Cargo.toml index 25ed3dab356..cbf6b5dffdc 100644 --- a/modules/fedimint-empty-server/Cargo.toml +++ b/modules/fedimint-empty-server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-empty-server" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimint-empty is a empty fedimint module, good template for a new module." @@ -20,8 +20,8 @@ anyhow = "1.0.81" async-trait = "0.1.77" erased-serde = "0.4" futures = "0.3" -fedimint-core = { version = "=0.3.0-rc.3", path = "../../fedimint-core" } -fedimint-empty-common = { version = "=0.3.0-rc.3", path = "../fedimint-empty-common" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../../fedimint-core" } +fedimint-empty-common = { version = "=0.3.1-rc.0", path = "../fedimint-empty-common" } serde = { version = "1.0.197", features = [ "derive" ] } strum = "0.26" strum_macros = "0.26" diff --git a/modules/fedimint-ln-client/Cargo.toml b/modules/fedimint-ln-client/Cargo.toml index 506d22cc664..a2cf922c351 100644 --- a/modules/fedimint-ln-client/Cargo.toml +++ b/modules/fedimint-ln-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-ln-client" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimint-ln is a lightning payment service module." @@ -33,9 +33,9 @@ erased-serde = "0.4" futures = "0.3.30" itertools = "0.12.1" lightning-invoice = { version = "0.26.0", features = [ "serde" ] } -fedimint-client = { version = "=0.3.0-rc.3", path = "../../fedimint-client" } -fedimint-core = { version = "=0.3.0-rc.3", path = "../../fedimint-core" } -fedimint-ln-common = { version = "=0.3.0-rc.3", path = "../fedimint-ln-common" } +fedimint-client = { version = "=0.3.1-rc.0", path = "../../fedimint-client" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../../fedimint-core" } +fedimint-ln-common = { version = "=0.3.1-rc.0", path = "../fedimint-ln-common" } secp256k1 = { version="0.24.3", default-features=false } secp256k1-zkp = { version = "0.7.0", features = [ "serde", "bitcoin_hashes" ] } serde = {version = "1.0.197", features = [ "derive" ] } diff --git a/modules/fedimint-ln-common/Cargo.toml b/modules/fedimint-ln-common/Cargo.toml index d4c24034fdf..e663afbbfa2 100644 --- a/modules/fedimint-ln-common/Cargo.toml +++ b/modules/fedimint-ln-common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-ln-common" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimint-ln is a lightning payment service module." @@ -32,8 +32,8 @@ futures = "0.3.30" itertools = "0.12.1" lightning = { version = "0.0.118", default-features = false, features = ["no-std"] } lightning-invoice = { version = "0.26.0", features = [ "serde" ] } -fedimint-client = { version = "=0.3.0-rc.3", path = "../../fedimint-client" } -fedimint-core = { version = "=0.3.0-rc.3", path = "../../fedimint-core" } +fedimint-client = { version = "=0.3.1-rc.0", path = "../../fedimint-client" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../../fedimint-core" } secp256k1 = { version="0.24.3", default-features=false } serde = {version = "1.0.197", features = [ "derive" ] } serde_json = "1.0.114" diff --git a/modules/fedimint-ln-server/Cargo.toml b/modules/fedimint-ln-server/Cargo.toml index 416c2e058c5..fcb8637c622 100644 --- a/modules/fedimint-ln-server/Cargo.toml +++ b/modules/fedimint-ln-server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-ln-server" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimint-ln is a lightning payment service module." @@ -27,10 +27,10 @@ futures = "0.3.30" itertools = "0.12.1" lightning = "0.0.118" lightning-invoice = { version = "0.26.0", features = [ "serde" ] } -fedimint-bitcoind = { version = "=0.3.0-rc.3", path = "../../fedimint-bitcoind" } -fedimint-core = { version = "=0.3.0-rc.3", path = "../../fedimint-core" } -fedimint-ln-common = { version = "=0.3.0-rc.3", path = "../fedimint-ln-common" } -fedimint-metrics = { version = "=0.3.0-rc.3", path = "../../fedimint-metrics" } +fedimint-bitcoind = { version = "=0.3.1-rc.0", path = "../../fedimint-bitcoind" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../../fedimint-core" } +fedimint-ln-common = { version = "=0.3.1-rc.0", path = "../fedimint-ln-common" } +fedimint-metrics = { version = "=0.3.1-rc.0", path = "../../fedimint-metrics" } secp256k1 = { version="0.24.3", default-features=false } serde = {version = "1.0.197", features = [ "derive" ] } serde_json = "1.0.114" @@ -42,7 +42,7 @@ tokio = { version = "1.36", features = ["full"] } tracing = "0.1.40" rand = "0.8" url = { version = "2.5.0", features = ["serde"] } -fedimint-server = { version = "=0.3.0-rc.3", path = "../../fedimint-server" } +fedimint-server = { version = "=0.3.1-rc.0", path = "../../fedimint-server" } [dev-dependencies] assert_matches = "1.5.0" diff --git a/modules/fedimint-ln-tests/Cargo.toml b/modules/fedimint-ln-tests/Cargo.toml index ec31bde5531..5ac7a7b087d 100644 --- a/modules/fedimint-ln-tests/Cargo.toml +++ b/modules/fedimint-ln-tests/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-ln-tests" -version = "0.3.0-rc.2" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimint-ln-tests contains integration tests for the lightning module" diff --git a/modules/fedimint-meta-client/Cargo.toml b/modules/fedimint-meta-client/Cargo.toml index 92f1d560db7..ff327b37a1a 100644 --- a/modules/fedimint-meta-client/Cargo.toml +++ b/modules/fedimint-meta-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-meta-client" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimint-meta is a meta consensus fedimint module." @@ -25,9 +25,9 @@ anyhow = "1.0.66" clap = { workspace = true, optional = true } hex = "0.4.3" serde_json = { workspace = true, optional = true } -fedimint-meta-common = { version = "=0.3.0-rc.3", path = "../fedimint-meta-common" } -fedimint-client = { version = "=0.3.0-rc.3", path = "../../fedimint-client" } -fedimint-core = { version = "=0.3.0-rc.3", path = "../../fedimint-core" } +fedimint-meta-common = { version = "=0.3.1-rc.0", path = "../fedimint-meta-common" } +fedimint-client = { version = "=0.3.1-rc.0", path = "../../fedimint-client" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../../fedimint-core" } futures = "0.3" erased-serde = "0.4" rand = "0.8.5" diff --git a/modules/fedimint-meta-common/Cargo.toml b/modules/fedimint-meta-common/Cargo.toml index 2a13a7486a7..e6b20d6d008 100644 --- a/modules/fedimint-meta-common/Cargo.toml +++ b/modules/fedimint-meta-common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-meta-common" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimint-meta is a meta-consensus fedimint module." @@ -22,7 +22,7 @@ bitcoin_hashes = "0.11.0" erased-serde = "0.4" hex = "0.4.3" futures = "0.3" -fedimint-core = { version = "=0.3.0-rc.3", path = "../../fedimint-core" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../../fedimint-core" } rand = "0.8" serde = { version = "1.0.149", features = [ "derive" ] } serde_json = "1.0.91" diff --git a/modules/fedimint-meta-server/Cargo.toml b/modules/fedimint-meta-server/Cargo.toml index b0b95780485..e55b1fec283 100644 --- a/modules/fedimint-meta-server/Cargo.toml +++ b/modules/fedimint-meta-server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-meta-server" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimint-meta is a meta consensus fedimint module." @@ -21,9 +21,9 @@ async-trait = "0.1.73" bitcoin_hashes = "0.11.0" erased-serde = "0.4" futures = "0.3" -fedimint-core = { version = "=0.3.0-rc.3", path = "../../fedimint-core" } -fedimint-logging = { version = "=0.3.0-rc.3", path = "../../fedimint-logging" } -fedimint-meta-common = { version = "=0.3.0-rc.3", path = "../fedimint-meta-common" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../../fedimint-core" } +fedimint-logging = { version = "=0.3.1-rc.0", path = "../../fedimint-logging" } +fedimint-meta-common = { version = "=0.3.1-rc.0", path = "../fedimint-meta-common" } rand = "0.8" serde = { version = "1.0.149", features = [ "derive" ] } secp256k1 = "0.24.2" diff --git a/modules/fedimint-mint-client/Cargo.toml b/modules/fedimint-mint-client/Cargo.toml index ac160ec1c9f..dabf99c3e3a 100644 --- a/modules/fedimint-mint-client/Cargo.toml +++ b/modules/fedimint-mint-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-mint-client" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimint-mint is a chaumian ecash mint module." @@ -27,11 +27,11 @@ bitcoin_hashes = "0.11.0" erased-serde = "0.4" futures = "0.3" itertools = "0.12.1" -fedimint-core = { version = "=0.3.0-rc.3", path = "../../fedimint-core" } -fedimint-client = { version = "=0.3.0-rc.3", path = "../../fedimint-client" } -fedimint-derive-secret = { version = "=0.3.0-rc.3", path = "../../crypto/derive-secret"} -fedimint-mint-common ={ version = "=0.3.0-rc.3", path = "../fedimint-mint-common" } -fedimint-logging = { version = "=0.3.0-rc.3", path = "../../fedimint-logging" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../../fedimint-core" } +fedimint-client = { version = "=0.3.1-rc.0", path = "../../fedimint-client" } +fedimint-derive-secret = { version = "=0.3.1-rc.0", path = "../../crypto/derive-secret"} +fedimint-mint-common ={ version = "=0.3.1-rc.0", path = "../fedimint-mint-common" } +fedimint-logging = { version = "=0.3.1-rc.0", path = "../../fedimint-logging" } rand = "0.8" secp256k1 = "0.24.3" secp256k1-zkp = "0.7.0" @@ -40,7 +40,7 @@ serde-big-array = "0.5.1" serde_json = "1.0.114" strum = "0.26" strum_macros = "0.26" -tbs = { package = "fedimint-tbs", version = "=0.3.0-rc.3", path = "../../crypto/tbs" } +tbs = { package = "fedimint-tbs", version = "=0.3.1-rc.0", path = "../../crypto/tbs" } thiserror = "1.0.58" threshold_crypto = { workspace = true } tokio = { version = "1.36.0", features = [ "sync" ] } diff --git a/modules/fedimint-mint-common/Cargo.toml b/modules/fedimint-mint-common/Cargo.toml index 983f095b4a2..0a68809b002 100644 --- a/modules/fedimint-mint-common/Cargo.toml +++ b/modules/fedimint-mint-common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-mint-common" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimint-mint is a chaumian ecash mint module." @@ -23,14 +23,14 @@ bincode = "1.3.3" bitcoin_hashes = "0.11.0" futures = "0.3" itertools = "0.12.1" -fedimint-core = { version = "=0.3.0-rc.3", path = "../../fedimint-core" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../../fedimint-core" } rand = "0.8" secp256k1 = "0.24.3" secp256k1-zkp = "0.7.0" serde = { version = "1.0.197", features = [ "derive" ] } strum = "0.26" strum_macros = "0.26" -tbs = { package = "fedimint-tbs", version = "=0.3.0-rc.3", path = "../../crypto/tbs" } +tbs = { package = "fedimint-tbs", version = "=0.3.1-rc.0", path = "../../crypto/tbs" } thiserror = "1.0.58" threshold_crypto = { workspace = true } tracing ="0.1.40" diff --git a/modules/fedimint-mint-server/Cargo.toml b/modules/fedimint-mint-server/Cargo.toml index 886d7485b18..6933ecda39c 100644 --- a/modules/fedimint-mint-server/Cargo.toml +++ b/modules/fedimint-mint-server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-mint-server" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimint-mint is a chaumian ecash mint module." @@ -25,20 +25,20 @@ bitcoin_hashes = "0.11.0" erased-serde = "0.4" futures = "0.3" itertools = "0.12.1" -fedimint-core = { version = "=0.3.0-rc.3", path = "../../fedimint-core" } -fedimint-metrics = { version = "=0.3.0-rc.3", path = "../../fedimint-metrics" } -fedimint-mint-common = { version = "=0.3.0-rc.3", path = "../fedimint-mint-common" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../../fedimint-core" } +fedimint-metrics = { version = "=0.3.1-rc.0", path = "../../fedimint-metrics" } +fedimint-mint-common = { version = "=0.3.1-rc.0", path = "../fedimint-mint-common" } rand = "0.8" secp256k1 = "0.24.3" secp256k1-zkp = "0.7.0" serde = { version = "1.0.197", features = [ "derive" ] } strum = "0.26" strum_macros = "0.26" -tbs = { package = "fedimint-tbs", version = "=0.3.0-rc.3", path = "../../crypto/tbs" } +tbs = { package = "fedimint-tbs", version = "=0.3.1-rc.0", path = "../../crypto/tbs" } thiserror = "1.0.58" threshold_crypto = { workspace = true } tracing ="0.1.40" -fedimint-server = { version = "=0.3.0-rc.3", path = "../../fedimint-server" } +fedimint-server = { version = "=0.3.1-rc.0", path = "../../fedimint-server" } [dev-dependencies] rand = "0.8" diff --git a/modules/fedimint-mint-tests/Cargo.toml b/modules/fedimint-mint-tests/Cargo.toml index 612ed132a75..8cf563775c6 100644 --- a/modules/fedimint-mint-tests/Cargo.toml +++ b/modules/fedimint-mint-tests/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-mint-tests" -version = "0.3.0-rc.2" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimint-mint-tests contains integration tests for the mint module" @@ -31,7 +31,7 @@ tracing = "0.1.40" rand = "0.8" secp256k1 = "0.24.3" serde = { version = "1.0.197", features = [ "derive" ] } -tbs = { package = "fedimint-tbs", version = "=0.3.0-rc.3", path = "../../crypto/tbs" } +tbs = { package = "fedimint-tbs", version = "=0.3.1-rc.0", path = "../../crypto/tbs" } threshold_crypto = { workspace = true } ff = "0.12.1" strum = "0.26" diff --git a/modules/fedimint-unknown-common/Cargo.toml b/modules/fedimint-unknown-common/Cargo.toml index eefd3529e62..a0f9ae43432 100644 --- a/modules/fedimint-unknown-common/Cargo.toml +++ b/modules/fedimint-unknown-common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-unknown-common" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimint-unknown is a fedimint module that doesn't have any client side implementation." @@ -21,7 +21,7 @@ async-trait = "0.1.77" bitcoin_hashes = "0.11.0" erased-serde = "0.4" futures = "0.3" -fedimint-core = { version = "=0.3.0-rc.3", path = "../../fedimint-core" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../../fedimint-core" } rand = "0.8" serde = { version = "1.0.197", features = [ "derive" ] } thiserror = "1.0.58" diff --git a/modules/fedimint-unknown-server/Cargo.toml b/modules/fedimint-unknown-server/Cargo.toml index 6d1141155a9..1df2c71f784 100644 --- a/modules/fedimint-unknown-server/Cargo.toml +++ b/modules/fedimint-unknown-server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-unknown-server" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimint-unknown-server is a test fedimint module that doesn't have any client side implementation." @@ -20,8 +20,8 @@ anyhow = "1.0.81" async-trait = "0.1.77" erased-serde = "0.4" futures = "0.3" -fedimint-core = { version = "=0.3.0-rc.3", path = "../../fedimint-core" } -fedimint-unknown-common = { version = "=0.3.0-rc.3", path = "../fedimint-unknown-common" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../../fedimint-core" } +fedimint-unknown-common = { version = "=0.3.1-rc.0", path = "../fedimint-unknown-common" } rand = "0.8" serde = { version = "1.0.197", features = [ "derive" ] } strum = "0.26" diff --git a/modules/fedimint-wallet-client/Cargo.toml b/modules/fedimint-wallet-client/Cargo.toml index 657da84b731..41dc1ff5d11 100644 --- a/modules/fedimint-wallet-client/Cargo.toml +++ b/modules/fedimint-wallet-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-wallet-client" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimint-wallet is a n on-chain bitcoin wallet module. It uses a key-value store and is not a standard HD wallet." @@ -22,9 +22,9 @@ async-stream = "0.3.5" async-trait = "0.1.77" bitcoin = { version = "0.29.2", features = [ "rand", "serde"] } erased-serde = "0.4" -fedimint-client = { version = "=0.3.0-rc.3", path = "../../fedimint-client" } -fedimint-core = { version = "=0.3.0-rc.3", path = "../../fedimint-core" } -fedimint-wallet-common = { version = "=0.3.0-rc.3", path = "../fedimint-wallet-common" } +fedimint-client = { version = "=0.3.1-rc.0", path = "../../fedimint-client" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../../fedimint-core" } +fedimint-wallet-common = { version = "=0.3.1-rc.0", path = "../fedimint-wallet-common" } futures = "0.3" miniscript = { version = "10.0.0", features = [ "compiler", "serde" ] } impl-tools = "0.10.0" @@ -41,10 +41,10 @@ url = "2.5.0" validator = { version = "0.17", features = ["derive"] } [target.'cfg(not(target_family = "wasm"))'.dependencies] -fedimint-bitcoind = { version = "=0.3.0-rc.3", path = "../../fedimint-bitcoind", default-features = false, features = ["esplora-client", "bitcoincore-rpc"] } +fedimint-bitcoind = { version = "=0.3.1-rc.0", path = "../../fedimint-bitcoind", default-features = false, features = ["esplora-client", "bitcoincore-rpc"] } [target.'cfg(target_family = "wasm")'.dependencies] -fedimint-bitcoind = { version = "=0.3.0-rc.3", path = "../../fedimint-bitcoind", default-features = false, features = ["esplora-client"] } +fedimint-bitcoind = { version = "=0.3.1-rc.0", path = "../../fedimint-bitcoind", default-features = false, features = ["esplora-client"] } [dev-dependencies] tracing-subscriber = { version = "0.3.18", features = [ "env-filter" ] } diff --git a/modules/fedimint-wallet-common/Cargo.toml b/modules/fedimint-wallet-common/Cargo.toml index 920dd09bd16..a99c7a7e3c1 100644 --- a/modules/fedimint-wallet-common/Cargo.toml +++ b/modules/fedimint-wallet-common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-wallet-common" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimint-wallet is a n on-chain bitcoin wallet module. It uses a key-value store and is not a standard HD wallet." @@ -20,7 +20,7 @@ anyhow = "1.0.81" async-trait = "0.1.77" bitcoin = { version = "0.29.2", features = [ "rand", "serde"] } erased-serde = "0.4" -fedimint-core = { version = "=0.3.0-rc.3", path = "../../fedimint-core" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../../fedimint-core" } futures = "0.3" miniscript = { version = "10.0.0", features = [ "compiler", "serde" ] } miniscript9 = { package = "miniscript", version = "9.0.2" } diff --git a/modules/fedimint-wallet-server/Cargo.toml b/modules/fedimint-wallet-server/Cargo.toml index dfb49e33707..e59c91f9450 100644 --- a/modules/fedimint-wallet-server/Cargo.toml +++ b/modules/fedimint-wallet-server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-wallet-server" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimint-wallet is a n on-chain bitcoin wallet module. It uses a key-value store and is not a standard HD wallet." @@ -20,10 +20,10 @@ anyhow = "1.0.81" async-trait = "0.1" bitcoin = { version = "0.29.2", features = [ "rand", "serde"] } erased-serde = "0.4" -fedimint-bitcoind = { version = "=0.3.0-rc.3", path = "../../fedimint-bitcoind" } -fedimint-core = { version = "=0.3.0-rc.3", path = "../../fedimint-core" } -fedimint-metrics = { version = "=0.3.0-rc.3", path = "../../fedimint-metrics" } -fedimint-wallet-common = { version = "=0.3.0-rc.3", path = "../fedimint-wallet-common" } +fedimint-bitcoind = { version = "=0.3.1-rc.0", path = "../../fedimint-bitcoind" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../../fedimint-core" } +fedimint-metrics = { version = "=0.3.1-rc.0", path = "../../fedimint-metrics" } +fedimint-wallet-common = { version = "=0.3.1-rc.0", path = "../fedimint-wallet-common" } futures = "0.3" miniscript = { version = "10.0.0", features = [ "compiler", "serde" ] } miniscript9 = { package = "miniscript", version = "9.0.2" } @@ -38,7 +38,7 @@ tokio = { version = "1.36.0", features = ["sync"], optional = true } tracing ="0.1.40" url = "2.5.0" validator = { version = "0.17", features = ["derive"] } -fedimint-server = { version = "=0.3.0-rc.3", path = "../../fedimint-server" } +fedimint-server = { version = "=0.3.1-rc.0", path = "../../fedimint-server" } [dev-dependencies] tracing-subscriber = { version = "0.3.18", features = [ "env-filter" ] } diff --git a/modules/fedimint-wallet-tests/Cargo.toml b/modules/fedimint-wallet-tests/Cargo.toml index e9d92093640..48013de1a63 100644 --- a/modules/fedimint-wallet-tests/Cargo.toml +++ b/modules/fedimint-wallet-tests/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-wallet-tests" -version = "0.3.0-rc.2" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "fedimint-wallet-tests contains integration tests for the lightning module" diff --git a/recoverytool/Cargo.toml b/recoverytool/Cargo.toml index 73de50a8977..ea4a8218fb6 100644 --- a/recoverytool/Cargo.toml +++ b/recoverytool/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-recoverytool" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" edition = "2021" authors = ["The Fedimint Developers"] description = "recoverytool allows retrieving on-chain funds from a offline federation" @@ -19,15 +19,15 @@ path = "src/main.rs" anyhow = "1.0.81" bitcoin = "0.29.2" clap = { version = "4.5.2", features = [ "derive", "env" ] } -fedimint-aead = { version = "=0.3.0-rc.3", path = "../crypto/aead" } -fedimint-core = { version = "=0.3.0-rc.3", path = "../fedimint-core" } -fedimint-rocksdb = { version = "=0.3.0-rc.3", path = "../fedimint-rocksdb" } -fedimint-server = { version = "=0.3.0-rc.3", path = "../fedimint-server" } -fedimint-wallet-server = { version = "=0.3.0-rc.3", path = "../modules/fedimint-wallet-server" } -fedimint-logging = { version = "=0.3.0-rc.3", path = "../fedimint-logging" } -fedimint-ln-common = { version = "=0.3.0-rc.3", path = "../modules/fedimint-ln-common" } -fedimint-ln-server = { version = "=0.3.0-rc.3", path = "../modules/fedimint-ln-server" } -fedimint-mint-server = { version = "=0.3.0-rc.3", path = "../modules/fedimint-mint-server" } +fedimint-aead = { version = "=0.3.1-rc.0", path = "../crypto/aead" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../fedimint-core" } +fedimint-rocksdb = { version = "=0.3.1-rc.0", path = "../fedimint-rocksdb" } +fedimint-server = { version = "=0.3.1-rc.0", path = "../fedimint-server" } +fedimint-wallet-server = { version = "=0.3.1-rc.0", path = "../modules/fedimint-wallet-server" } +fedimint-logging = { version = "=0.3.1-rc.0", path = "../fedimint-logging" } +fedimint-ln-common = { version = "=0.3.1-rc.0", path = "../modules/fedimint-ln-common" } +fedimint-ln-server = { version = "=0.3.1-rc.0", path = "../modules/fedimint-ln-server" } +fedimint-mint-server = { version = "=0.3.1-rc.0", path = "../modules/fedimint-mint-server" } futures = "0.3.30" miniscript = { version = "10.0.0" } secp256k1 = { version = "0.24.3", features = [ "serde", "global-context" ] } diff --git a/utils/portalloc/Cargo.toml b/utils/portalloc/Cargo.toml index c2259552f77..75f824b5b3e 100644 --- a/utils/portalloc/Cargo.toml +++ b/utils/portalloc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fedimint-portalloc" -version = "0.3.0-rc.3" +version = "0.3.1-rc.0" authors = ["The Fedimint Developers"] edition = "2021" description = "Port allocation utility for Fedimint" @@ -23,4 +23,4 @@ serde_json = { version = "1.0.114", features = ["preserve_order"] } tracing = "0.1.40" rand = "0.8" dirs = "5.0.1" -fedimint-core = { version = "=0.3.0-rc.3", path = "../../fedimint-core" } +fedimint-core = { version = "=0.3.1-rc.0", path = "../../fedimint-core" } From a5995a54061c488b18832a8e6ac2ebee39fbfa36 Mon Sep 17 00:00:00 2001 From: Justin Moeller Date: Tue, 2 Apr 2024 10:52:26 -0500 Subject: [PATCH 17/18] fix: use random gateway on cli when gateway not specified --- devimint/src/tests.rs | 7 +++++-- fedimint-cli/src/client.rs | 43 ++++++++++++++++++++++++++++++++------ 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/devimint/src/tests.rs b/devimint/src/tests.rs index 3c57dc547ea..754096f0a46 100644 --- a/devimint/src/tests.rs +++ b/devimint/src/tests.rs @@ -273,7 +273,8 @@ pub async fn latency_tests(dev_fed: DevFed, r#type: LatencyTest) -> Result<()> { client, "ln-invoice", "--amount=1000000msat", - "--description=internal-swap-invoice" + "--description=internal-swap-invoice", + "--force-internal" ) .out_json() .await?; @@ -287,7 +288,9 @@ pub async fn latency_tests(dev_fed: DevFed, r#type: LatencyTest) -> Result<()> { .to_owned(); let start_time = Instant::now(); - cmd!(sender, "ln-pay", invoice).run().await?; + cmd!(sender, "ln-pay", invoice, "--force-internal") + .run() + .await?; cmd!(client, "await-invoice", recv_op).run().await?; fm_internal_pay.push(start_time.elapsed()); } diff --git a/fedimint-cli/src/client.rs b/fedimint-cli/src/client.rs index a9bc48738b7..e51727e1f3c 100644 --- a/fedimint-cli/src/client.rs +++ b/fedimint-cli/src/client.rs @@ -3,7 +3,7 @@ use std::ffi; use std::str::FromStr; use std::time::{Duration, UNIX_EPOCH}; -use anyhow::{bail, Context}; +use anyhow::{anyhow, bail, Context}; use bip39::Mnemonic; use bitcoin::{secp256k1, Network}; use bitcoin_hashes::hex::ToHex; @@ -29,6 +29,8 @@ use fedimint_wallet_client::{WalletClientModule, WithdrawState}; use futures::StreamExt; use itertools::Itertools; use lightning_invoice::{Bolt11Invoice, Bolt11InvoiceDescription, Description}; +use rand::rngs::OsRng; +use rand::seq::IteratorRandom; use serde::{Deserialize, Serialize}; use serde_json::json; use time::format_description::well_known::iso8601; @@ -99,6 +101,8 @@ pub enum ClientCmd { expiry_time: Option, #[clap(long)] gateway_id: Option, + #[clap(long, default_value = "false")] + force_internal: bool, }, /// Wait for incoming invoice to be paid AwaitInvoice { operation_id: OperationId }, @@ -117,6 +121,8 @@ pub enum ClientCmd { finish_in_background: bool, #[clap(long)] gateway_id: Option, + #[clap(long, default_value = "false")] + force_internal: bool, }, /// Wait for a lightning payment to complete AwaitLnPay { operation_id: OperationId }, @@ -318,8 +324,9 @@ pub async fn handle_command( description, expiry_time, gateway_id, + force_internal, } => { - let ln_gateway = get_gateway(&client, gateway_id).await; + let ln_gateway = get_gateway(&client, gateway_id, force_internal).await?; let lightning_module = client.get_first_module::(); let desc = Description::new(description)?; @@ -368,10 +375,11 @@ pub async fn handle_command( finish_in_background, lnurl_comment, gateway_id, + force_internal, } => { let bolt11 = get_invoice(&payment_info, amount, lnurl_comment).await?; info!("Paying invoice: {bolt11}"); - let ln_gateway = get_gateway(&client, gateway_id).await; + let ln_gateway = get_gateway(&client, gateway_id, force_internal).await?; let lightning_module = client.get_first_module::(); let OutgoingLightningPayment { @@ -765,13 +773,36 @@ async fn get_note_summary(client: &ClientHandleArc) -> anyhow::Result, -) -> Option { + force_internal: bool, +) -> anyhow::Result> { let lightning_module = client.get_first_module::(); - let gateway_id = gateway_id.or(None)?; - lightning_module.select_gateway(&gateway_id).await + match gateway_id { + Some(gateway_id) => Ok(lightning_module.select_gateway(&gateway_id).await), + None if !force_internal => { + let gw = lightning_module + .list_gateways() + .await + .into_iter() + .choose(&mut OsRng) + .map(|gw| gw.info); + if let Some(gw) = gw { + let gw_id = gw.gateway_id; + info!(%gw_id, "Using random gateway"); + Ok(Some(gw)) + } else { + Err(anyhow!( + "No gateways exist in gateway cache and `force_internal` is false" + )) + } + } + None => Ok(None), + } } #[derive(Debug, Clone, Serialize, Deserialize)] From bb306ad603c0504c318666d17709a4a85d21574b Mon Sep 17 00:00:00 2001 From: Justin Moeller Date: Mon, 8 Apr 2024 10:04:19 -0500 Subject: [PATCH 18/18] feat: update gateway cache if no gateways are found --- devimint/src/tests.rs | 47 ++++++++++++++++++++++--------- devimint/src/version_constants.rs | 1 + fedimint-cli/src/client.rs | 24 ++++++++++------ 3 files changed, 50 insertions(+), 22 deletions(-) diff --git a/devimint/src/tests.rs b/devimint/src/tests.rs index 754096f0a46..a23dd776c6a 100644 --- a/devimint/src/tests.rs +++ b/devimint/src/tests.rs @@ -26,7 +26,7 @@ use tracing::{debug, info}; use crate::cli::{cleanup_on_exit, exec_user_command, setup, write_ready_file, CommonArgs}; use crate::federation::{Client, Federation}; use crate::util::{poll, poll_with_timeout, LoadTestTool, ProcessManager}; -use crate::version_constants::VERSION_0_3_0_ALPHA; +use crate::version_constants::{VERSION_0_3_0, VERSION_0_3_0_ALPHA}; use crate::{cmd, dev_fed, poll_eq, DevFed, Gatewayd, LightningNode, Lightningd, Lnd}; pub struct Stats { @@ -268,16 +268,32 @@ pub async fn latency_tests(dev_fed: DevFed, r#type: LatencyTest) -> Result<()> { let mut fm_internal_pay = Vec::with_capacity(iterations); let sender = fed.new_joined_client("internal-swap-sender").await?; fed.pegin_client(10_000_000, &sender).await?; + // TODO(support:v0.2): 0.3 removed the active gateway concept and requires an + // explicit gateway or `force-internal` + let fedimint_cli_version = crate::util::FedimintCli::version_or_default().await; + let default_internal = fedimint_cli_version <= *VERSION_0_3_0; for _ in 0..iterations { - let recv = cmd!( - client, - "ln-invoice", - "--amount=1000000msat", - "--description=internal-swap-invoice", - "--force-internal" - ) - .out_json() - .await?; + let recv = if default_internal { + cmd!( + client, + "ln-invoice", + "--amount=1000000msat", + "--description=internal-swap-invoice" + ) + .out_json() + .await? + } else { + cmd!( + client, + "ln-invoice", + "--amount=1000000msat", + "--description=internal-swap-invoice", + "--force-internal" + ) + .out_json() + .await? + }; + let invoice = recv["invoice"] .as_str() .context("invoice must be string")? @@ -288,9 +304,14 @@ pub async fn latency_tests(dev_fed: DevFed, r#type: LatencyTest) -> Result<()> { .to_owned(); let start_time = Instant::now(); - cmd!(sender, "ln-pay", invoice, "--force-internal") - .run() - .await?; + if default_internal { + cmd!(sender, "ln-pay", invoice).run().await?; + } else { + cmd!(sender, "ln-pay", invoice, "--force-internal") + .run() + .await?; + } + cmd!(client, "await-invoice", recv_op).run().await?; fm_internal_pay.push(start_time.elapsed()); } diff --git a/devimint/src/version_constants.rs b/devimint/src/version_constants.rs index aa29014fdae..a28ecaef4a7 100644 --- a/devimint/src/version_constants.rs +++ b/devimint/src/version_constants.rs @@ -4,4 +4,5 @@ use semver::Version; lazy_static! { pub static ref VERSION_0_3_0_ALPHA: Version = Version::parse("0.3.0-alpha").expect("version is parsable"); + pub static ref VERSION_0_3_0: Version = Version::parse("0.3.0").expect("version is parsable"); } diff --git a/fedimint-cli/src/client.rs b/fedimint-cli/src/client.rs index e51727e1f3c..6e4534b0c75 100644 --- a/fedimint-cli/src/client.rs +++ b/fedimint-cli/src/client.rs @@ -774,8 +774,7 @@ async fn get_note_summary(client: &ClientHandleArc) -> anyhow::Result, @@ -783,14 +782,21 @@ async fn get_gateway( ) -> anyhow::Result> { let lightning_module = client.get_first_module::(); match gateway_id { - Some(gateway_id) => Ok(lightning_module.select_gateway(&gateway_id).await), + Some(gateway_id) => { + if let Some(gw) = lightning_module.select_gateway(&gateway_id).await { + Ok(Some(gw)) + } else { + // Refresh the gateway cache in case the target gateway was registered since the + // last update. + lightning_module.update_gateway_cache().await?; + Ok(lightning_module.select_gateway(&gateway_id).await) + } + } None if !force_internal => { - let gw = lightning_module - .list_gateways() - .await - .into_iter() - .choose(&mut OsRng) - .map(|gw| gw.info); + // Refresh the gateway cache to find a random gateway to select from. + lightning_module.update_gateway_cache().await?; + let gateways = lightning_module.list_gateways().await; + let gw = gateways.into_iter().choose(&mut OsRng).map(|gw| gw.info); if let Some(gw) = gw { let gw_id = gw.gateway_id; info!(%gw_id, "Using random gateway");