Skip to content
This repository has been archived by the owner on Feb 3, 2025. It is now read-only.

Commit

Permalink
Wrap fedimint around an async rwlock
Browse files Browse the repository at this point in the history
  • Loading branch information
TonyGiorgio authored and benthecarman committed Jan 2, 2024
1 parent 9646fb8 commit 2f0b903
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 24 deletions.
54 changes: 51 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions mutiny-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ gluesql = { version = "0.15", default-features = false, features = ["memory-stor
gluesql-core = "0.15.0"
bincode = "1.3.3"
hex = "0.4.3"
async-lock = "3.2.0"

fedimint-client = { git = "https://github.com/fedimint/fedimint.git", rev = "51d09c76b8a15615114d4f2c2663c738d8ff3135" }
fedimint-core = { git = "https://github.com/fedimint/fedimint.git", rev = "51d09c76b8a15615114d4f2c2663c738d8ff3135" }
Expand Down
42 changes: 21 additions & 21 deletions mutiny-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,13 @@ use crate::{nodemanager::NodeManager, nostr::ProfileType};
use crate::{nostr::NostrManager, utils::sleep};
use ::nostr::key::XOnlyPublicKey;
use ::nostr::{Event, JsonUtil, Kind, Metadata};
use async_lock::RwLock;
use bdk_chain::ConfirmationTime;
use bip39::Mnemonic;
use bitcoin::util::bip32::ExtendedPrivKey;
use bitcoin::{hashes::sha256, Network};
use fedimint_core::{api::InviteCode, config::FederationId, BitcoinHash};
use futures::{pin_mut, select, FutureExt};
use futures_util::lock::Mutex;
use lightning::{log_debug, util::logger::Logger};
use lightning::{log_error, log_info, log_warn};
use lightning_invoice::Bolt11Invoice;
Expand Down Expand Up @@ -505,7 +505,7 @@ impl<S: MutinyStorage> MutinyWalletBuilder<S> {
.await?;
(federations, Some(glue_db))
} else {
(Arc::new(Mutex::new(HashMap::new())), None)
(Arc::new(RwLock::new(HashMap::new())), None)
};

if !self.skip_hodl_invoices {
Expand All @@ -522,7 +522,7 @@ impl<S: MutinyStorage> MutinyWalletBuilder<S> {
glue_db,
node_manager,
nostr,
federation_storage: Arc::new(Mutex::new(federation_storage)),
federation_storage: Arc::new(RwLock::new(federation_storage)),
federations,
stop,
logger,
Expand Down Expand Up @@ -572,8 +572,8 @@ pub struct MutinyWallet<S: MutinyStorage> {
glue_db: Option<GlueDB>,
pub node_manager: Arc<NodeManager<S>>,
pub nostr: Arc<NostrManager<S>>,
pub federation_storage: Arc<Mutex<FederationStorage>>,
pub(crate) federations: Arc<Mutex<HashMap<FederationId, Arc<FederationClient>>>>,
pub federation_storage: Arc<RwLock<FederationStorage>>,
pub(crate) federations: Arc<RwLock<HashMap<FederationId, Arc<FederationClient>>>>,
pub stop: Arc<AtomicBool>,
pub logger: Arc<MutinyLogger>,
network: Network,
Expand Down Expand Up @@ -742,7 +742,7 @@ impl<S: MutinyStorage> MutinyWallet<S> {
// Try each federation first
let federation_ids = self.list_federation_ids().await?;
for federation_id in federation_ids {
if let Some(fedimint_client) = self.federations.lock().await.get(&federation_id) {
if let Some(fedimint_client) = self.federations.read().await.get(&federation_id) {
// Check if the federation has enough balance
let balance = fedimint_client.get_balance().await?;
if balance >= send_msat / 1_000 {
Expand Down Expand Up @@ -840,7 +840,7 @@ impl<S: MutinyStorage> MutinyWallet<S> {
// Attempt to create federation invoice
if !federation_ids.is_empty() {
let federation_id = &federation_ids[0];
let fedimint_client = self.federations.lock().await.get(federation_id).cloned();
let fedimint_client = self.federations.read().await.get(federation_id).cloned();

if let Some(client) = fedimint_client {
if let Ok(inv) = client
Expand Down Expand Up @@ -873,7 +873,7 @@ impl<S: MutinyStorage> MutinyWallet<S> {
let mut activities = self.node_manager.get_activity().await?;

// Directly iterate over federation clients to get their activities
let federations = self.federations.lock().await;
let federations = self.federations.read().await;
for (_fed_id, federation) in federations.iter() {
let federation_activities = federation.get_activity().await?;
activities.extend(federation_activities);
Expand Down Expand Up @@ -903,7 +903,7 @@ impl<S: MutinyStorage> MutinyWallet<S> {
}

// If not found in node manager, search in federations
let federations = self.federations.lock().await;
let federations = self.federations.read().await;
for (_fed_id, federation) in federations.iter() {
if let Ok(invoice) = federation.get_invoice_by_hash(hash).await {
return Ok(invoice);
Expand Down Expand Up @@ -1246,7 +1246,7 @@ impl<S: MutinyStorage> MutinyWallet<S> {

/// Lists the federation id's of the federation clients in the manager.
pub async fn list_federations(&self) -> Result<Vec<FederationIdentity>, MutinyError> {
let federations = self.federations.lock().await;
let federations = self.federations.read().await;
let federation_identities = federations
.iter()
.map(|(_, n)| n.get_mutiny_federation_identity())
Expand All @@ -1256,7 +1256,7 @@ impl<S: MutinyStorage> MutinyWallet<S> {

/// Lists the federation id's of the federation clients in the manager.
pub async fn list_federation_ids(&self) -> Result<Vec<FederationId>, MutinyError> {
let federations = self.federations.lock().await;
let federations = self.federations.read().await;
let federation_identities = federations
.iter()
.map(|(_, n)| n.fedimint_client.federation_id())
Expand All @@ -1266,12 +1266,12 @@ impl<S: MutinyStorage> MutinyWallet<S> {

/// Removes a federation by setting its archived status to true, based on the FederationId.
pub async fn remove_federation(&self, federation_id: FederationId) -> Result<(), MutinyError> {
let mut federations_guard = self.federations.lock().await;
let mut federations_guard = self.federations.write().await;

if let Some(fedimint_client) = federations_guard.get(&federation_id) {
let uuid = &fedimint_client.uuid;

let mut federation_storage_guard = self.federation_storage.lock().await;
let mut federation_storage_guard = self.federation_storage.write().await;

if federation_storage_guard.federations.contains_key(uuid) {
federation_storage_guard.federations.remove(uuid);
Expand All @@ -1292,7 +1292,7 @@ impl<S: MutinyStorage> MutinyWallet<S> {
let federation_ids = self.list_federation_ids().await?;
let mut total_balance = 0;

let federations = self.federations.lock().await;
let federations = self.federations.read().await;
for fed_id in federation_ids {
let balance = federations
.get(&fed_id)
Expand All @@ -1307,7 +1307,7 @@ impl<S: MutinyStorage> MutinyWallet<S> {
}

pub async fn get_federation_balances(&self) -> Result<FederationBalances, MutinyError> {
let federation_lock = self.federations.lock().await;
let federation_lock = self.federations.read().await;

let federation_ids = self.list_federation_ids().await?;
let mut balances = Vec::with_capacity(federation_ids.len());
Expand Down Expand Up @@ -1367,7 +1367,7 @@ async fn create_federations(
c: &MutinyWalletConfig,
g: GlueDB,
logger: &Arc<MutinyLogger>,
) -> Result<Arc<Mutex<HashMap<FederationId, Arc<FederationClient>>>>, MutinyError> {
) -> Result<Arc<RwLock<HashMap<FederationId, Arc<FederationClient>>>>, MutinyError> {
let federations = federation_storage.federations.into_iter();
let mut federation_map = HashMap::new();
for federation_item in federations {
Expand All @@ -1385,7 +1385,7 @@ async fn create_federations(

federation_map.insert(id, Arc::new(federation));
}
let federations = Arc::new(Mutex::new(federation_map));
let federations = Arc::new(RwLock::new(federation_map));
Ok(federations)
}

Expand All @@ -1397,14 +1397,14 @@ pub(crate) async fn create_new_federation<S: MutinyStorage>(
g: GlueDB,
network: Network,
logger: Arc<MutinyLogger>,
federation_storage: Arc<Mutex<FederationStorage>>,
federations: Arc<Mutex<HashMap<FederationId, Arc<FederationClient>>>>,
federation_storage: Arc<RwLock<FederationStorage>>,
federations: Arc<RwLock<HashMap<FederationId, Arc<FederationClient>>>>,
federation_code: InviteCode,
) -> Result<FederationIdentity, MutinyError> {
// Begin with a mutex lock so that nothing else can
// save or alter the federation list while it is about to
// be saved.
let mut federation_mutex = federation_storage.lock().await;
let mut federation_mutex = federation_storage.write().await;

// Get the current federations so that we can check if the new federation already exists
let mut existing_federations = storage.get_federations()?;
Expand Down Expand Up @@ -1450,7 +1450,7 @@ pub(crate) async fn create_new_federation<S: MutinyStorage>(
.get_meta("federation_expiry_timestamp");
let welcome_message = new_federation.fedimint_client.get_meta("welcome_message");
federations
.lock()
.write()
.await
.insert(federation_id, Arc::new(new_federation));

Expand Down

0 comments on commit 2f0b903

Please sign in to comment.