Skip to content

Commit 37e28b4

Browse files
authored
builtin actor registry in system actor (#401)
1 parent 48ca33a commit 37e28b4

File tree

5 files changed

+122
-21
lines changed

5 files changed

+122
-21
lines changed

fvm/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ mod init_actor;
2727
mod market_actor;
2828
mod power_actor;
2929
mod reward_actor;
30+
mod system_actor;
3031

3132
use cid::multihash::{Code, MultihashDigest};
3233
use cid::Cid;
@@ -134,7 +135,7 @@ mod test {
134135
Zero::zero(),
135136
fvm_shared::version::NetworkVersion::V14,
136137
root,
137-
manifest_cid,
138+
(0, Some(manifest_cid)),
138139
bs,
139140
DummyExterns,
140141
)

fvm/src/machine/default.rs

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ use std::ops::RangeInclusive;
22

33
use anyhow::{anyhow, Context as _};
44
use cid::Cid;
5-
use fvm_shared::actor::builtin::Manifest;
5+
use fvm_shared::actor::builtin::{load_manifest, Manifest};
66
use fvm_shared::address::Address;
7-
use fvm_shared::blockstore::{Blockstore, Buffered, CborStore};
7+
use fvm_shared::blockstore::{Blockstore, Buffered};
88
use fvm_shared::clock::ChainEpoch;
99
use fvm_shared::econ::TokenAmount;
1010
use fvm_shared::error::ErrorNumber;
@@ -19,6 +19,7 @@ use crate::externs::Externs;
1919
use crate::gas::price_list_by_network_version;
2020
use crate::kernel::{ClassifyResult, Context as _, Result};
2121
use crate::state_tree::{ActorState, StateTree};
22+
use crate::system_actor::State as SystemActorState;
2223
use crate::{syscall_error, Config};
2324

2425
pub struct DefaultMachine<B, E> {
@@ -56,7 +57,7 @@ where
5657
circ_supply: TokenAmount,
5758
network_version: NetworkVersion,
5859
state_root: Cid,
59-
builtin_actors: Cid,
60+
builtin_actors: (u32, Option<Cid>),
6061
blockstore: B,
6162
externs: E,
6263
) -> anyhow::Result<Self> {
@@ -93,29 +94,29 @@ where
9394
));
9495
}
9596

97+
// Create a new state tree from the supplied root.
98+
let state_tree = {
99+
let bstore = BufferedBlockstore::new(blockstore);
100+
StateTree::new_from_root(bstore, &context.initial_state_root)?
101+
};
102+
96103
// Load the built-in actors manifest.
97104
// TODO: Check that the actor bundle is sane for the network version.
98-
let builtin_actors: Manifest = blockstore
99-
.get_cbor(&builtin_actors)
100-
.context("failed to load built-in actor index")?
101-
.ok_or_else(|| {
102-
anyhow!(
103-
"blockstore doesn't contain builtin actors index with CID {}",
104-
&builtin_actors
105-
)
106-
})?;
105+
let builtin_actors_cid = match builtin_actors.1 {
106+
Some(cid) => cid,
107+
None => {
108+
let (state, _) = SystemActorState::load(&state_tree)?;
109+
state.builtin_actors
110+
}
111+
};
112+
let builtin_actors =
113+
load_manifest(state_tree.store(), &builtin_actors_cid, builtin_actors.0)?;
107114

108115
// Preload any uncached modules.
109116
// This interface works for now because we know all actor CIDs
110117
// ahead of time, but with user-supplied code, we won't have that
111118
// guarantee.
112-
engine.preload(&blockstore, builtin_actors.left_values())?;
113-
114-
// Create a new state tree from the supplied root.
115-
let state_tree = {
116-
let bstore = BufferedBlockstore::new(blockstore);
117-
StateTree::new_from_root(bstore, &context.initial_state_root)?
118-
};
119+
engine.preload(state_tree.store(), builtin_actors.left_values())?;
119120

