Skip to main content

qualia_core_db/net/
fetch_10d.rs

1//! Remote `.10d`-by-hash fetch and verification
2
3use crate::container_10d;
4use crate::net::disclosure::NetworkDisclosureRegistry;
5
6pub struct Fetch10dService {
7    // In a real implementation this would hold WebTorrent or HTTP clients.
8}
9
10impl Fetch10dService {
11    pub fn new() -> Self {
12        Self {}
13    }
14
15    /// Fetches a .10d container by its hash from a specified endpoint,
16    /// verifies the whole-file CRC-32C, and returns the byte payload if valid.
17    pub fn fetch_10d_by_hash(
18        &self,
19        hash: &str,
20        endpoint: &str,
21        registry: &NetworkDisclosureRegistry,
22    ) -> Result<Vec<u8>, String> {
23        // Enforce network disclosure discipline
24        if !registry.check_egress_consent("fetch_10d", endpoint) {
25            return Err(format!("Consent denied to fetch from {}", endpoint));
26        }
27
28        // Mock the fetch. In reality, we'd use `reqwest` or the `WebTorrent` seeder.
29        let bytes = self.mock_network_fetch(endpoint, hash)?;
30
31        // Verify CRC-32C
32        // Because `container_10d::verify_whole_file_crc32c` expects `&mut [u8]`
33        // and modifies the buffer to zeroes out the CRC field temporarily, we need it mutable.
34        let mut verify_bytes = bytes.clone();
35        if let Err(e) = container_10d::verify_whole_file_crc32c(&mut verify_bytes) {
36            return Err(format!("CRC-32C verification failed: {}", e));
37        }
38
39        Ok(bytes)
40    }
41
42    fn mock_network_fetch(&self, _endpoint: &str, _hash: &str) -> Result<Vec<u8>, String> {
43        // Return a dummy valid 10d container payload
44        // Real implementation would make the network call
45        Ok(vec![0; 64]) // Just returning a mock payload for test structure
46    }
47}
48
49#[cfg(test)]
50mod tests {
51    use super::*;
52
53    #[test]
54    fn test_fetch_10d_egress() {
55        let fetcher = Fetch10dService::new();
56        let mut registry = NetworkDisclosureRegistry::new();
57
58        let endpoint = "https://assets.example.com";
59        let hash = "abc123hash";
60
61        // Without registration, it should fail
62        let res1 = fetcher.fetch_10d_by_hash(hash, endpoint, &registry);
63        assert!(res1.is_err());
64        assert!(res1.unwrap_err().contains("Consent denied"));
65
66        // Register the endpoint
67        registry.register_egress(
68            "fetch_10d",
69            endpoint,
70            "Fetch 10d asset by hash",
71            "User requests asset",
72        );
73
74        // Now it should pass the consent check, but the mock payload might fail CRC.
75        // We just assert we don't get the consent error.
76        let res2 = fetcher.fetch_10d_by_hash(hash, endpoint, &registry);
77        assert!(res2.is_err());
78        assert!(res2.unwrap_err().contains("CRC"));
79    }
80}