Skip to content

Commit

Permalink
Adapt fvm to blockstore changes
Browse files Browse the repository at this point in the history
  • Loading branch information
Stebalien committed Mar 3, 2023
1 parent f4f0f8c commit 5bed4e0
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 19 deletions.
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
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,7 @@ impl fvm_ipld_blockstore::Blockstore for Blockstore {
Ok(())
}

fn put<D>(&self, code: Code, block: &Block<D>) -> Result<Cid>
where
D: AsRef<[u8]>,
{
fn put(&self, mh_code: u64, block: &dyn Block) -> Result<Cid> {
// TODO: Don't hard-code the size. Unfortunately, there's no good way to get it from the
// codec at the moment.
const SIZE: u32 = 32;
Expand Down

0 comments on commit 5bed4e0

Please sign in to comment.