Skip to content

Commit b734bf4

Browse files
committed
fix: handled possible concurrency issue in file management
1 parent 6d0352a commit b734bf4

File tree

2 files changed

+22
-16
lines changed

2 files changed

+22
-16
lines changed

core/service/src/vault/storage/crypto_material/base.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ where
291291
// Convenience Storage Methods
292292
// =========================
293293

294-
// TODO it seems these methods are never used!
294+
// TODO it seems these methods are never used! Should we remove them?
295295
/// Store CRS (public parameters + private info)
296296
pub async fn store_crs(
297297
&self,
@@ -440,8 +440,6 @@ where
440440
// Ensure_xxx_existence Methods
441441
// =========================
442442

443-
// TODO these methods should either be in threshold.rs or the similar methods there should be moved here
444-
445443
/// Tries to delete all the types of key material related to a specific [RequestId].
446444
pub async fn purge_key_material(
447445
&self,
@@ -492,11 +490,10 @@ where
492490
result.is_err()
493491
};
494492
let f3 = async {
495-
// TODO should backups also be purged here?
496493
match back_vault {
497-
Some(mut x) => {
494+
Some(mut guarded_backup_vault) => {
498495
let result = delete_at_request_id(
499-
&mut (*x),
496+
&mut (*guarded_backup_vault),
500497
req_id,
501498
&BackupDataType::PrivData(PrivDataType::FheKeyInfo).to_string(),
502499
)

core/service/src/vault/storage/crypto_material/threshold.rs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ pub struct ThresholdCryptoMaterialStorage<
4141
PrivS: Storage + Send + Sync + 'static,
4242
> {
4343
pub(crate) inner: CryptoMaterialStorage<PubS, PrivS>,
44+
/// Note that `fhe_keys` should be locked after any locking of elements in `inner`.
4445
fhe_keys: Arc<RwLock<HashMap<RequestId, ThresholdFheKeys>>>,
4546
}
4647

@@ -108,9 +109,15 @@ impl<PubS: Storage + Send + Sync + 'static, PrivS: Storage + Send + Sync + 'stat
108109
// all other locks are taken as needed so that we don't lock up
109110
// other function calls too much
110111
let mut guarded_meta_storage = meta_store.write().await;
112+
// Lock the storage components in the correct order to avoid deadlocks.
113+
let mut pub_storage = self.inner.public_storage.lock().await;
114+
let mut priv_storage = self.inner.private_storage.lock().await;
115+
let back_vault = match self.inner.backup_vault {
116+
Some(ref x) => Some(x.lock().await),
117+
None => None,
118+
};
111119

112120
let f1 = async {
113-
let mut priv_storage = self.inner.private_storage.lock().await;
114121
let store_result = store_versioned_at_request_id(
115122
&mut (*priv_storage),
116123
key_id,
@@ -129,7 +136,6 @@ impl<PubS: Storage + Send + Sync + 'static, PrivS: Storage + Send + Sync + 'stat
129136
store_result.is_ok()
130137
};
131138
let f2 = async {
132-
let mut pub_storage = self.inner.public_storage.lock().await;
133139
let pk_result = store_pk_at_request_id(
134140
&mut (*pub_storage),
135141
key_id,
@@ -154,10 +160,8 @@ impl<PubS: Storage + Send + Sync + 'static, PrivS: Storage + Send + Sync + 'stat
154160
};
155161
let threshold_key_clone = threshold_fhe_keys.clone();
156162
let f3 = async move {
157-
// // TODO ciphertext should be versioned
158-
match self.inner.backup_vault {
159-
Some(ref back_vault) => {
160-
let mut guarded_backup_vault = back_vault.lock().await;
163+
match back_vault {
164+
Some(mut guarded_backup_vault) => {
161165
let backup_result = store_versioned_at_request_id(
162166
&mut (*guarded_backup_vault),
163167
key_id,
@@ -177,8 +181,6 @@ impl<PubS: Storage + Send + Sync + 'static, PrivS: Storage + Send + Sync + 'stat
177181
}
178182
}
179183
};
180-
// TODO since each thread is locking a storage component and they are run concurrently in a single thread
181-
// don't we risk deadlocks with parallel executions since we have no guaranteed on the lock order?
182184
let (r1, r2, r3) = tokio::join!(f1, f2, f3);
183185
// Try to store the new data
184186
tracing::info!("Storing DKG objects for key ID {}", key_id);
@@ -287,6 +289,10 @@ impl<PubS: Storage + Send + Sync + 'static, PrivS: Storage + Send + Sync + 'stat
287289
commitments: BackupCommitments,
288290
meta_store: Arc<RwLock<CustodianMetaStore>>,
289291
) {
292+
// use guarded_meta_store as the synchronization point
293+
// all other locks are taken as needed so that we don't lock up
294+
// other function calls too much
295+
let mut guarded_meta_store = meta_store.write().await;
290296
// Lock the storage needed in correct order to avoid deadlocks.
291297
let mut private_storage_guard = self.inner.private_storage.lock().await;
292298
let mut public_storage_guard = self.inner.public_storage.lock().await;
@@ -343,7 +349,6 @@ impl<PubS: Storage + Send + Sync + 'static, PrivS: Storage + Send + Sync + 'stat
343349
{
344350
// Update meta store
345351
// First we insert the request ID
346-
let mut guarded_meta_store = meta_store.write().await;
347352
// Whether things fail or not we can't do much
348353
match guarded_meta_store.insert(req_id) {
349354
Ok(_) => {}
@@ -381,7 +386,11 @@ impl<PubS: Storage + Send + Sync + 'static, PrivS: Storage + Send + Sync + 'stat
381386
sharing_chain.set_backup_enc_key(pub_key);
382387
}
383388
},
384-
None => todo!(),
389+
None => {
390+
tracing::info!(
391+
"No keychain in backup vault, skipping setting backup encryption key for request {req_id}"
392+
);
393+
},
385394
}
386395
},
387396
None => tracing::warn!(

0 commit comments

Comments
 (0)