Skip to content

Commit bca2478

Browse files
authored
Merge pull request #490 from filecoin-project/feat/refactor-constructor
refactor: combine/refactor context/config/machine arguments
2 parents 8799f1d + b7bb780 commit bca2478

File tree

9 files changed

+142
-109
lines changed

9 files changed

+142
-109
lines changed

fvm/src/call_manager/default.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ where
100100
//
101101
// NOTE: Unlike the FVM, Lotus adds _then_ checks. It does this because the
102102
// `call_stack_depth` in lotus is 0 for the top-level call, unlike in the FVM where it's 1.
103-
if self.call_stack_depth > self.machine.config().max_call_depth {
103+
if self.call_stack_depth > self.machine.context().max_call_depth {
104104
return Err(
105105
syscall_error!(LimitExceeded, "message execution exceeds call depth").into(),
106106
);

fvm/src/kernel/default.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -915,7 +915,7 @@ where
915915
}
916916

917917
fn debug_enabled(&self) -> bool {
918-
self.call_manager.context().debug
918+
self.call_manager.context().actor_debugging
919919
}
920920
}
921921

fvm/src/lib.rs

Lines changed: 6 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -42,37 +42,19 @@ lazy_static::lazy_static! {
4242
};
4343
}
4444

45-
#[derive(Clone)]
46-
pub struct Config {
47-
/// The maximum call depth.
48-
pub max_call_depth: u32,
49-
/// Whether debug mode is enabled or not.
50-
pub debug: bool,
51-
}
52-
53-
impl Default for Config {
54-
fn default() -> Self {
55-
Self {
56-
max_call_depth: 4096,
57-
debug: false,
58-
}
59-
}
60-
}
61-
6245
#[cfg(test)]
6346
mod test {
6447
use fvm_ipld_blockstore::MemoryBlockstore;
6548
use fvm_ipld_encoding::CborStore;
6649
use fvm_shared::actor::builtin::Manifest;
6750
use fvm_shared::state::StateTreeVersion;
6851
use multihash::Code;
69-
use num_traits::Zero;
7052

7153
use crate::call_manager::DefaultCallManager;
7254
use crate::externs::{Consensus, Externs, Rand};
73-
use crate::machine::{DefaultMachine, Engine};
55+
use crate::machine::{DefaultMachine, Engine, NetworkConfig};
7456
use crate::state_tree::StateTree;
75-
use crate::{executor, Config, DefaultKernel};
57+
use crate::{executor, DefaultKernel};
7658

7759
struct DummyExterns;
7860

@@ -125,14 +107,10 @@ mod test {
125107
let actors_cid = bs.put_cbor(&(0, manifest_cid), Code::Blake2b256).unwrap();
126108

127109
let machine = DefaultMachine::new(
128-
Config::default(),
129-
Engine::default(),
130-
0,
131-
Zero::zero(),
132-
Zero::zero(),
133-
fvm_shared::version::NetworkVersion::V14,
134-
root,
135-
Some(actors_cid),
110+
&Engine::default(),
111+
&NetworkConfig::new(fvm_shared::version::NetworkVersion::V14)
112+
.override_actors(actors_cid)
113+
.for_epoch(0, root),
136114
bs,
137115
DummyExterns,
138116
)

fvm/src/machine/boxed.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ use fvm_shared::ActorID;
77
use super::{Engine, Machine, MachineContext};
88
use crate::kernel::Result;
99
use crate::state_tree::{ActorState, StateTree};
10-
use crate::Config;
10+
11+
type Type = MachineContext;
1112

1213
impl<M: Machine> Machine for Box<M> {
1314
type Blockstore = M::Blockstore;
@@ -18,18 +19,13 @@ impl<M: Machine> Machine for Box<M> {
1819
(&**self).engine()
1920
}
2021

21-
#[inline(always)]
22-
fn config(&self) -> &Config {
23-
(&**self).config()
24-
}
25-
2622
#[inline(always)]
2723
fn blockstore(&self) -> &Self::Blockstore {
2824
(&**self).blockstore()
2925
}
3026

3127
#[inline(always)]
32-
fn context(&self) -> &MachineContext {
28+
fn context(&self) -> &Type {
3329
(&**self).context()
3430
}
3531

fvm/src/machine/default.rs

Lines changed: 22 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use fvm_ipld_blockstore::{Blockstore, Buffered};
66
use fvm_ipld_encoding::CborStore;
77
use fvm_shared::actor::builtin::{load_manifest, Manifest};
88
use fvm_shared::address::Address;
9-
use fvm_shared::clock::ChainEpoch;
109
use fvm_shared::econ::TokenAmount;
1110
use fvm_shared::error::ErrorNumber;
1211
use fvm_shared::version::NetworkVersion;
@@ -17,16 +16,13 @@ use num_traits::{Signed, Zero};
1716
use super::{Engine, Machine, MachineContext};
1817
use crate::blockstore::BufferedBlockstore;
1918
use crate::externs::Externs;
20-
use crate::gas::price_list_by_network_version;
2119
use crate::kernel::{ClassifyResult, Context as _, Result};
2220
use crate::state_tree::{ActorState, StateTree};
21+
use crate::syscall_error;
2322
use crate::system_actor::State as SystemActorState;
24-
use crate::{syscall_error, Config};
2523

2624
pub struct DefaultMachine<B, E> {
27-
/// The machine's configuration for this instantiation.
28-
config: Config,
29-
/// The context for the execution.
25+
/// The initial execution context for this epoch.
3026
context: MachineContext,
3127
/// The WASM engine is created on construction of the DefaultMachine, and
3228
/// is dropped when the DefaultMachine is dropped.
@@ -48,17 +44,18 @@ where
4844
B: Blockstore + 'static,
4945
E: Externs + 'static,
5046
{
51-
// ISSUE: #249
52-
#[allow(clippy::too_many_arguments)]
47+
/// Create a new [`DefaultMachine`].
48+
///
49+
/// # Arguments
50+
///
51+
/// * `engine`: The global wasm [`Engine`] (engine, pooled resources, caches).
52+
/// * `context`: Machine execution [context][`MachineContext`] (system params, epoch, network
53+
/// version, etc.).
54+
/// * `blockstore`: The underlying [blockstore][`Blockstore`] for reading/writing state.
55+
/// * `externs`: Client-provided ["external"][`Externs`] methods for accessing chain state.
5356
pub fn new(
54-
config: Config,
55-
engine: Engine,
56-
epoch: ChainEpoch,
57-
base_fee: TokenAmount,
58-
circ_supply: TokenAmount,
59-
network_version: NetworkVersion,
60-
state_root: Cid,
61-
builtin_actors: Option<Cid>,
57+
engine: &Engine,
58+
context: &MachineContext,
6259
blockstore: B,
6360
externs: E,
6461
) -> anyhow::Result<Self> {
@@ -67,23 +64,16 @@ where
6764

6865
debug!(
6966
"initializing a new machine, epoch={}, base_fee={}, nv={:?}, root={}",
70-
epoch, &base_fee, network_version, state_root
67+
context.epoch, &context.base_fee, context.network_version, context.initial_state_root
7168
);
7269

73-
if !SUPPORTED_VERSIONS.contains(&network_version) {
74-
return Err(anyhow!("unsupported network version: {}", network_version));
70+
if !SUPPORTED_VERSIONS.contains(&context.network_version) {
71+
return Err(anyhow!(
72+
"unsupported network version: {}",
73+
context.network_version
74+
));
7575
}
7676

77-
let context = MachineContext {
78-
epoch,
79-
base_fee,
80-
circ_supply,
81-
network_version,
82-
initial_state_root: state_root,
83-
price_list: price_list_by_network_version(network_version),
84-
debug: config.debug,
85-
};
86-
8777
// Sanity check that the blockstore contains the supplied state root.
8878
if !blockstore
8979
.has(&context.initial_state_root)
@@ -103,7 +93,7 @@ where
10393

10494
// Load the built-in actors manifest.
10595
// TODO: Check that the actor bundle is sane for the network version.
106-
let (builtin_actors_cid, manifest_version) = match builtin_actors {
96+
let (builtin_actors_cid, manifest_version) = match context.builtin_actors_override {
10797
Some(manifest_cid) => {
10898
let (version, cid): (u32, Cid) = state_tree
10999
.store()
@@ -126,9 +116,8 @@ where
126116
engine.preload(state_tree.store(), builtin_actors.left_values())?;
127117

128118
Ok(DefaultMachine {
129-
config,
130-
context,
131-
engine,
119+
context: context.clone(),
120+
engine: engine.clone(),
132121
externs,
133122
state_tree,
134123
builtin_actors,
@@ -148,10 +137,6 @@ where
148137
&self.engine
149138
}
150139

151-
fn config(&self) -> &Config {
152-
&self.config
153-
}
154-
155140
fn blockstore(&self) -> &Self::Blockstore {
156141
self.state_tree.store()
157142
}

fvm/src/machine/mod.rs

Lines changed: 100 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
use cid::Cid;
2+
use derive_more::{Deref, DerefMut};
23
use fvm_ipld_blockstore::Blockstore;
34
use fvm_shared::actor::builtin::Manifest;
45
use fvm_shared::address::Address;
56
use fvm_shared::clock::ChainEpoch;
67
use fvm_shared::econ::TokenAmount;
78
use fvm_shared::version::NetworkVersion;
89
use fvm_shared::ActorID;
10+
use num_traits::Zero;
911

1012
use crate::externs::Externs;
11-
use crate::gas::PriceList;
13+
use crate::gas::{price_list_by_network_version, PriceList};
1214
use crate::kernel::Result;
1315
use crate::state_tree::{ActorState, StateTree};
14-
use crate::Config;
1516

1617
mod default;
1718

@@ -47,9 +48,6 @@ pub trait Machine: 'static {
4748
/// static lifetime.
4849
fn engine(&self) -> &Engine;
4950

50-
/// Returns the FVM's configuration.
51-
fn config(&self) -> &Config;
52-
5351
/// Returns a reference to the machine's blockstore.
5452
fn blockstore(&self) -> &Self::Blockstore;
5553

@@ -88,23 +86,110 @@ pub trait Machine: 'static {
8886
fn consume(self) -> Self::Blockstore;
8987
}
9088

91-
/// Execution context supplied to the machine.
92-
#[derive(Clone, Debug)]
89+
/// Network-level settings. Except when testing locally, changing any of these likely requires a
90+
/// network upgrade.
91+
#[derive(Debug, Clone)]
92+
pub struct NetworkConfig {
93+
/// The network version at epoch
94+
pub network_version: NetworkVersion,
95+
96+
/// The maximum call depth.
97+
///
98+
/// DEFAULT: 4096
99+
pub max_call_depth: u32,
100+
101+
/// An override for builtin-actors. If specified, this should be the CID of a builtin-actors
102+
/// "manifest".
103+
///
104+
/// DEFAULT: `None`
105+
pub builtin_actors_override: Option<Cid>,
106+
107+
/// Enable actor debugging.
108+
///
109+
/// DEFAULT: `false`
110+
pub actor_debugging: bool,
111+
112+
/// The price list.
113+
///
114+
/// DEFAULT: The price-list for the current network version.
115+
pub price_list: &'static PriceList,
116+
}
117+
118+
impl NetworkConfig {
119+
/// Create a new network config for the given network version.
120+
pub fn new(network_version: NetworkVersion) -> Self {
121+
NetworkConfig {
122+
network_version,
123+
max_call_depth: 4096,
124+
actor_debugging: false,
125+
builtin_actors_override: None,
126+
price_list: price_list_by_network_version(network_version),
127+
}
128+
}
129+
130+
/// Enable actor debugging. This is a consensus-critical option (affects gas usage) so it should
131+
/// only be enabled for local testing or as a network-wide parameter.
132+
pub fn enable_actor_debugging(&mut self, enabled: bool) -> &mut Self {
133+
self.actor_debugging = enabled;
134+
self
135+
}
136+
137+
/// Override actors with the specific manifest. This is primarily useful for testing, or
138+
/// networks prior to NV16 (where the actor's "manifest" isn't specified on-chain).
139+
pub fn override_actors(&mut self, manifest: Cid) -> &mut Self {
140+
self.builtin_actors_override = Some(manifest);
141+
self
142+
}
143+
144+
/// Create a [`MachineContext`] for a given `epoch` with the specified `initial_state`.
145+
pub fn for_epoch(&self, epoch: ChainEpoch, initial_state: Cid) -> MachineContext {
146+
MachineContext {
147+
network: self.clone(),
148+
epoch,
149+
initial_state_root: initial_state,
150+
base_fee: TokenAmount::zero(),
151+
circ_supply: fvm_shared::TOTAL_FILECOIN.clone(),
152+
}
153+
}
154+
}
155+
156+
/// Per-epoch machine context.
157+
#[derive(Clone, Debug, Deref, DerefMut)]
93158
pub struct MachineContext {
159+
/// Network-level settings.
160+
#[deref]
161+
#[deref_mut]
162+
pub network: NetworkConfig,
163+
94164
/// The epoch at which the Machine runs.
95165
pub epoch: ChainEpoch,
166+
167+
/// The initial state root on which this block is based.
168+
pub initial_state_root: Cid,
169+
96170
/// The base fee that's in effect when the Machine runs.
171+
///
172+
/// Default: 0.
97173
pub base_fee: TokenAmount,
174+
98175
/// v15 and onwards: The amount of FIL that has vested from genesis actors.
99176
/// v14 and earlier: The amount of FIL that has vested from genesis msigs
100177
/// (the remainder of the circ supply must be calculated by the FVM)
178+
///
179+
/// DEFAULT: Total FIL supply (likely not what you want).
101180
pub circ_supply: TokenAmount,
102-
/// The initial state root on which this block is based.
103-
pub initial_state_root: Cid,
104-
/// The price list.
105-
pub price_list: &'static PriceList,
106-
/// The network version at epoch
107-
pub network_version: NetworkVersion,
108-
/// Whether debug mode is enabled or not.
109-
pub debug: bool,
181+
}
182+
183+
impl MachineContext {
184+
/// Sets [`EpochContext::base_fee`].
185+
pub fn set_base_fee(&mut self, amt: TokenAmount) -> &mut Self {
186+
self.base_fee = amt;
187+
self
188+
}
189+
190+
/// Set [`EpochContext::circ_supply`].
191+
pub fn set_circulating_supply(&mut self, amt: TokenAmount) -> &mut Self {
192+
self.circ_supply = amt;
193+
self
194+
}
110195
}

testing/conformance/benches/bench_drivers.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ pub fn bench_vector_variant(
4545
let vector = &(*vector).clone();
4646
let bs = bs.clone();
4747
// TODO next few lines don't impact the benchmarks, but it might make them run waaaay more slowly... ought to make a base copy of the machine and exec and deepcopy them each time.
48-
let machine = TestMachine::new_for_vector(vector, variant, bs, engine.clone());
48+
let machine = TestMachine::new_for_vector(vector, variant, bs, engine);
4949
// can assume this works because it passed a test before this ran
5050
let exec: DefaultExecutor<TestKernel> = DefaultExecutor::new(machine);
5151
(messages_with_lengths.clone(), exec)

testing/conformance/src/driver.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ pub fn run_variant(
190190
let id = variant.id.clone();
191191

192192
// Construct the Machine.
193-
let machine = TestMachine::new_for_vector(v, variant, bs, engine.clone());
193+
let machine = TestMachine::new_for_vector(v, variant, bs, engine);
194194
let mut exec: DefaultExecutor<TestKernel> = DefaultExecutor::new(machine);
195195

196196
// Apply all messages in the vector.

0 commit comments

Comments
 (0)