Skip to main content

void_core/store/
traits.rs

1//! Object store trait
2
3use crate::cid::VoidCid;
4use crate::Result;
5use void_crypto::EncryptedBlob;
6
7/// Low-level content-addressed storage.
8///
9/// Implementation trait for storage backends (FsStore, etc.).
10/// External callers should use `ObjectStoreExt` typed methods instead.
11pub(crate) trait ObjectStore {
12    /// Writes raw bytes to storage, returning the content-addressed CID.
13    fn write_raw(&self, data: &[u8]) -> Result<VoidCid>;
14
15    /// Reads raw bytes from storage by CID. No integrity verification.
16    fn read_raw(&self, cid: &VoidCid) -> Result<Vec<u8>>;
17
18    /// Checks if an object exists.
19    fn has(&self, cid: &VoidCid) -> Result<bool>;
20
21    /// Deletes an object.
22    fn delete(&self, cid: &VoidCid) -> Result<()>;
23}
24
25/// Typed object store API.
26///
27/// All reads and writes go through typed encrypted blobs, enforcing
28/// correct AAD at the encryption boundary. No raw `&[u8]` in or out.
29pub trait ObjectStoreExt {
30    /// Store a typed encrypted blob, returning its CID.
31    fn put_blob<B: EncryptedBlob>(&self, blob: &B) -> Result<VoidCid>;
32
33    /// Retrieve a typed encrypted blob by CID.
34    ///
35    /// No CID hash verification — AES-GCM's auth tag provides integrity
36    /// when the blob is decrypted.
37    fn get_blob<B: EncryptedBlob>(&self, cid: &VoidCid) -> Result<B>;
38
39    /// Retrieve a typed encrypted blob with CID hash verification.
40    ///
41    /// Re-hashes the content and verifies it matches the CID.
42    /// Use for audit/fsck where CID integrity must be verified
43    /// independent of decryption.
44    fn get_blob_verified<B: EncryptedBlob>(&self, cid: &VoidCid) -> Result<B>;
45
46    /// Checks if an object exists by CID.
47    fn exists(&self, cid: &VoidCid) -> Result<bool>;
48
49    /// Removes an object by CID.
50    fn remove(&self, cid: &VoidCid) -> Result<()>;
51}
52
53// Blanket implementation for all ObjectStore implementors.
54impl<T: ObjectStore + ?Sized> ObjectStoreExt for T {
55    fn put_blob<B: EncryptedBlob>(&self, blob: &B) -> Result<VoidCid> {
56        self.write_raw(blob.as_bytes())
57    }
58
59    fn get_blob<B: EncryptedBlob>(&self, cid: &VoidCid) -> Result<B> {
60        self.read_raw(cid).map(B::from_bytes)
61    }
62
63    fn get_blob_verified<B: EncryptedBlob>(&self, cid: &VoidCid) -> Result<B> {
64        let data = self.read_raw(cid)?;
65        let computed = VoidCid::create(&data);
66        if computed != *cid {
67            return Err(crate::VoidError::IntegrityError {
68                expected: cid.to_string(),
69                actual: computed.to_string(),
70            });
71        }
72        Ok(B::from_bytes(data))
73    }
74
75    fn exists(&self, cid: &VoidCid) -> Result<bool> {
76        self.has(cid)
77    }
78
79    fn remove(&self, cid: &VoidCid) -> Result<()> {
80        self.delete(cid)
81    }
82}