forest/libp2p_bitswap/
store.rs1use super::*;
5use crate::utils::multihash::MultihashCode;
6use ambassador::delegatable_trait;
7use multihash_derive::MultihashDigest;
8use std::marker::PhantomData;
9
10#[auto_impl::auto_impl(&, Arc)]
12#[delegatable_trait]
13pub trait BitswapStoreRead {
14 fn contains(&self, cid: &Cid) -> anyhow::Result<bool>;
16
17 fn get(&self, cid: &Cid) -> anyhow::Result<Option<Vec<u8>>>;
19}
20
21#[auto_impl::auto_impl(&, Arc)]
23#[delegatable_trait]
24pub trait BitswapStoreReadWrite: BitswapStoreRead + Send + Sync + 'static {
25 type Hashes: MultihashDigest<64>;
27
28 fn insert(&self, block: &Block64<Self::Hashes>) -> anyhow::Result<()>;
30}
31
32pub type Block64<H> = Block<H, 64>;
33
34#[derive(Clone, Debug)]
36pub struct Block<H, const S: usize> {
37 cid: Cid,
39 data: Vec<u8>,
41 _pd: PhantomData<H>,
42}
43
44impl<H, const S: usize> PartialEq for Block<H, S> {
45 fn eq(&self, other: &Self) -> bool {
46 self.cid == other.cid
47 }
48}
49
50impl<H, const S: usize> Eq for Block<H, S> {}
51
52impl<H: MultihashDigest<S>, const S: usize> Block<H, S> {
53 pub fn new(cid: Cid, data: Vec<u8>) -> anyhow::Result<Self> {
56 Self::verify_cid(&cid, &data)?;
57 Ok(Self {
58 cid,
59 data,
60 _pd: Default::default(),
61 })
62 }
63
64 pub fn cid(&self) -> &Cid {
66 &self.cid
67 }
68
69 pub fn data(&self) -> &[u8] {
71 &self.data
72 }
73
74 fn verify_cid(cid: &Cid, payload: &[u8]) -> anyhow::Result<()> {
75 let code = cid.hash().code();
76 anyhow::ensure!(
78 code != u64::from(MultihashCode::Identity) || payload.len() <= S,
79 "identity multihash payload of {} bytes exceeds the {S}-byte limit",
80 payload.len()
81 );
82 let mh = H::try_from(code)
83 .map_err(|_| anyhow::anyhow!("unsupported multihash code {code}"))?
84 .digest(payload);
85 if mh.digest() != cid.hash().digest() {
86 anyhow::bail!("invalid multihash digest");
87 }
88 Ok(())
89 }
90}