Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor the blockstore #1694

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 29 additions & 4 deletions fvm/src/blockstore/buffered.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,33 @@
use std::cell::RefCell;
use std::collections::HashMap;
use std::io::{Cursor, Read, Seek};
use std::marker::PhantomData;

use anyhow::{anyhow, Result};
use byteorder::{BigEndian, ByteOrder, ReadBytesExt};
use cid::Cid;
use fvm_ipld_blockstore::{Blockstore, Buffered};
use fvm_ipld_blockstore::{Block, Blockstore, Buffered};
use fvm_ipld_encoding::{CBOR, DAG_CBOR};
use fvm_shared::commcid::{FIL_COMMITMENT_SEALED, FIL_COMMITMENT_UNSEALED};

/// Wrapper around `Blockstore` to limit and have control over when values are written.
/// This type is not threadsafe and can only be used in synchronous contexts.
#[derive(Debug)]
pub struct BufferedBlockstore<BS> {
pub struct BufferedBlockstore<BS, C = multihash::Code> {
base: BS,
write: RefCell<HashMap<Cid, Vec<u8>>>,
_marker: PhantomData<fn() -> C>,
}

impl<BS> BufferedBlockstore<BS>
impl<BS, C> BufferedBlockstore<BS, C>
where
BS: Blockstore,
{
pub fn new(base: BS) -> Self {
Self {
base,
write: Default::default(),
_marker: Default::default(),
}
}

Expand All @@ -37,6 +40,20 @@ where
}
}

impl<BS, C> BufferedBlockstore<BS, C>
where
C: multihash::MultihashDigest<64>,
anyhow::Error: From<C::Error>,
{
fn cid_of(&self, mh_code: u64, block: &dyn Block) -> Result<Cid> {
let mh_code = C::try_from(mh_code)?;
let data = block.data();
let codec = block.codec();
let digest = mh_code.digest(data);
Ok(Cid::new_v1(codec, digest))
}
}

impl<BS> Buffered for BufferedBlockstore<BS>
where
BS: Blockstore,
Expand Down Expand Up @@ -229,9 +246,11 @@ fn copy_rec<'a>(
Ok(())
}

