1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
// Copyright 2021-2023 Protocol Labs
// SPDX-License-Identifier: Apache-2.0, MIT
use std::rc::Rc;
use std::sync::Arc;
use anyhow::Result;
use cid::{multihash, Cid};
pub mod tracking;
mod memory;
pub use memory::MemoryBlockstore;
mod block;
pub use block::*;
/// An IPLD blockstore suitable for injection into the FVM.
///
/// The cgo blockstore adapter implements this trait.
pub trait Blockstore {
/// Gets the block from the blockstore.
fn get(&self, k: &Cid) -> Result<Option<Vec<u8>>>;
/// Put a block with a pre-computed cid.
///
/// If you don't yet know the CID, use put. Some blockstores will re-compute the CID internally
/// even if you provide it.
///
/// If you _do_ already know the CID, use this method as some blockstores _won't_ recompute it.
fn put_keyed(&self, k: &Cid, block: &[u8]) -> Result<()>;
/// Checks if the blockstore has the specified block.
fn has(&self, k: &Cid) -> Result<bool> {
Ok(self.get(k)?.is_some())
}
/// Puts the block into the blockstore, computing the hash with the specified multicodec.
///
/// By default, this defers to put.
fn put<D>(&self, mh_code: multihash::Code, block: &Block<D>) -> Result<Cid>
where
Self: Sized,
D: AsRef<[u8]>,
{
let k = block.cid(mh_code);
self.put_keyed(&k, block.as_ref())?;
Ok(k)
}
/// Bulk put blocks into the blockstore.
///
///
/// ```rust
/// use multihash::Code::Blake2b256;
/// use fvm_ipld_blockstore::{Blockstore, MemoryBlockstore, Block};
///
/// let bs = MemoryBlockstore::default();
/// let blocks = vec![Block::new(0x55, vec![0, 1, 2])];
/// bs.put_many(blocks.iter().map(|b| (Blake2b256, b.into()))).unwrap();
/// ```
fn put_many<D, I>(&self, blocks: I) -> Result<()>
where
Self: Sized,
D: AsRef<[u8]>,
I: IntoIterator<Item = (multihash::Code, Block<D>)>,
{
self.put_many_keyed(blocks.into_iter().map(|(mc, b)| (b.cid(mc), b)))?;
Ok(())
}
/// Bulk-put pre-keyed blocks into the blockstore.
///
/// By default, this defers to put_keyed.
fn put_many_keyed<D, I>(&self, blocks: I) -> Result<()>
where
Self: Sized,
D: AsRef<[u8]>,
I: IntoIterator<Item = (Cid, D)>,
{
for (c, b) in blocks {
self.put_keyed(&c, b.as_ref())?
}
Ok(())
}
}
pub trait Buffered: Blockstore {
fn flush(&self, root: &Cid) -> Result<()>;
}
macro_rules! impl_blockstore {
($($typ:ty),+) => {
$(
impl<BS> Blockstore for $typ where
BS: Blockstore, {
fn get(&self, k: &Cid) -> Result<Option<Vec<u8>>> {
(**self).get(k)
}
fn put_keyed(&self, k: &Cid, block: &[u8]) -> Result<()> {
(**self).put_keyed(k, block)
}
fn has(&self, k: &Cid) -> Result<bool> {
(**self).has(k)
}
fn put<D>(&self, mh_code: multihash::Code, block: &Block<D>) -> Result<Cid>
where
Self: Sized,
D: AsRef<[u8]>,
{
(**self).put(mh_code, block)
}
fn put_many<D, I>(&self, blocks: I) -> Result<()>
where
Self: Sized,
D: AsRef<[u8]>,
I: IntoIterator<Item = (multihash::Code, Block<D>)>,
{
(**self).put_many(blocks)
}
fn put_many_keyed<D, I>(&self, blocks: I) -> Result<()>
where
Self: Sized,
D: AsRef<[u8]>,
I: IntoIterator<Item = (Cid, D)>,
{
(**self).put_many_keyed(blocks)
}
}
)+
}
}
impl_blockstore!(Arc<BS>, Rc<BS>, &BS);