Skip to main content

coven_storage/
objects.rs

1//! Exact-reference access to Store protocol objects.
2
3use super::CloudSyncObjectStorage;
4use coven_protocol::membership::{MembershipEntry, MembershipEntryRef};
5use coven_protocol::objects::{
6    ExactObjectRef, PreparedExactObject, ProtocolObjectContext, ProtocolObjectDomain, StorageError,
7    StoreObjectError,
8};
9use coven_protocol::store_commit::{
10    membership_entry_semantic_prefix, ObjectHash, StoreProtocolError,
11};
12
13pub async fn run_blocking_object_verification<T>(
14    semantic_prefix: &str,
15    object: &ExactObjectRef,
16    verify: Box<dyn FnOnce() -> Result<T, StoreProtocolError> + Send>,
17) -> Result<T, StoreObjectError>
18where
19    T: Send + 'static,
20{
21    coven_foundation::blocking::run(verify)
22        .await
23        .map_err(|source| {
24            StoreObjectError::Storage(StorageError::Blocking {
25                operation: "verify Store object",
26                source,
27            })
28        })?
29        .map_err(|source| StoreObjectError::InvalidObject {
30            semantic_prefix: semantic_prefix.to_string(),
31            key: object.slot().logical_key().to_string(),
32            source: Box::new(source),
33        })
34}
35
36pub async fn prepare_membership_entry(
37    storage: &dyn CloudSyncObjectStorage,
38    store_root_hash: ObjectHash,
39    entry: &MembershipEntry,
40) -> Result<(PreparedExactObject, MembershipEntryRef), StoreObjectError> {
41    let coord = entry.coord();
42    let semantic_prefix = membership_entry_semantic_prefix(
43        &coord.author_pubkey,
44        &coord.author_owner_grant,
45        coord.stream_id,
46        coord.seq,
47        coord.entry_hash,
48    );
49    let context = ProtocolObjectContext::signed_plaintext(
50        store_root_hash,
51        ProtocolObjectDomain::StoreMembershipEntry,
52    );
53    let slot = storage
54        .allocate_protocol_slot(&context, &semantic_prefix, ".json")
55        .await?;
56    let prepared = storage.prepare_protocol_object(
57        &context,
58        slot,
59        &semantic_prefix,
60        serde_json::to_vec(entry).expect("membership entry serialization cannot fail"),
61    )?;
62    let reference = MembershipEntryRef {
63        coord,
64        object: prepared.reference().clone(),
65    };
66    Ok((prepared, reference))
67}