impl<BS> Blockstore for BufferedBlockstore<BS>
impl<BS, C> Blockstore for BufferedBlockstore<BS, C>
where
BS: Blockstore,
C: multihash::MultihashDigest<64>,
anyhow::Error: From<C::Error>,
{
fn get(&self, cid: &Cid) -> Result<Option<Vec<u8>>> {
Ok(if let Some(data) = self.write.borrow().get(cid) {
Expand All @@ -241,6 +260,12 @@ where
})
}

fn put(&self, mh_code: u64, block: &dyn fvm_ipld_blockstore::Block) -> Result<Cid> {
let k = self.cid_of(mh_code, block)?;
self.put_keyed(&k, block.data())?;
Ok(k)
}

fn put_keyed(&self, cid: &Cid, buf: &[u8]) -> Result<()> {
self.write.borrow_mut().insert(*cid, Vec::from(buf));
Ok(())
Expand Down
51 changes: 48 additions & 3 deletions fvm/src/blockstore/discard.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,67 @@
// Copyright 2021-2023 Protocol Labs
// SPDX-License-Identifier: Apache-2.0, MIT

use std::marker::PhantomData;

use cid::Cid;
use fvm_ipld_blockstore::Blockstore;

// A blockstore that accepts but discards all insertions, and returns errors on reads.
// Useful for when the FVM needs to stage ephemeral data structures without persisting them,
// like the events AMT.
pub struct DiscardBlockstore;
#[derive(Copy, Clone)]
pub struct DiscardBlockstore<C = multihash::Code>(PhantomData<fn() -> C>);

impl Default for DiscardBlockstore {
fn default() -> Self {
DiscardBlockstore(Default::default())
}
}

impl Blockstore for DiscardBlockstore {
impl<C> Blockstore for DiscardBlockstore<C>
where
C: multihash::MultihashDigest<64>,
anyhow::Error: From<C::Error>,
{
fn get(&self, _: &Cid) -> anyhow::Result<Option<Vec<u8>>> {
Err(anyhow::anyhow!(
"Blockstore#get not supported with DiscardBlockstore"
"Blockstore::get not supported with DiscardBlockstore"
))
}

fn put_keyed(&self, _: &Cid, _: &[u8]) -> anyhow::Result<()> {
Ok(())
}

fn put(&self, mh_code: u64, block: &dyn fvm_ipld_blockstore::Block) -> anyhow::Result<Cid> {
let mh_code = C::try_from(mh_code)?;
let data = block.data();
let codec = block.codec();
let digest = mh_code.digest(data);
Ok(Cid::new_v1(codec, digest))
}

fn has(&self, _: &Cid) -> anyhow::Result<bool> {
Err(anyhow::anyhow!(
"Blockstore::has not supported with DiscardBlockstore"
))
}

fn put_many<B, I>(&self, _: I) -> anyhow::Result<()>
where
Self: Sized,
B: fvm_ipld_blockstore::Block,
I: IntoIterator<Item = (u64, B)>,
{
Ok(())
}

fn put_many_keyed<D, I>(&self, _: I) -> anyhow::Result<()>
where
Self: Sized,
D: AsRef<[u8]>,
I: IntoIterator<Item = (Cid, D)>,
{
Ok(())
}
}
2 changes: 1 addition & 1 deletion fvm/src/call_manager/default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -928,7 +928,7 @@ impl EventsAccumulator {
let root = if !self.events.is_empty() {
const EVENTS_AMT_BITWIDTH: u32 = 5;
let root = Amt::new_from_iter_with_bit_width(
DiscardBlockstore,
DiscardBlockstore::default(),
EVENTS_AMT_BITWIDTH,
self.events.iter().cloned(),
)
Expand Down
10 changes: 6 additions & 4 deletions fvm/src/machine/default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use std::ops::RangeInclusive;

use anyhow::{anyhow, Context as _};
use cid::Cid;
use fvm_ipld_blockstore::{Block, Blockstore, Buffered};
use fvm_ipld_blockstore::{Blockstore, Buffered};
use fvm_ipld_encoding::ipld_block::IpldBlock;
use fvm_ipld_encoding::{to_vec, CborStore, DAG_CBOR};
use fvm_shared::version::NetworkVersion;
use log::debug;
Expand All @@ -24,8 +25,9 @@ use crate::EMPTY_ARR_CID;

lazy_static::lazy_static! {
/// Pre-serialized block containing the empty array
pub static ref EMPTY_ARRAY_BLOCK: Block<Vec<u8>> = {
Block::new(DAG_CBOR, to_vec::<[(); 0]>(&[]).unwrap())
pub static ref EMPTY_ARRAY_BLOCK: IpldBlock = IpldBlock {
codec: DAG_CBOR,
data: to_vec::<[(); 0]>(&[]).unwrap(),
};
}

Expand Down Expand Up @@ -194,7 +196,7 @@ where
// Helper method that puts certain "empty" types in the blockstore.
// These types are privileged by some parts of the system (eg. as the default actor state).
fn put_empty_blocks<B: Blockstore>(blockstore: B) -> anyhow::Result<()> {
let empty_arr_cid = blockstore.put(Blake2b256, &EMPTY_ARRAY_BLOCK)?;
let empty_arr_cid = blockstore.put(Blake2b256.into(), &*EMPTY_ARRAY_BLOCK)?;

debug_assert!(
empty_arr_cid == *EMPTY_ARR_CID,
Expand Down
2 changes: 1 addition & 1 deletion fvm/tests/default_kernel/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::rc::Rc;

// test target
use fvm::kernel::default::DefaultKernel;
use fvm::kernel::{Block, BlockRegistry};
use fvm::kernel::BlockRegistry;
use fvm::Kernel;
use multihash::Code;
use num_traits::Zero;
Expand Down
3 changes: 1 addition & 2 deletions fvm/tests/default_kernel/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,6 @@ mod ipld {
"charge_gas should only be called exactly once per block_link"
);

let expected_block = Block::new(cid.codec(), block);
let expected_create_price = call_manager
.machine
.context()
Expand All @@ -190,7 +189,7 @@ mod ipld {
.price_list
.on_block_link(
SupportedHashes::try_from(cid.hash().code()).unwrap(),
expected_block.size() as usize,
block.len(),
)
.total();

Expand Down
5 changes: 5 additions & 0 deletions ipld/blockstore/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,10 @@ anyhow = "1.0.51"
# depdendency is needed to enable the features of the re-export.
multihash = { version = "0.16.1", default-features = false, features = ["multihash-impl"] }

[dev-dependencies.multihash]
version = "*"
default-features = false
features = ["multihash-impl", "blake2b"]

[features]
default = []
57 changes: 0 additions & 57 deletions ipld/blockstore/src/block.rs

This file was deleted.

Loading