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

fix: make the empty array CID const and export it #668

Merged
merged 1 commit into from
Sep 20, 2022
Merged
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
4 changes: 2 additions & 2 deletions runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ fvm_shared = { version = "2.0.0-alpha.2", default-features = false }
num-traits = "0.2.14"
num-derive = "0.3.3"
serde = { version = "1.0.136", features = ["derive"] }
lazy_static = "1.4.0"
lazy_static = { version = "1.4.0", optional = true }
unsigned-varint = "0.7.1"
integer-encoding = { version = "3.0.3", default-features = false }
byteorder = "1.4.3"
Expand Down Expand Up @@ -78,4 +78,4 @@ no-provider-deal-collateral = []
# fake proofs (for testing)
fake-proofs = []

test_utils = ["hex", "multihash/sha2"]
test_utils = ["hex", "multihash/sha2", "lazy_static"]
37 changes: 37 additions & 0 deletions runtime/src/runtime/empty.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use std::mem;

use cid::multihash::Multihash;
use cid::Cid;
use fvm_ipld_encoding::DAG_CBOR;
use fvm_shared::crypto::hash::SupportedHashes;

const fn const_unwrap<T: Copy, E>(r: Result<T, E>) -> T {
let v = match r {
Ok(r) => r,
Err(_) => panic!(),
};
mem::forget(r);
v
}

// 45b0cfc220ceec5b7c1c62c4d4193d38e4eba48e8815729ce75f9c0ab0e4c1c0
const EMPTY_ARR_HASH_DIGEST: &[u8] = &[
0x45, 0xb0, 0xcf, 0xc2, 0x20, 0xce, 0xec, 0x5b, 0x7c, 0x1c, 0x62, 0xc4, 0xd4, 0x19, 0x3d, 0x38,
0xe4, 0xeb, 0xa4, 0x8e, 0x88, 0x15, 0x72, 0x9c, 0xe7, 0x5f, 0x9c, 0x0a, 0xb0, 0xe4, 0xc1, 0xc0,
];

// bafy2bzacebc3bt6cedhoyw34drrmjvazhu4oj25er2ebk4u445pzycvq4ta4a
pub const EMPTY_ARR_CID: Cid = Cid::new_v1(
DAG_CBOR,
const_unwrap(Multihash::wrap(SupportedHashes::Blake2b256 as u64, EMPTY_ARR_HASH_DIGEST)),
);

#[test]
fn test_empty_arr_cid() {
use cid::multihash::{Code, MultihashDigest};
use fvm_ipld_encoding::to_vec;

let empty = to_vec::<[(); 0]>(&[]).unwrap();
let expected = Cid::new_v1(DAG_CBOR, Code::Blake2b256.digest(&empty));
assert_eq!(EMPTY_ARR_CID, expected);
}
14 changes: 4 additions & 10 deletions runtime/src/runtime/fvm.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use anyhow::{anyhow, Error};
use cid::multihash::{Code, MultihashDigest};
use cid::multihash::Code;
use cid::Cid;
use fvm_ipld_blockstore::Blockstore;
use fvm_ipld_encoding::{to_vec, Cbor, CborStore, RawBytes, DAG_CBOR};
use fvm_ipld_encoding::{Cbor, CborStore, RawBytes, DAG_CBOR};
use fvm_sdk as fvm;
use fvm_sdk::NO_DATA_BLOCK_ID;
use fvm_shared::address::Address;
Expand Down Expand Up @@ -30,13 +30,7 @@ use crate::runtime::{
};
use crate::{actor_error, ActorError, Runtime};

lazy_static::lazy_static! {
/// Cid of the empty array Cbor bytes (`EMPTY_ARR_BYTES`).
pub static ref EMPTY_ARR_CID: Cid = {
let empty = to_vec::<[(); 0]>(&[]).unwrap();
Cid::new_v1(DAG_CBOR, Code::Blake2b256.digest(&empty))
};
}
use super::EMPTY_ARR_CID;

