Skip to main content

void_core/store/
network.rs

1//! Network-backed remote store.
2//!
3//! Bridges async `BlockTransport` (daemon) to sync `RemoteStore` (pipeline).
4//! CID verification happens here — the transport layer deals in raw bytes,
5//! this layer verifies content hashes on fetch.
6
7use std::sync::Arc;
8
9use crate::cid::{self, VoidCid};
10use crate::store::RemoteStore;
11use crate::transport::BlockTransport;
12use crate::{Result, VoidError};
13
14/// Bridges an async `BlockTransport` to the sync `RemoteStore` trait.
15///
16/// The pipeline code is synchronous. The daemon is async. This adapter
17/// holds a tokio runtime handle and calls `block_on` to bridge the gap.
18///
19/// # Safety
20///
21/// Must NOT be called from within a tokio async context — that would
22/// deadlock. The CLI's main thread (which runs the pipeline) is not
23/// inside tokio, so this is safe.
24pub struct NetworkRemoteStore {
25    transport: Arc<dyn BlockTransport>,
26    runtime: tokio::runtime::Handle,
27}
28
29impl NetworkRemoteStore {
30    /// Create a new adapter wrapping a `BlockTransport`.
31    pub fn new(transport: Arc<dyn BlockTransport>, runtime: tokio::runtime::Handle) -> Self {
32        Self { transport, runtime }
33    }
34}
35
36impl RemoteStore for NetworkRemoteStore {
37    fn fetch_raw(&self, cid_obj: &VoidCid) -> Result<Vec<u8>> {
38        let data = self.runtime.block_on(self.transport.get(cid_obj))?;
39
40        // Verify content matches CID.
41        let computed = cid::create(&data);
42        if computed != *cid_obj {
43            return Err(VoidError::IntegrityError {
44                expected: cid_obj.to_string(),
45                actual: computed.to_string(),
46            });
47        }
48
49        Ok(data)
50    }
51
52    fn push_raw(&self, data: &[u8]) -> Result<VoidCid> {
53        let cid_obj = cid::create(data);
54        self.runtime.block_on(self.transport.put(&cid_obj, data))?;
55        Ok(cid_obj)
56    }
57
58    fn exists(&self, cid_obj: &VoidCid) -> Result<bool> {
59        self.runtime.block_on(self.transport.has(cid_obj))
60    }
61
62    fn pin(&self, _cid: &VoidCid) -> Result<()> {
63        // Pinning is implicit — blocks stored locally + DHT provided on put.
64        Ok(())
65    }
66}