120121
Ok(DefaultMachine {
121122
config,

fvm/src/system_actor.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
use anyhow::Context;
2+
use cid::Cid;
3+
use serde::{Deserialize, Serialize};
4+
5+
use fvm_shared::address::Address;
6+
use fvm_shared::blockstore::{Blockstore, CborStore};
7+
use fvm_shared::encoding::Cbor;
8+
9+
use crate::kernel::{ClassifyResult, Result};
10+
use crate::state_tree::{ActorState, StateTree};
11+
12+
pub const SYSTEM_ACTOR_ADDR: Address = Address::new_id(0);
13+
14+
#[derive(Default, Deserialize, Serialize)]
15+
pub struct State {
16+
// builtin actor registry: Vec<(String, Cid)>
17+
pub builtin_actors: Cid,
18+
}
19+
impl Cbor for State {}
20+
21+
impl State {
22+
pub fn load<B>(state_tree: &StateTree<B>) -> Result<(Self, ActorState)>
23+
where
24+
B: Blockstore,
25+
{
26+
let system_act = state_tree
27+
.get_actor(&SYSTEM_ACTOR_ADDR)?
28+
.context("system actor address could not be resolved")
29+
.or_fatal()?;
30+
31+
let state = state_tree
32+
.store()
33+
.get_cbor(&system_act.state)
34+
.or_fatal()?
35+
.context("system actor state not found")
36+
.or_fatal()?;
37+
38+
Ok((state, system_act))
39+
}
40+
}

shared/src/actor/builtin.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
use anyhow::anyhow;
12
use bimap::BiBTreeMap;
23
use cid::Cid;
34
use num_derive::FromPrimitive;
45
use serde_repr::{Deserialize_repr, Serialize_repr};
56

7+
use crate::blockstore::{Blockstore, CborStore};
8+
69
/// Identifies the builtin actor types for usage with the
710
/// actor::resolve_builtin_actor_type syscall.
811
#[derive(
@@ -82,5 +85,61 @@ impl TryFrom<&str> for Type {
8285
}
8386
}
8487

88+
impl From<&Type> for String {
89+
fn from(t: &Type) -> String {
90+
match t {
91+
Type::System => "system",
92+
Type::Init => "init",
93+
Type::Cron => "cron",
94+
Type::Account => "account",
95+
Type::Power => "storagepower",
96+
Type::Miner => "storageminer",
97+
Type::Market => "storagemarket",
98+
Type::PaymentChannel => "paymentchannel",
99+
Type::Multisig => "multisig",
100+
Type::Reward => "reward",
101+
Type::VerifiedRegistry => "verifiedregistry",
102+
}
103+
.to_string()
104+
}
105+
}
106+
85107
/// A mapping of builtin actor CIDs to their respective types.
86108
pub type Manifest = BiBTreeMap<Cid, Type>;
109+
110+
pub fn load_manifest<B: Blockstore>(bs: &B, root_cid: &Cid, ver: u32) -> anyhow::Result<Manifest> {
111+
match ver {
112+
0 => load_manifest_v0(bs, root_cid),
113+
1 => load_manifest_v1(bs, root_cid),
114+
_ => Err(anyhow!("unknown manifest version {}", ver)),
115+
}
116+
}
117+
118+
pub fn load_manifest_v0<B: Blockstore>(bs: &B, root_cid: &Cid) -> anyhow::Result<Manifest> {
119+
match bs.get_cbor::<Manifest>(root_cid)? {
120+
Some(mf) => Ok(mf),
121+
None => Err(anyhow!("cannot find manifest root cid {}", root_cid)),
122+
}
123+
}
124+
125+
pub fn load_manifest_v1<B: Blockstore>(bs: &B, root_cid: &Cid) -> anyhow::Result<Manifest> {
126+
let vec: Vec<(String, Cid)> = match bs.get_cbor(root_cid)? {
127+
Some(vec) => vec,
128+
None => {
129+
return Err(anyhow!("cannot find manifest root cid {}", root_cid));
130+
}
131+
};
132+
let mut manifest = Manifest::new();
133+
for (name, code_cid) in vec {
134+
let t = Type::try_from(name.as_str());
135+
match t {
136+
Ok(t) => {
137+
manifest.insert(code_cid, t);
138+
}
139+
Err(what) => {
140+
return Err(anyhow!("bad builtin actor name: {}: {} ", name, what));
141+
}
142+
}
143+
}
144+
Ok(manifest)
145+
}

testing/conformance/src/vm.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ impl TestMachine<Box<DefaultMachine<MemoryBlockstore, TestExterns>>> {
8585
BigInt::zero(),
8686
network_version,
8787
state_root,
88-
builtin_actors,
88+
(0, Some(builtin_actors)),
8989
blockstore,
9090
externs,
9191
)

0 commit comments

Comments
 (0)