/// A runtime that bridges to the FVM environment through the FVM SDK.
pub struct FvmRuntime<B = ActorBlockstore> {
Expand Down Expand Up @@ -231,7 +225,7 @@ where

fn create<C: Cbor>(&mut self, obj: &C) -> Result<(), ActorError> {
let root = fvm::sself::root()?;
if root != *EMPTY_ARR_CID {
if root != EMPTY_ARR_CID {
return Err(
actor_error!(illegal_state; "failed to create state; expected empty array CID, got: {}", root),
);
Expand Down
3 changes: 3 additions & 0 deletions runtime/src/runtime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ mod actor_blockstore;
#[cfg(feature = "fil-actor")]
pub mod fvm;

pub(crate) mod empty;
pub use empty::EMPTY_ARR_CID;

/// Runtime is the VM's internal runtime object.
/// this is everything that is accessible to actors, beyond parameters.
pub trait Runtime<BS: Blockstore>: Primitives + Verifier + RuntimePolicy {
Expand Down
10 changes: 3 additions & 7 deletions test_vm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use fil_actors_runtime::cbor::serialize;
use fil_actors_runtime::runtime::builtins::Type;
use fil_actors_runtime::runtime::{
ActorCode, DomainSeparationTag, MessageInfo, Policy, Primitives, Runtime, RuntimePolicy,
Verifier,
Verifier, EMPTY_ARR_CID,
};
use fil_actors_runtime::test_utils::*;
use fil_actors_runtime::MessageAccumulator;
Expand Down Expand Up @@ -66,7 +66,6 @@ pub struct VM<'bs> {
total_fil: TokenAmount,
actors_dirty: RefCell<bool>,
actors_cache: RefCell<HashMap<Address, Actor>>,
empty_obj_cid: Cid,
network_version: NetworkVersion,
curr_epoch: ChainEpoch,
invocations: RefCell<Vec<InvocationTrace>>,
Expand Down Expand Up @@ -111,14 +110,12 @@ pub const FIRST_TEST_USER_ADDR: ActorID = FIRST_NON_SINGLETON_ADDR + 3;
impl<'bs> VM<'bs> {
pub fn new(store: &'bs MemoryBlockstore) -> VM<'bs> {
let mut actors = Hamt::<&'bs MemoryBlockstore, Actor, BytesKey, Sha256>::new(store);
let empty = store.put_cbor(&(), Code::Blake2b256).unwrap();
VM {
store,
state_root: RefCell::new(actors.flush().unwrap()),
total_fil: TokenAmount::zero(),
actors_dirty: RefCell::new(false),
actors_cache: RefCell::new(HashMap::new()),
empty_obj_cid: empty,
network_version: NetworkVersion::V16,
curr_epoch: ChainEpoch::zero(),
invocations: RefCell::new(vec![]),
Expand Down Expand Up @@ -256,7 +253,6 @@ impl<'bs> VM<'bs> {
total_fil: self.total_fil,
actors_dirty: RefCell::new(false),
actors_cache: RefCell::new(HashMap::new()),
empty_obj_cid: self.empty_obj_cid,
network_version: self.network_version,
curr_epoch: epoch,
invocations: RefCell::new(vec![]),
Expand Down Expand Up @@ -683,7 +679,7 @@ impl<'invocation, 'bs> Runtime<&'bs MemoryBlockstore> for InvocationCtx<'invocat
"attempt to create new actor at existing address".to_string(),
));
}
let a = actor(code_id, self.v.empty_obj_cid, 0, TokenAmount::zero());
let a = actor(code_id, EMPTY_ARR_CID, 0, TokenAmount::zero());
self.v.set_actor(addr, a);
Ok(())
}
Expand Down Expand Up @@ -838,7 +834,7 @@ impl<'invocation, 'bs> Runtime<&'bs MemoryBlockstore> for InvocationCtx<'invocat
"failed to create state".to_string(),
)),
Some(mut act) => {
if act.head != self.v.empty_obj_cid {
if act.head != EMPTY_ARR_CID {
Err(ActorError::unchecked(
ExitCode::SYS_ASSERTION_FAILED,
"failed to construct state: already initialized".to_string(),
Expand Down