From 57533708d20d28f1430a75d535f4bb3988b5e858 Mon Sep 17 00:00:00 2001 From: austinabell Date: Fri, 13 Mar 2020 21:00:19 -0400 Subject: [PATCH 01/11] Update and cleanup actors --- blockchain/state_manager/src/lib.rs | 6 +- .../builtin/{account.rs => account/mod.rs} | 15 ++--- vm/actor/src/builtin/account/state.rs | 9 +++ vm/actor/src/builtin/{cron.rs => cron/mod.rs} | 28 +++------ vm/actor/src/builtin/cron/state.rs | 24 ++++++++ vm/actor/src/builtin/{init.rs => init/mod.rs} | 59 ++----------------- vm/actor/src/builtin/init/state.rs | 52 ++++++++++++++++ vm/actor/src/builtin/miner/mod.rs | 8 +++ .../{miner_actor.rs => miner/state.rs} | 32 +++++----- vm/actor/src/builtin/mod.rs | 8 +-- .../{storage_power.rs => power/mod.rs} | 30 ++++------ vm/actor/src/builtin/power/state.rs | 10 ++++ .../src/builtin/{reward.rs => reward/mod.rs} | 33 +++-------- vm/actor/src/builtin/reward/state.rs | 27 +++++++++ 14 files changed, 191 insertions(+), 150 deletions(-) rename vm/actor/src/builtin/{account.rs => account/mod.rs} (83%) create mode 100644 vm/actor/src/builtin/account/state.rs rename vm/actor/src/builtin/{cron.rs => cron/mod.rs} (77%) create mode 100644 vm/actor/src/builtin/cron/state.rs rename vm/actor/src/builtin/{init.rs => init/mod.rs} (57%) create mode 100644 vm/actor/src/builtin/init/state.rs create mode 100644 vm/actor/src/builtin/miner/mod.rs rename vm/actor/src/builtin/{miner_actor.rs => miner/state.rs} (94%) rename vm/actor/src/builtin/{storage_power.rs => power/mod.rs} (62%) create mode 100644 vm/actor/src/builtin/power/state.rs rename vm/actor/src/builtin/{reward.rs => reward/mod.rs} (69%) create mode 100644 vm/actor/src/builtin/reward/state.rs diff --git a/blockchain/state_manager/src/lib.rs b/blockchain/state_manager/src/lib.rs index 5741109cef16..73305f552c4c 100644 --- a/blockchain/state_manager/src/lib.rs +++ b/blockchain/state_manager/src/lib.rs @@ -4,7 +4,7 @@ mod errors; pub use self::errors::*; -use actor::{ActorState, MinerInfo, StorageMinerActorState}; +use actor::{ActorState, MinerActorState, MinerInfo}; use address::Address; use blockstore::BlockStore; use encoding::de::DeserializeOwned; @@ -40,12 +40,12 @@ where } /// Returns the epoch at which the miner was slashed at pub fn miner_slashed(&self, addr: &Address, ts: &Tipset) -> Result { - let act: StorageMinerActorState = self.load_actor_state(addr, ts)?; + let act: MinerActorState = self.load_actor_state(addr, ts)?; Ok(act.slashed_at) } /// Returns the amount of space in each sector committed to the network by this miner pub fn miner_sector_size(&self, addr: &Address, ts: &Tipset) -> Result { - let act: StorageMinerActorState = self.load_actor_state(addr, ts)?; + let act: MinerActorState = self.load_actor_state(addr, ts)?; let info: MinerInfo = self.bs.get(&act.info)?.ok_or_else(|| { Error::State("Could not retrieve miner info from IPLD store".to_owned()) })?; diff --git a/vm/actor/src/builtin/account.rs b/vm/actor/src/builtin/account/mod.rs similarity index 83% rename from vm/actor/src/builtin/account.rs rename to vm/actor/src/builtin/account/mod.rs index fa466ec85ed5..14681ed49d58 100644 --- a/vm/actor/src/builtin/account.rs +++ b/vm/actor/src/builtin/account/mod.rs @@ -1,17 +1,14 @@ // Copyright 2020 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -use address::Address; +mod state; + +pub use self::state::AccountActorState; use num_derive::FromPrimitive; use num_traits::FromPrimitive; use runtime::{ActorCode, Runtime}; use vm::{ExitCode, MethodNum, Serialized, METHOD_CONSTRUCTOR}; -/// AccountActorState includes the address for the actor -pub struct AccountActorState { - pub address: Address, -} - #[derive(FromPrimitive)] pub enum AccountMethod { Constructor = METHOD_CONSTRUCTOR, @@ -25,16 +22,16 @@ impl AccountMethod { } #[derive(Clone)] -pub struct AccountActorCode; +pub struct AccountActor; -impl AccountActorCode { +impl AccountActor { /// Constructor for Account actor fn constructor(_rt: &RT) { // Intentionally left blank } } -impl ActorCode for AccountActorCode { +impl ActorCode for AccountActor { fn invoke_method(&self, rt: &RT, method: MethodNum, _params: &Serialized) { match AccountMethod::from_method_num(method) { Some(AccountMethod::Constructor) => { diff --git a/vm/actor/src/builtin/account/state.rs b/vm/actor/src/builtin/account/state.rs new file mode 100644 index 000000000000..208e862a506e --- /dev/null +++ b/vm/actor/src/builtin/account/state.rs @@ -0,0 +1,9 @@ +// Copyright 2020 ChainSafe Systems +// SPDX-License-Identifier: Apache-2.0, MIT + +use address::Address; + +/// AccountActorState includes the address for the actor +pub struct AccountActorState { + pub address: Address, +} diff --git a/vm/actor/src/builtin/cron.rs b/vm/actor/src/builtin/cron/mod.rs similarity index 77% rename from vm/actor/src/builtin/cron.rs rename to vm/actor/src/builtin/cron/mod.rs index 8ced3121db4a..e86dc3f16a17 100644 --- a/vm/actor/src/builtin/cron.rs +++ b/vm/actor/src/builtin/cron/mod.rs @@ -1,22 +1,13 @@ // Copyright 2020 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -use vm::{ExitCode, MethodNum, Serialized, METHOD_CONSTRUCTOR, METHOD_CRON}; +mod state; -use address::Address; +pub use self::state::{CronActorState, CronEntry}; use num_derive::FromPrimitive; use num_traits::FromPrimitive; use runtime::{ActorCode, Runtime}; - -/// CronActorState has no internal state -#[derive(Default)] -pub struct CronActorState; - -#[derive(Clone)] -pub struct CronTableEntry { - to_addr: Address, - method_num: MethodNum, -} +use vm::{ExitCode, MethodNum, Serialized, METHOD_CONSTRUCTOR, METHOD_CRON}; #[derive(FromPrimitive)] pub enum CronMethod { @@ -31,16 +22,11 @@ impl CronMethod { } } +// TODO spec has changed, this will need to be moved to Cron State in full impl #[derive(Clone)] -pub struct CronActorCode { - /// Entries is a set of actors (and corresponding methods) to call during EpochTick. - /// This can be done a bunch of ways. We do it this way here to make it easy to add - /// a handler to Cron elsewhere in the spec code. How to do this is implementation - /// specific. - entries: Vec, -} +pub struct CronActor; -impl CronActorCode { +impl CronActor { /// Constructor for Cron actor fn constructor(_rt: &RT) { // Intentionally left blank @@ -67,7 +53,7 @@ impl CronActorCode { } } -impl ActorCode for CronActorCode { +impl ActorCode for CronActor { fn invoke_method(&self, rt: &RT, method: MethodNum, _params: &Serialized) { match CronMethod::from_method_num(method) { Some(CronMethod::Constructor) => { diff --git a/vm/actor/src/builtin/cron/state.rs b/vm/actor/src/builtin/cron/state.rs new file mode 100644 index 000000000000..8a5eec487c4f --- /dev/null +++ b/vm/actor/src/builtin/cron/state.rs @@ -0,0 +1,24 @@ +// Copyright 2020 ChainSafe Systems +// SPDX-License-Identifier: Apache-2.0, MIT + +use address::Address; +use serde::{Deserialize, Serialize}; +use vm::MethodNum; + +/// CronActorState has no internal state +// TODO implement tuple serialize/deserialize +#[derive(Default, Serialize, Deserialize)] +pub struct CronActorState { + /// Entries is a set of actors (and corresponding methods) to call during EpochTick. + /// This can be done a bunch of ways. We do it this way here to make it easy to add + /// a handler to Cron elsewhere in the spec code. How to do this is implementation + /// specific. + entries: Vec, +} + +// TODO implement tuple serialize/deserialize +#[derive(Clone, Serialize, Deserialize)] +pub struct CronEntry { + to_addr: Address, + method_num: MethodNum, +} diff --git a/vm/actor/src/builtin/init.rs b/vm/actor/src/builtin/init/mod.rs similarity index 57% rename from vm/actor/src/builtin/init.rs rename to vm/actor/src/builtin/init/mod.rs index b17b5e8cde15..f3cefe1e3379 100644 --- a/vm/actor/src/builtin/init.rs +++ b/vm/actor/src/builtin/init/mod.rs @@ -1,61 +1,14 @@ // Copyright 2020 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -use crate::FIRST_NON_SINGLETON_ADDR; -use vm::{ - ActorID, CodeID, ExitCode, MethodNum, Serialized, METHOD_CONSTRUCTOR, METHOD_PLACEHOLDER, -}; +mod state; +pub use self::state::InitActorState; use address::Address; -use cid::Cid; -use ipld_blockstore::BlockStore; -use ipld_hamt::{Error as HamtError, Hamt}; use num_derive::FromPrimitive; use num_traits::FromPrimitive; use runtime::{ActorCode, Runtime}; -use serde::{Deserialize, Serialize}; - -/// InitActorState is reponsible for creating -// TODO implement actual serialize and deserialize to match -#[derive(Serialize, Deserialize)] -pub struct InitActorState { - address_map: Cid, - next_id: ActorID, -} - -impl InitActorState { - pub fn new(address_map: Cid) -> Self { - Self { - address_map, - next_id: FIRST_NON_SINGLETON_ADDR, - } - } - /// Assigns next available ID and incremenets the next_id value from state - pub fn map_address_to_new_id( - &mut self, - store: &BS, - addr: &Address, - ) -> Result { - let id = self.next_id; - self.next_id += 1; - - let mut map: Hamt = Hamt::load_with_bit_width(&self.address_map, store, 5)?; - map.set(String::from_utf8_lossy(&addr.to_bytes()).to_string(), id)?; - self.address_map = map.flush()?; - - Ok(Address::new_id(id.0).expect("Id Address should be created without Error")) - } - - /// Resolve address - pub fn resolve_address( - &self, - _store: &BS, - _addr: &Address, - ) -> Result { - // TODO implement address resolution - todo!() - } -} +use vm::{CodeID, ExitCode, MethodNum, Serialized, METHOD_CONSTRUCTOR, METHOD_PLACEHOLDER}; #[derive(FromPrimitive)] pub enum InitMethod { @@ -71,8 +24,8 @@ impl InitMethod { } } -pub struct InitActorCode; -impl InitActorCode { +pub struct InitActor; +impl InitActor { fn constructor(_rt: &RT) { // Acquire state // Update actor substate @@ -86,7 +39,7 @@ impl InitActorCode { } } -impl ActorCode for InitActorCode { +impl ActorCode for InitActor { fn invoke_method(&self, rt: &RT, method: MethodNum, params: &Serialized) { // Create mutable copy of params for usage in functions let params: &mut Serialized = &mut params.clone(); diff --git a/vm/actor/src/builtin/init/state.rs b/vm/actor/src/builtin/init/state.rs new file mode 100644 index 000000000000..fd9e0c258761 --- /dev/null +++ b/vm/actor/src/builtin/init/state.rs @@ -0,0 +1,52 @@ +// Copyright 2020 ChainSafe Systems +// SPDX-License-Identifier: Apache-2.0, MIT + +use crate::FIRST_NON_SINGLETON_ADDR; +use address::Address; +use cid::Cid; +use ipld_blockstore::BlockStore; +use ipld_hamt::{Error as HamtError, Hamt}; +use serde::{Deserialize, Serialize}; +use vm::ActorID; + +/// InitActorState is reponsible for creating +// TODO implement actual serialize and deserialize to match +#[derive(Serialize, Deserialize)] +pub struct InitActorState { + address_map: Cid, + next_id: ActorID, +} + +impl InitActorState { + pub fn new(address_map: Cid) -> Self { + Self { + address_map, + next_id: FIRST_NON_SINGLETON_ADDR, + } + } + /// Assigns next available ID and incremenets the next_id value from state + pub fn map_address_to_new_id( + &mut self, + store: &BS, + addr: &Address, + ) -> Result { + let id = self.next_id; + self.next_id += 1; + + let mut map: Hamt = Hamt::load_with_bit_width(&self.address_map, store, 5)?; + map.set(String::from_utf8_lossy(&addr.to_bytes()).to_string(), id)?; + self.address_map = map.flush()?; + + Ok(Address::new_id(id.0).expect("Id Address should be created without Error")) + } + + /// Resolve address + pub fn resolve_address( + &self, + _store: &BS, + _addr: &Address, + ) -> Result { + // TODO implement address resolution + todo!() + } +} diff --git a/vm/actor/src/builtin/miner/mod.rs b/vm/actor/src/builtin/miner/mod.rs new file mode 100644 index 000000000000..4ded1d3e4528 --- /dev/null +++ b/vm/actor/src/builtin/miner/mod.rs @@ -0,0 +1,8 @@ +// Copyright 2020 ChainSafe Systems +// SPDX-License-Identifier: Apache-2.0, MIT + +mod state; + +pub use self::state::{MinerActorState, MinerInfo}; + +pub struct MinerActor; diff --git a/vm/actor/src/builtin/miner_actor.rs b/vm/actor/src/builtin/miner/state.rs similarity index 94% rename from vm/actor/src/builtin/miner_actor.rs rename to vm/actor/src/builtin/miner/state.rs index 56e400026804..69337ad81c31 100644 --- a/vm/actor/src/builtin/miner_actor.rs +++ b/vm/actor/src/builtin/miner/state.rs @@ -7,10 +7,8 @@ use encoding::de; use libp2p::PeerId; use serde::Deserialize; -pub struct StorageMinerActor {} - /// Container representing storage miner actor state -pub struct StorageMinerActorState { +pub struct MinerActorState { // TODO add proving_set, post_state /// The height at which this miner was slashed at. pub slashed_at: u64, @@ -20,6 +18,20 @@ pub struct StorageMinerActorState { pub info: Cid, } +impl<'de> de::Deserialize<'de> for MinerActorState { + fn deserialize(deserializer: D) -> Result + where + D: de::Deserializer<'de>, + { + let (slashed_at, sectors, info) = Deserialize::deserialize(deserializer)?; + Ok(Self { + slashed_at, + sectors, + info, + }) + } +} + /// Static information about miner pub struct MinerInfo { /// Account that owns this miner @@ -44,20 +56,6 @@ impl MinerInfo { } } -impl<'de> de::Deserialize<'de> for StorageMinerActorState { - fn deserialize(deserializer: D) -> Result - where - D: de::Deserializer<'de>, - { - let (slashed_at, sectors, info) = Deserialize::deserialize(deserializer)?; - Ok(Self { - slashed_at, - sectors, - info, - }) - } -} - impl<'de> de::Deserialize<'de> for MinerInfo { fn deserialize(deserializer: D) -> Result where diff --git a/vm/actor/src/builtin/mod.rs b/vm/actor/src/builtin/mod.rs index 136c494fd9ae..89a5061d19a8 100644 --- a/vm/actor/src/builtin/mod.rs +++ b/vm/actor/src/builtin/mod.rs @@ -4,13 +4,13 @@ mod account; mod cron; mod init; -mod miner_actor; +mod miner; +mod power; mod reward; -mod storage_power; pub use self::account::*; pub use self::cron::*; pub use self::init::*; -pub use self::miner_actor::*; +pub use self::miner::*; +pub use self::power::*; pub use self::reward::*; -pub use self::storage_power::*; diff --git a/vm/actor/src/builtin/storage_power.rs b/vm/actor/src/builtin/power/mod.rs similarity index 62% rename from vm/actor/src/builtin/storage_power.rs rename to vm/actor/src/builtin/power/mod.rs index fdb2c67de9f0..f9dd0ac8aecd 100644 --- a/vm/actor/src/builtin/storage_power.rs +++ b/vm/actor/src/builtin/power/mod.rs @@ -1,21 +1,17 @@ // Copyright 2020 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -use num_bigint::BigUint; +mod state; + +pub use self::state::PowerActorState; use num_derive::FromPrimitive; use num_traits::FromPrimitive; use runtime::{ActorCode, Runtime}; use vm::{ExitCode, MethodNum, Serialized, METHOD_CONSTRUCTOR}; -/// State of storage power actor -pub struct StoragePowerActorState { - // TODO add power tables on finished spec - _total_storage: BigUint, -} - /// Method definitions for Storage Power Actor #[derive(FromPrimitive)] -pub enum StoragePowerMethod { +pub enum PowerMethod { /// Constructor for Storage Power Actor Constructor = METHOD_CONSTRUCTOR, // TODO add other methods on finished spec @@ -23,16 +19,16 @@ pub enum StoragePowerMethod { GetTotalStorage = 5, } -impl StoragePowerMethod { - /// from_method_num converts a method number into an StoragePowerMethod enum - fn from_method_num(m: MethodNum) -> Option { +impl PowerMethod { + /// from_method_num converts a method number into an PowerMethod enum + fn from_method_num(m: MethodNum) -> Option { FromPrimitive::from_u64(u64::from(m)) } } #[derive(Clone)] -pub struct StoragePowerActorCode; -impl StoragePowerActorCode { +pub struct PowerActor; +impl PowerActor { /// Constructor for StoragePower actor fn constructor(_rt: &RT) { // TODO @@ -45,12 +41,12 @@ impl StoragePowerActorCode { } } -impl ActorCode for StoragePowerActorCode { +impl ActorCode for PowerActor { fn invoke_method(&self, rt: &RT, method: MethodNum, _params: &Serialized) { - match StoragePowerMethod::from_method_num(method) { + match PowerMethod::from_method_num(method) { // TODO determine parameters for each method on finished spec - Some(StoragePowerMethod::Constructor) => Self::constructor(rt), - Some(StoragePowerMethod::GetTotalStorage) => Self::get_total_storage(rt), + Some(PowerMethod::Constructor) => Self::constructor(rt), + Some(PowerMethod::GetTotalStorage) => Self::get_total_storage(rt), _ => { rt.abort(ExitCode::SysErrInvalidMethod, "Invalid method".to_owned()); unreachable!(); diff --git a/vm/actor/src/builtin/power/state.rs b/vm/actor/src/builtin/power/state.rs new file mode 100644 index 000000000000..7d1af5ab8974 --- /dev/null +++ b/vm/actor/src/builtin/power/state.rs @@ -0,0 +1,10 @@ +// Copyright 2020 ChainSafe Systems +// SPDX-License-Identifier: Apache-2.0, MIT + +use num_bigint::BigUint; + +/// State of storage power actor +pub struct PowerActorState { + // TODO add power tables on finished spec + _total_storage: BigUint, +} diff --git a/vm/actor/src/builtin/reward.rs b/vm/actor/src/builtin/reward/mod.rs similarity index 69% rename from vm/actor/src/builtin/reward.rs rename to vm/actor/src/builtin/reward/mod.rs index 68c37c688348..4f63106c55f1 100644 --- a/vm/actor/src/builtin/reward.rs +++ b/vm/actor/src/builtin/reward/mod.rs @@ -1,32 +1,13 @@ // Copyright 2020 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -use address::Address; -use clock::ChainEpoch; +mod state; + +pub use self::state::{Reward, RewardActorState}; use num_derive::FromPrimitive; use num_traits::FromPrimitive; use runtime::{ActorCode, Runtime}; -use std::collections::HashMap; -use vm::{ExitCode, MethodNum, Serialized, TokenAmount, METHOD_CONSTRUCTOR, METHOD_PLACEHOLDER}; - -pub struct Reward { - pub start_epoch: ChainEpoch, - pub value: TokenAmount, - pub release_rate: TokenAmount, - pub amount_withdrawn: TokenAmount, -} - -/// RewardActorState has no internal state -pub struct RewardActorState { - pub reward_map: HashMap>, -} - -impl RewardActorState { - pub fn withdraw_reward(_rt: &RT, _owner: Address) -> TokenAmount { - // TODO - TokenAmount::new(0) - } -} +use vm::{ExitCode, MethodNum, Serialized, METHOD_CONSTRUCTOR, METHOD_PLACEHOLDER}; #[derive(FromPrimitive)] pub enum RewardMethod { @@ -43,8 +24,8 @@ impl RewardMethod { } #[derive(Clone)] -pub struct RewardActorCode; -impl RewardActorCode { +pub struct RewardActor; +impl RewardActor { /// Constructor for Reward actor fn constructor(_rt: &RT) { // TODO @@ -62,7 +43,7 @@ impl RewardActorCode { } } -impl ActorCode for RewardActorCode { +impl ActorCode for RewardActor { fn invoke_method(&self, rt: &RT, method: MethodNum, _params: &Serialized) { match RewardMethod::from_method_num(method) { // TODO determine parameters for each method on finished spec diff --git a/vm/actor/src/builtin/reward/state.rs b/vm/actor/src/builtin/reward/state.rs new file mode 100644 index 000000000000..91eedbb96ed4 --- /dev/null +++ b/vm/actor/src/builtin/reward/state.rs @@ -0,0 +1,27 @@ +// Copyright 2020 ChainSafe Systems +// SPDX-License-Identifier: Apache-2.0, MIT + +use address::Address; +use clock::ChainEpoch; +use runtime::Runtime; +use std::collections::HashMap; +use vm::TokenAmount; + +pub struct Reward { + pub start_epoch: ChainEpoch, + pub value: TokenAmount, + pub release_rate: TokenAmount, + pub amount_withdrawn: TokenAmount, +} + +/// RewardActorState has no internal state +pub struct RewardActorState { + pub reward_map: HashMap>, +} + +impl RewardActorState { + pub fn withdraw_reward(_rt: &RT, _owner: Address) -> TokenAmount { + // TODO + TokenAmount::new(0) + } +} From 5f2c6b2ef370ad64e067b69f0a1313421cb7b1cb Mon Sep 17 00:00:00 2001 From: austinabell Date: Fri, 13 Mar 2020 21:51:55 -0400 Subject: [PATCH 02/11] Clean and implement serialize for cron and account actors --- vm/actor/src/builtin/account/mod.rs | 2 - vm/actor/src/builtin/account/state.rs | 20 ++++++++++ vm/actor/src/builtin/cron/mod.rs | 35 +++++++++++++--- vm/actor/src/builtin/cron/state.rs | 57 +++++++++++++++++++++------ vm/actor/src/builtin/power/mod.rs | 1 - vm/actor/src/builtin/reward/mod.rs | 1 - 6 files changed, 96 insertions(+), 20 deletions(-) diff --git a/vm/actor/src/builtin/account/mod.rs b/vm/actor/src/builtin/account/mod.rs index 14681ed49d58..d8a6667f97c8 100644 --- a/vm/actor/src/builtin/account/mod.rs +++ b/vm/actor/src/builtin/account/mod.rs @@ -21,9 +21,7 @@ impl AccountMethod { } } -#[derive(Clone)] pub struct AccountActor; - impl AccountActor { /// Constructor for Account actor fn constructor(_rt: &RT) { diff --git a/vm/actor/src/builtin/account/state.rs b/vm/actor/src/builtin/account/state.rs index 208e862a506e..508bab3e3822 100644 --- a/vm/actor/src/builtin/account/state.rs +++ b/vm/actor/src/builtin/account/state.rs @@ -2,8 +2,28 @@ // SPDX-License-Identifier: Apache-2.0, MIT use address::Address; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; /// AccountActorState includes the address for the actor pub struct AccountActorState { pub address: Address, } + +impl Serialize for AccountActorState { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + [&self.address].serialize(serializer) + } +} + +impl<'de> Deserialize<'de> for AccountActorState { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let [address]: [Address; 1] = Deserialize::deserialize(deserializer)?; + Ok(AccountActorState { address }) + } +} diff --git a/vm/actor/src/builtin/cron/mod.rs b/vm/actor/src/builtin/cron/mod.rs index e86dc3f16a17..022b51b087f0 100644 --- a/vm/actor/src/builtin/cron/mod.rs +++ b/vm/actor/src/builtin/cron/mod.rs @@ -7,6 +7,7 @@ pub use self::state::{CronActorState, CronEntry}; use num_derive::FromPrimitive; use num_traits::FromPrimitive; use runtime::{ActorCode, Runtime}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; use vm::{ExitCode, MethodNum, Serialized, METHOD_CONSTRUCTOR, METHOD_CRON}; #[derive(FromPrimitive)] @@ -22,13 +23,37 @@ impl CronMethod { } } -// TODO spec has changed, this will need to be moved to Cron State in full impl -#[derive(Clone)] -pub struct CronActor; +/// Constructor parameters for Cron actor, contains entries +/// of actors and methods to call on each epoch +#[derive(Default)] +pub struct CronConstructorParams { + /// Entries is a set of actors (and corresponding methods) to call during EpochTick. + pub entries: Vec, +} + +impl Serialize for CronConstructorParams { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.entries.serialize(serializer) + } +} +impl<'de> Deserialize<'de> for CronConstructorParams { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let entries: Vec = Deserialize::deserialize(deserializer)?; + Ok(Self { entries }) + } +} + +pub struct CronActor; impl CronActor { /// Constructor for Cron actor - fn constructor(_rt: &RT) { + fn constructor(_rt: &RT, _params: CronConstructorParams) { // Intentionally left blank } /// epoch_tick executes built-in periodic actions, run at every Epoch. @@ -58,7 +83,7 @@ impl ActorCode for CronActor { match CronMethod::from_method_num(method) { Some(CronMethod::Constructor) => { // TODO unfinished spec - Self::constructor(rt) + Self::constructor(rt, CronConstructorParams::default()) } Some(CronMethod::Cron) => { // TODO unfinished spec diff --git a/vm/actor/src/builtin/cron/state.rs b/vm/actor/src/builtin/cron/state.rs index 8a5eec487c4f..16717865c960 100644 --- a/vm/actor/src/builtin/cron/state.rs +++ b/vm/actor/src/builtin/cron/state.rs @@ -2,23 +2,58 @@ // SPDX-License-Identifier: Apache-2.0, MIT use address::Address; -use serde::{Deserialize, Serialize}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; use vm::MethodNum; -/// CronActorState has no internal state -// TODO implement tuple serialize/deserialize -#[derive(Default, Serialize, Deserialize)] +/// Cron actor state which holds entries to call during epoch tick +#[derive(Default)] pub struct CronActorState { /// Entries is a set of actors (and corresponding methods) to call during EpochTick. - /// This can be done a bunch of ways. We do it this way here to make it easy to add - /// a handler to Cron elsewhere in the spec code. How to do this is implementation - /// specific. - entries: Vec, + pub entries: Vec, } -// TODO implement tuple serialize/deserialize -#[derive(Clone, Serialize, Deserialize)] pub struct CronEntry { - to_addr: Address, + receiver: Address, method_num: MethodNum, } + +impl Serialize for CronActorState { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.entries.serialize(serializer) + } +} + +impl<'de> Deserialize<'de> for CronActorState { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let entries: Vec = Deserialize::deserialize(deserializer)?; + Ok(Self { entries }) + } +} + +impl Serialize for CronEntry { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + (&self.receiver, &self.method_num).serialize(serializer) + } +} + +impl<'de> Deserialize<'de> for CronEntry { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let (receiver, method_num) = Deserialize::deserialize(deserializer)?; + Ok(Self { + receiver, + method_num, + }) + } +} diff --git a/vm/actor/src/builtin/power/mod.rs b/vm/actor/src/builtin/power/mod.rs index f9dd0ac8aecd..29a8f2e55179 100644 --- a/vm/actor/src/builtin/power/mod.rs +++ b/vm/actor/src/builtin/power/mod.rs @@ -26,7 +26,6 @@ impl PowerMethod { } } -#[derive(Clone)] pub struct PowerActor; impl PowerActor { /// Constructor for StoragePower actor diff --git a/vm/actor/src/builtin/reward/mod.rs b/vm/actor/src/builtin/reward/mod.rs index 4f63106c55f1..abb539b5bbae 100644 --- a/vm/actor/src/builtin/reward/mod.rs +++ b/vm/actor/src/builtin/reward/mod.rs @@ -23,7 +23,6 @@ impl RewardMethod { } } -#[derive(Clone)] pub struct RewardActor; impl RewardActor { /// Constructor for Reward actor From 047e4e36bcbb05acf6728fbb1b5ce61503527470 Mon Sep 17 00:00:00 2001 From: austinabell Date: Sat, 14 Mar 2020 12:56:42 -0400 Subject: [PATCH 03/11] Clean remaining actors and refactor access --- blockchain/state_manager/src/lib.rs | 8 ++-- vm/actor/src/builtin/account/mod.rs | 22 ++++++----- vm/actor/src/builtin/account/state.rs | 11 +++--- vm/actor/src/builtin/cron/mod.rs | 38 ++++++++++--------- vm/actor/src/builtin/cron/state.rs | 16 ++++---- vm/actor/src/builtin/init/mod.rs | 49 +++++++++++++------------ vm/actor/src/builtin/init/state.rs | 38 +++++++++++++++---- vm/actor/src/builtin/miner/mod.rs | 5 ++- vm/actor/src/builtin/miner/state.rs | 9 +++-- vm/actor/src/builtin/mod.rs | 19 +++------- vm/actor/src/builtin/power/mod.rs | 25 +++++++------ vm/actor/src/builtin/power/state.rs | 4 +- vm/actor/src/builtin/reward/mod.rs | 26 +++++++------ vm/actor/src/builtin/reward/state.rs | 45 +++++++++++++++++++---- vm/state_tree/src/lib.rs | 6 +-- vm/state_tree/tests/state_tree_tests.rs | 4 +- 16 files changed, 192 insertions(+), 133 deletions(-) diff --git a/blockchain/state_manager/src/lib.rs b/blockchain/state_manager/src/lib.rs index 73305f552c4c..decd66b0a4ba 100644 --- a/blockchain/state_manager/src/lib.rs +++ b/blockchain/state_manager/src/lib.rs @@ -4,7 +4,7 @@ mod errors; pub use self::errors::*; -use actor::{ActorState, MinerActorState, MinerInfo}; +use actor::{miner, ActorState}; use address::Address; use blockstore::BlockStore; use encoding::de::DeserializeOwned; @@ -40,13 +40,13 @@ where } /// Returns the epoch at which the miner was slashed at pub fn miner_slashed(&self, addr: &Address, ts: &Tipset) -> Result { - let act: MinerActorState = self.load_actor_state(addr, ts)?; + let act: miner::State = self.load_actor_state(addr, ts)?; Ok(act.slashed_at) } /// Returns the amount of space in each sector committed to the network by this miner pub fn miner_sector_size(&self, addr: &Address, ts: &Tipset) -> Result { - let act: MinerActorState = self.load_actor_state(addr, ts)?; - let info: MinerInfo = self.bs.get(&act.info)?.ok_or_else(|| { + let act: miner::State = self.load_actor_state(addr, ts)?; + let info: miner::MinerInfo = self.bs.get(&act.info)?.ok_or_else(|| { Error::State("Could not retrieve miner info from IPLD store".to_owned()) })?; Ok(*info.sector_size()) diff --git a/vm/actor/src/builtin/account/mod.rs b/vm/actor/src/builtin/account/mod.rs index d8a6667f97c8..dae0af6657ff 100644 --- a/vm/actor/src/builtin/account/mod.rs +++ b/vm/actor/src/builtin/account/mod.rs @@ -3,36 +3,38 @@ mod state; -pub use self::state::AccountActorState; +pub use self::state::State; use num_derive::FromPrimitive; use num_traits::FromPrimitive; use runtime::{ActorCode, Runtime}; use vm::{ExitCode, MethodNum, Serialized, METHOD_CONSTRUCTOR}; +/// Account actor methods available #[derive(FromPrimitive)] -pub enum AccountMethod { +pub enum Method { Constructor = METHOD_CONSTRUCTOR, } -impl AccountMethod { - /// from_method_num converts a method number into an AccountMethod enum - fn from_method_num(m: MethodNum) -> Option { +impl Method { + /// from_method_num converts a method number into a Method enum + fn from_method_num(m: MethodNum) -> Option { FromPrimitive::from_u64(u64::from(m)) } } -pub struct AccountActor; -impl AccountActor { +/// Account Actor +pub struct Actor; +impl Actor { /// Constructor for Account actor fn constructor(_rt: &RT) { // Intentionally left blank } } -impl ActorCode for AccountActor { +impl ActorCode for Actor { fn invoke_method(&self, rt: &RT, method: MethodNum, _params: &Serialized) { - match AccountMethod::from_method_num(method) { - Some(AccountMethod::Constructor) => { + match Method::from_method_num(method) { + Some(Method::Constructor) => { // TODO unfinished spec Self::constructor(rt) } diff --git a/vm/actor/src/builtin/account/state.rs b/vm/actor/src/builtin/account/state.rs index 508bab3e3822..a6d79e6f8628 100644 --- a/vm/actor/src/builtin/account/state.rs +++ b/vm/actor/src/builtin/account/state.rs @@ -4,12 +4,13 @@ use address::Address; use serde::{Deserialize, Deserializer, Serialize, Serializer}; -/// AccountActorState includes the address for the actor -pub struct AccountActorState { +/// State includes the address for the actor +pub struct State { pub address: Address, } -impl Serialize for AccountActorState { +/// Account actor state +impl Serialize for State { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -18,12 +19,12 @@ impl Serialize for AccountActorState { } } -impl<'de> Deserialize<'de> for AccountActorState { +impl<'de> Deserialize<'de> for State { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { let [address]: [Address; 1] = Deserialize::deserialize(deserializer)?; - Ok(AccountActorState { address }) + Ok(Self { address }) } } diff --git a/vm/actor/src/builtin/cron/mod.rs b/vm/actor/src/builtin/cron/mod.rs index 022b51b087f0..2c33f2843505 100644 --- a/vm/actor/src/builtin/cron/mod.rs +++ b/vm/actor/src/builtin/cron/mod.rs @@ -3,22 +3,23 @@ mod state; -pub use self::state::{CronActorState, CronEntry}; +pub use self::state::{Entry, State}; use num_derive::FromPrimitive; use num_traits::FromPrimitive; use runtime::{ActorCode, Runtime}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use vm::{ExitCode, MethodNum, Serialized, METHOD_CONSTRUCTOR, METHOD_CRON}; +/// Cron actor methods available #[derive(FromPrimitive)] -pub enum CronMethod { +pub enum Method { Constructor = METHOD_CONSTRUCTOR, Cron = METHOD_CRON, } -impl CronMethod { - /// from_method_num converts a method number into an CronMethod enum - fn from_method_num(m: MethodNum) -> Option { +impl Method { + /// from_method_num converts a method number into an Method enum + fn from_method_num(m: MethodNum) -> Option { FromPrimitive::from_u64(u64::from(m)) } } @@ -26,12 +27,12 @@ impl CronMethod { /// Constructor parameters for Cron actor, contains entries /// of actors and methods to call on each epoch #[derive(Default)] -pub struct CronConstructorParams { +pub struct ConstructorParams { /// Entries is a set of actors (and corresponding methods) to call during EpochTick. - pub entries: Vec, + pub entries: Vec, } -impl Serialize for CronConstructorParams { +impl Serialize for ConstructorParams { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -40,20 +41,21 @@ impl Serialize for CronConstructorParams { } } -impl<'de> Deserialize<'de> for CronConstructorParams { +impl<'de> Deserialize<'de> for ConstructorParams { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { - let entries: Vec = Deserialize::deserialize(deserializer)?; + let entries: Vec = Deserialize::deserialize(deserializer)?; Ok(Self { entries }) } } -pub struct CronActor; -impl CronActor { +/// Cron actor +pub struct Actor; +impl Actor { /// Constructor for Cron actor - fn constructor(_rt: &RT, _params: CronConstructorParams) { + fn constructor(_rt: &RT, _params: ConstructorParams) { // Intentionally left blank } /// epoch_tick executes built-in periodic actions, run at every Epoch. @@ -78,14 +80,14 @@ impl CronActor { } } -impl ActorCode for CronActor { +impl ActorCode for Actor { fn invoke_method(&self, rt: &RT, method: MethodNum, _params: &Serialized) { - match CronMethod::from_method_num(method) { - Some(CronMethod::Constructor) => { + match Method::from_method_num(method) { + Some(Method::Constructor) => { // TODO unfinished spec - Self::constructor(rt, CronConstructorParams::default()) + Self::constructor(rt, ConstructorParams::default()) } - Some(CronMethod::Cron) => { + Some(Method::Cron) => { // TODO unfinished spec self.epoch_tick(rt) } diff --git a/vm/actor/src/builtin/cron/state.rs b/vm/actor/src/builtin/cron/state.rs index 16717865c960..c11cd202422e 100644 --- a/vm/actor/src/builtin/cron/state.rs +++ b/vm/actor/src/builtin/cron/state.rs @@ -7,17 +7,17 @@ use vm::MethodNum; /// Cron actor state which holds entries to call during epoch tick #[derive(Default)] -pub struct CronActorState { +pub struct State { /// Entries is a set of actors (and corresponding methods) to call during EpochTick. - pub entries: Vec, + pub entries: Vec, } -pub struct CronEntry { +pub struct Entry { receiver: Address, method_num: MethodNum, } -impl Serialize for CronActorState { +impl Serialize for State { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -26,17 +26,17 @@ impl Serialize for CronActorState { } } -impl<'de> Deserialize<'de> for CronActorState { +impl<'de> Deserialize<'de> for State { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { - let entries: Vec = Deserialize::deserialize(deserializer)?; + let entries: Vec = Deserialize::deserialize(deserializer)?; Ok(Self { entries }) } } -impl Serialize for CronEntry { +impl Serialize for Entry { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -45,7 +45,7 @@ impl Serialize for CronEntry { } } -impl<'de> Deserialize<'de> for CronEntry { +impl<'de> Deserialize<'de> for Entry { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, diff --git a/vm/actor/src/builtin/init/mod.rs b/vm/actor/src/builtin/init/mod.rs index f3cefe1e3379..3a16ecb15ab4 100644 --- a/vm/actor/src/builtin/init/mod.rs +++ b/vm/actor/src/builtin/init/mod.rs @@ -3,30 +3,37 @@ mod state; -pub use self::state::InitActorState; +pub use self::state::State; use address::Address; use num_derive::FromPrimitive; use num_traits::FromPrimitive; use runtime::{ActorCode, Runtime}; use vm::{CodeID, ExitCode, MethodNum, Serialized, METHOD_CONSTRUCTOR, METHOD_PLACEHOLDER}; +/// Init actor methods available #[derive(FromPrimitive)] -pub enum InitMethod { +pub enum Method { Constructor = METHOD_CONSTRUCTOR, Exec = METHOD_PLACEHOLDER, GetActorIDForAddress = METHOD_PLACEHOLDER + 1, } -impl InitMethod { - /// from_method_num converts a method number into an InitMethod enum - fn from_method_num(m: MethodNum) -> Option { +impl Method { + /// from_method_num converts a method number into an Method enum + fn from_method_num(m: MethodNum) -> Option { FromPrimitive::from_u64(u64::from(m)) } } -pub struct InitActor; -impl InitActor { - fn constructor(_rt: &RT) { +/// Constructor parameters +pub struct ConstructorParams { + pub network_name: String, +} + +/// Init actor +pub struct Actor; +impl Actor { + fn constructor(_rt: &RT, _params: ConstructorParams) { // Acquire state // Update actor substate } @@ -39,21 +46,26 @@ impl InitActor { } } -impl ActorCode for InitActor { +impl ActorCode for Actor { fn invoke_method(&self, rt: &RT, method: MethodNum, params: &Serialized) { // Create mutable copy of params for usage in functions let params: &mut Serialized = &mut params.clone(); - match InitMethod::from_method_num(method) { - Some(InitMethod::Constructor) => { + match Method::from_method_num(method) { + Some(Method::Constructor) => { // TODO unfinished spec - Self::constructor(rt) + Self::constructor( + rt, + ConstructorParams { + network_name: "".into(), + }, + ) } - Some(InitMethod::Exec) => { + Some(Method::Exec) => { // TODO deserialize CodeID on finished spec Self::exec(rt, CodeID::Init, params) } - Some(InitMethod::GetActorIDForAddress) => { + Some(Method::GetActorIDForAddress) => { // Unmarshall address parameter // TODO unfinished spec @@ -68,12 +80,3 @@ impl ActorCode for InitActor { } } } - -#[cfg(test)] -mod test { - - #[test] - fn assign_id() { - // TODO replace with new functionality test on full impl - } -} diff --git a/vm/actor/src/builtin/init/state.rs b/vm/actor/src/builtin/init/state.rs index fd9e0c258761..13207e4b761d 100644 --- a/vm/actor/src/builtin/init/state.rs +++ b/vm/actor/src/builtin/init/state.rs @@ -6,24 +6,25 @@ use address::Address; use cid::Cid; use ipld_blockstore::BlockStore; use ipld_hamt::{Error as HamtError, Hamt}; -use serde::{Deserialize, Serialize}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; use vm::ActorID; -/// InitActorState is reponsible for creating -// TODO implement actual serialize and deserialize to match -#[derive(Serialize, Deserialize)] -pub struct InitActorState { +/// State is reponsible for creating +pub struct State { address_map: Cid, next_id: ActorID, + network_name: String, } -impl InitActorState { - pub fn new(address_map: Cid) -> Self { +impl State { + pub fn new(address_map: Cid, network_name: String) -> Self { Self { address_map, next_id: FIRST_NON_SINGLETON_ADDR, + network_name, } } + /// Assigns next available ID and incremenets the next_id value from state pub fn map_address_to_new_id( &mut self, @@ -50,3 +51,26 @@ impl InitActorState { todo!() } } + +impl Serialize for State { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + (&self.address_map, &self.next_id, &self.network_name).serialize(serializer) + } +} + +impl<'de> Deserialize<'de> for State { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let (address_map, next_id, network_name) = Deserialize::deserialize(deserializer)?; + Ok(Self { + address_map, + next_id, + network_name, + }) + } +} diff --git a/vm/actor/src/builtin/miner/mod.rs b/vm/actor/src/builtin/miner/mod.rs index 4ded1d3e4528..39b920a8c1b1 100644 --- a/vm/actor/src/builtin/miner/mod.rs +++ b/vm/actor/src/builtin/miner/mod.rs @@ -3,6 +3,7 @@ mod state; -pub use self::state::{MinerActorState, MinerInfo}; +pub use self::state::{MinerInfo, State}; -pub struct MinerActor; +/// Miner Actor +pub struct Actor; diff --git a/vm/actor/src/builtin/miner/state.rs b/vm/actor/src/builtin/miner/state.rs index 69337ad81c31..69643d95ea4e 100644 --- a/vm/actor/src/builtin/miner/state.rs +++ b/vm/actor/src/builtin/miner/state.rs @@ -7,9 +7,9 @@ use encoding::de; use libp2p::PeerId; use serde::Deserialize; -/// Container representing storage miner actor state -pub struct MinerActorState { - // TODO add proving_set, post_state +/// Miner actor state +pub struct State { + // TODO update fields to match current spec /// The height at which this miner was slashed at. pub slashed_at: u64, /// Sectors this miner has committed @@ -18,7 +18,7 @@ pub struct MinerActorState { pub info: Cid, } -impl<'de> de::Deserialize<'de> for MinerActorState { +impl<'de> de::Deserialize<'de> for State { fn deserialize(deserializer: D) -> Result where D: de::Deserializer<'de>, @@ -43,6 +43,7 @@ pub struct MinerInfo { /// sign messages sent on behalf of this miner to commit sectors, submit PoSts, and /// other day to day miner activities _worker_address: Address, + // TODO missing worker key /// Libp2p identity that should be used when connecting to this miner _peer_id: PeerId, /// Amount of space in each sector committed to the network by this miner diff --git a/vm/actor/src/builtin/mod.rs b/vm/actor/src/builtin/mod.rs index 89a5061d19a8..98ae7ba8a26f 100644 --- a/vm/actor/src/builtin/mod.rs +++ b/vm/actor/src/builtin/mod.rs @@ -1,16 +1,9 @@ // Copyright 2020 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -mod account; -mod cron; -mod init; -mod miner; -mod power; -mod reward; - -pub use self::account::*; -pub use self::cron::*; -pub use self::init::*; -pub use self::miner::*; -pub use self::power::*; -pub use self::reward::*; +pub mod account; +pub mod cron; +pub mod init; +pub mod miner; +pub mod power; +pub mod reward; diff --git a/vm/actor/src/builtin/power/mod.rs b/vm/actor/src/builtin/power/mod.rs index 29a8f2e55179..4227bf106109 100644 --- a/vm/actor/src/builtin/power/mod.rs +++ b/vm/actor/src/builtin/power/mod.rs @@ -3,15 +3,15 @@ mod state; -pub use self::state::PowerActorState; +pub use self::state::State; use num_derive::FromPrimitive; use num_traits::FromPrimitive; use runtime::{ActorCode, Runtime}; use vm::{ExitCode, MethodNum, Serialized, METHOD_CONSTRUCTOR}; -/// Method definitions for Storage Power Actor +/// Storage power actor methods available #[derive(FromPrimitive)] -pub enum PowerMethod { +pub enum Method { /// Constructor for Storage Power Actor Constructor = METHOD_CONSTRUCTOR, // TODO add other methods on finished spec @@ -19,15 +19,16 @@ pub enum PowerMethod { GetTotalStorage = 5, } -impl PowerMethod { - /// from_method_num converts a method number into an PowerMethod enum - fn from_method_num(m: MethodNum) -> Option { +impl Method { + /// from_method_num converts a method number into an Method enum + fn from_method_num(m: MethodNum) -> Option { FromPrimitive::from_u64(u64::from(m)) } } -pub struct PowerActor; -impl PowerActor { +/// Storage Power Actor +pub struct Actor; +impl Actor { /// Constructor for StoragePower actor fn constructor(_rt: &RT) { // TODO @@ -40,12 +41,12 @@ impl PowerActor { } } -impl ActorCode for PowerActor { +impl ActorCode for Actor { fn invoke_method(&self, rt: &RT, method: MethodNum, _params: &Serialized) { - match PowerMethod::from_method_num(method) { + match Method::from_method_num(method) { // TODO determine parameters for each method on finished spec - Some(PowerMethod::Constructor) => Self::constructor(rt), - Some(PowerMethod::GetTotalStorage) => Self::get_total_storage(rt), + Some(Method::Constructor) => Self::constructor(rt), + Some(Method::GetTotalStorage) => Self::get_total_storage(rt), _ => { rt.abort(ExitCode::SysErrInvalidMethod, "Invalid method".to_owned()); unreachable!(); diff --git a/vm/actor/src/builtin/power/state.rs b/vm/actor/src/builtin/power/state.rs index 7d1af5ab8974..658ffc3ab855 100644 --- a/vm/actor/src/builtin/power/state.rs +++ b/vm/actor/src/builtin/power/state.rs @@ -3,8 +3,8 @@ use num_bigint::BigUint; -/// State of storage power actor -pub struct PowerActorState { +/// Storage power actor state +pub struct State { // TODO add power tables on finished spec _total_storage: BigUint, } diff --git a/vm/actor/src/builtin/reward/mod.rs b/vm/actor/src/builtin/reward/mod.rs index abb539b5bbae..b3594f6eaca1 100644 --- a/vm/actor/src/builtin/reward/mod.rs +++ b/vm/actor/src/builtin/reward/mod.rs @@ -3,28 +3,30 @@ mod state; -pub use self::state::{Reward, RewardActorState}; +pub use self::state::{Reward, State}; use num_derive::FromPrimitive; use num_traits::FromPrimitive; use runtime::{ActorCode, Runtime}; use vm::{ExitCode, MethodNum, Serialized, METHOD_CONSTRUCTOR, METHOD_PLACEHOLDER}; +/// Reward actor methods available #[derive(FromPrimitive)] -pub enum RewardMethod { +pub enum Method { Constructor = METHOD_CONSTRUCTOR, MintReward = METHOD_PLACEHOLDER, WithdrawReward = METHOD_PLACEHOLDER + 1, } -impl RewardMethod { - /// from_method_num converts a method number into an RewardMethod enum - fn from_method_num(m: MethodNum) -> Option { +impl Method { + /// from_method_num converts a method number into an Method enum + fn from_method_num(m: MethodNum) -> Option { FromPrimitive::from_u64(u64::from(m)) } } -pub struct RewardActor; -impl RewardActor { +/// Reward Actor +pub struct Actor; +impl Actor { /// Constructor for Reward actor fn constructor(_rt: &RT) { // TODO @@ -42,13 +44,13 @@ impl RewardActor { } } -impl ActorCode for RewardActor { +impl ActorCode for Actor { fn invoke_method(&self, rt: &RT, method: MethodNum, _params: &Serialized) { - match RewardMethod::from_method_num(method) { + match Method::from_method_num(method) { // TODO determine parameters for each method on finished spec - Some(RewardMethod::Constructor) => Self::constructor(rt), - Some(RewardMethod::MintReward) => Self::mint_reward(rt), - Some(RewardMethod::WithdrawReward) => Self::withdraw_reward(rt), + Some(Method::Constructor) => Self::constructor(rt), + Some(Method::MintReward) => Self::mint_reward(rt), + Some(Method::WithdrawReward) => Self::withdraw_reward(rt), _ => { rt.abort(ExitCode::SysErrInvalidMethod, "Invalid method".to_owned()); unreachable!(); diff --git a/vm/actor/src/builtin/reward/state.rs b/vm/actor/src/builtin/reward/state.rs index 91eedbb96ed4..4554533bbaa4 100644 --- a/vm/actor/src/builtin/reward/state.rs +++ b/vm/actor/src/builtin/reward/state.rs @@ -2,26 +2,55 @@ // SPDX-License-Identifier: Apache-2.0, MIT use address::Address; +use cid::Cid; use clock::ChainEpoch; -use runtime::Runtime; -use std::collections::HashMap; +use ipld_blockstore::BlockStore; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; use vm::TokenAmount; pub struct Reward { + // TODO update to new spec pub start_epoch: ChainEpoch, pub value: TokenAmount, pub release_rate: TokenAmount, pub amount_withdrawn: TokenAmount, } -/// RewardActorState has no internal state -pub struct RewardActorState { - pub reward_map: HashMap>, +/// Reward actor state +pub struct State { + pub reward_map: Cid, + pub reward_total: TokenAmount, } -impl RewardActorState { - pub fn withdraw_reward(_rt: &RT, _owner: Address) -> TokenAmount { +impl State { + pub fn withdraw_reward( + _store: &BS, + _owner: Address, + _curr_epoch: ChainEpoch, + ) -> TokenAmount { // TODO - TokenAmount::new(0) + todo!() + } +} + +impl Serialize for State { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + (&self.reward_map, &self.reward_total).serialize(serializer) + } +} + +impl<'de> Deserialize<'de> for State { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let (reward_map, reward_total) = Deserialize::deserialize(deserializer)?; + Ok(Self { + reward_map, + reward_total, + }) } } diff --git a/vm/state_tree/src/lib.rs b/vm/state_tree/src/lib.rs index 884eb7d4b929..a755e0f0ae5f 100644 --- a/vm/state_tree/src/lib.rs +++ b/vm/state_tree/src/lib.rs @@ -3,7 +3,7 @@ pub use vm::StateTree; -use actor::{InitActorState, INIT_ACTOR_ADDR}; +use actor::{init, INIT_ACTOR_ADDR}; use address::{Address, Protocol}; use cid::{multihash::Blake2b256, Cid}; use fnv::FnvHashMap; @@ -109,7 +109,7 @@ where .get_actor(&INIT_ACTOR_ADDR)? .ok_or("Init actor address could not be resolved")?; - let state: InitActorState = self + let state: init::State = self .hamt .store() .get(&init_act.state) @@ -155,7 +155,7 @@ where .ok_or("Could not retrieve init actor")?; // Get init actor state from store - let mut ias: InitActorState = self + let mut ias: init::State = self .hamt .store() .get(&init_act.state) diff --git a/vm/state_tree/tests/state_tree_tests.rs b/vm/state_tree/tests/state_tree_tests.rs index bb8f5cca63f8..c2a13c433f69 100644 --- a/vm/state_tree/tests/state_tree_tests.rs +++ b/vm/state_tree/tests/state_tree_tests.rs @@ -1,7 +1,7 @@ // Copyright 2020 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -use actor::{ActorState, InitActorState, INIT_ACTOR_ADDR}; +use actor::{init, ActorState, INIT_ACTOR_ADDR}; use address::Address; use cid::{multihash::Blake2b256, Cid}; use ipld_blockstore::BlockStore; @@ -52,7 +52,7 @@ fn get_set_non_id() { .flush() .unwrap(); - let init_state = InitActorState::new(e_cid.clone()); + let init_state = init::State::new(e_cid.clone(), "test".to_owned()); let state_cid = tree .store() .put(&init_state, Blake2b256) From c3eb93d86a4a490f733c5d59b97ffd5ec8dcd3fc Mon Sep 17 00:00:00 2001 From: austinabell Date: Sat, 14 Mar 2020 13:25:59 -0400 Subject: [PATCH 04/11] Clean up method calls --- vm/actor/src/builtin/account/mod.rs | 21 +++++++++++++++---- vm/actor/src/builtin/cron/mod.rs | 9 +++++---- vm/actor/src/builtin/init/mod.rs | 29 ++++++++++----------------- vm/actor/src/builtin/power/mod.rs | 31 +++++++++++++++++++---------- vm/actor/src/builtin/reward/mod.rs | 24 +++++++++++----------- vm/src/method.rs | 6 ------ 6 files changed, 65 insertions(+), 55 deletions(-) diff --git a/vm/actor/src/builtin/account/mod.rs b/vm/actor/src/builtin/account/mod.rs index dae0af6657ff..72881390da9a 100644 --- a/vm/actor/src/builtin/account/mod.rs +++ b/vm/actor/src/builtin/account/mod.rs @@ -4,6 +4,7 @@ mod state; pub use self::state::State; +use address::Address; use num_derive::FromPrimitive; use num_traits::FromPrimitive; use runtime::{ActorCode, Runtime}; @@ -13,6 +14,7 @@ use vm::{ExitCode, MethodNum, Serialized, METHOD_CONSTRUCTOR}; #[derive(FromPrimitive)] pub enum Method { Constructor = METHOD_CONSTRUCTOR, + PubkeyAddress = 2, } impl Method { @@ -26,8 +28,15 @@ impl Method { pub struct Actor; impl Actor { /// Constructor for Account actor - fn constructor(_rt: &RT) { - // Intentionally left blank + pub fn constructor(_rt: &RT, _address: Address) { + // TODO now updated spec + todo!() + } + + // Fetches the pubkey-type address from this actor. + pub fn pubkey_address(_rt: &RT) -> Address { + // TODO + todo!() } } @@ -35,8 +44,12 @@ impl ActorCode for Actor { fn invoke_method(&self, rt: &RT, method: MethodNum, _params: &Serialized) { match Method::from_method_num(method) { Some(Method::Constructor) => { - // TODO unfinished spec - Self::constructor(rt) + // TODO deserialize address from params + Self::constructor(rt, Address::default()) + } + Some(Method::PubkeyAddress) => { + // TODO assert that no params and handle return + let _ = Self::pubkey_address(rt); } _ => { rt.abort(ExitCode::SysErrInvalidMethod, "Invalid method".to_owned()); diff --git a/vm/actor/src/builtin/cron/mod.rs b/vm/actor/src/builtin/cron/mod.rs index 2c33f2843505..dd0bd65f6ba8 100644 --- a/vm/actor/src/builtin/cron/mod.rs +++ b/vm/actor/src/builtin/cron/mod.rs @@ -8,13 +8,13 @@ use num_derive::FromPrimitive; use num_traits::FromPrimitive; use runtime::{ActorCode, Runtime}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use vm::{ExitCode, MethodNum, Serialized, METHOD_CONSTRUCTOR, METHOD_CRON}; +use vm::{ExitCode, MethodNum, Serialized, METHOD_CONSTRUCTOR}; /// Cron actor methods available #[derive(FromPrimitive)] pub enum Method { Constructor = METHOD_CONSTRUCTOR, - Cron = METHOD_CRON, + EpochTick = 2, } impl Method { @@ -56,7 +56,8 @@ pub struct Actor; impl Actor { /// Constructor for Cron actor fn constructor(_rt: &RT, _params: ConstructorParams) { - // Intentionally left blank + // TODO now finished spec + todo!() } /// epoch_tick executes built-in periodic actions, run at every Epoch. /// epoch_tick(r) is called after all other messages in the epoch have been applied. @@ -87,7 +88,7 @@ impl ActorCode for Actor { // TODO unfinished spec Self::constructor(rt, ConstructorParams::default()) } - Some(Method::Cron) => { + Some(Method::EpochTick) => { // TODO unfinished spec self.epoch_tick(rt) } diff --git a/vm/actor/src/builtin/init/mod.rs b/vm/actor/src/builtin/init/mod.rs index 3a16ecb15ab4..8927825b9245 100644 --- a/vm/actor/src/builtin/init/mod.rs +++ b/vm/actor/src/builtin/init/mod.rs @@ -4,18 +4,16 @@ mod state; pub use self::state::State; -use address::Address; use num_derive::FromPrimitive; use num_traits::FromPrimitive; use runtime::{ActorCode, Runtime}; -use vm::{CodeID, ExitCode, MethodNum, Serialized, METHOD_CONSTRUCTOR, METHOD_PLACEHOLDER}; +use vm::{ExitCode, MethodNum, Serialized, METHOD_CONSTRUCTOR}; /// Init actor methods available #[derive(FromPrimitive)] pub enum Method { Constructor = METHOD_CONSTRUCTOR, - Exec = METHOD_PLACEHOLDER, - GetActorIDForAddress = METHOD_PLACEHOLDER + 1, + Exec = 2, } impl Method { @@ -33,15 +31,17 @@ pub struct ConstructorParams { /// Init actor pub struct Actor; impl Actor { - fn constructor(_rt: &RT, _params: ConstructorParams) { + /// Init actor constructor + pub fn constructor(_rt: &RT, _params: ConstructorParams) { + // TODO + todo!() // Acquire state // Update actor substate } - fn exec(_rt: &RT, _code: CodeID, _params: &Serialized) { - todo!() - } - fn get_actor_id_for_address(_rt: &RT, _address: Address) { - // TODO + + /// Exec init actor + pub fn exec(_rt: &RT, _params: &Serialized) { + // TODO update and include exec params type and return todo!() } } @@ -63,14 +63,7 @@ impl ActorCode for Actor { } Some(Method::Exec) => { // TODO deserialize CodeID on finished spec - Self::exec(rt, CodeID::Init, params) - } - Some(Method::GetActorIDForAddress) => { - // Unmarshall address parameter - // TODO unfinished spec - - // Errors checked, get actor by address - Self::get_actor_id_for_address(rt, Address::default()) + Self::exec(rt, params) } _ => { // Method number does not match available, abort in runtime diff --git a/vm/actor/src/builtin/power/mod.rs b/vm/actor/src/builtin/power/mod.rs index 4227bf106109..30dc337a4a20 100644 --- a/vm/actor/src/builtin/power/mod.rs +++ b/vm/actor/src/builtin/power/mod.rs @@ -14,9 +14,20 @@ use vm::{ExitCode, MethodNum, Serialized, METHOD_CONSTRUCTOR}; pub enum Method { /// Constructor for Storage Power Actor Constructor = METHOD_CONSTRUCTOR, - // TODO add other methods on finished spec - /// Gets the total storage for the network - GetTotalStorage = 5, + AddBalance = 2, + WithdrawBalance = 3, + CreateMiner = 4, + DeleteMiner = 5, + OnSectorProveCommit = 6, + OnSectorTerminate = 7, + OnSectorTemporaryFaultEffectiveBegin = 8, + OnSectorTemporaryFaultEffectiveEnd = 9, + OnSectorModifyWeightDesc = 10, + OnMinerWindowedPoStSuccess = 11, + OnMinerWindowedPoStFailure = 12, + EnrollCronEvent = 13, + ReportConsensusFault = 14, + OnEpochTickEnd = 15, } impl Method { @@ -34,19 +45,17 @@ impl Actor { // TODO todo!(); } - /// Withdraw available funds from StoragePower map - fn get_total_storage(_rt: &RT) { - // TODO - todo!() - } + // TODO implement other actor methods based on methods available } impl ActorCode for Actor { fn invoke_method(&self, rt: &RT, method: MethodNum, _params: &Serialized) { match Method::from_method_num(method) { - // TODO determine parameters for each method on finished spec - Some(Method::Constructor) => Self::constructor(rt), - Some(Method::GetTotalStorage) => Self::get_total_storage(rt), + Some(Method::Constructor) => { + // TODO make sure params is empty + Self::constructor(rt) + } + // TODO handle other methods available _ => { rt.abort(ExitCode::SysErrInvalidMethod, "Invalid method".to_owned()); unreachable!(); diff --git a/vm/actor/src/builtin/reward/mod.rs b/vm/actor/src/builtin/reward/mod.rs index b3594f6eaca1..0b6d7864e7f2 100644 --- a/vm/actor/src/builtin/reward/mod.rs +++ b/vm/actor/src/builtin/reward/mod.rs @@ -4,17 +4,18 @@ mod state; pub use self::state::{Reward, State}; +use address::Address; use num_derive::FromPrimitive; use num_traits::FromPrimitive; use runtime::{ActorCode, Runtime}; -use vm::{ExitCode, MethodNum, Serialized, METHOD_CONSTRUCTOR, METHOD_PLACEHOLDER}; +use vm::{ExitCode, MethodNum, Serialized, METHOD_CONSTRUCTOR}; /// Reward actor methods available #[derive(FromPrimitive)] pub enum Method { Constructor = METHOD_CONSTRUCTOR, - MintReward = METHOD_PLACEHOLDER, - WithdrawReward = METHOD_PLACEHOLDER + 1, + AwardBlockReward = 2, + WithdrawReward = 3, } impl Method { @@ -30,27 +31,26 @@ impl Actor { /// Constructor for Reward actor fn constructor(_rt: &RT) { // TODO - unimplemented!(); + todo!(); } /// Mints a reward and puts into state reward map - fn mint_reward(_rt: &RT) { - // TODO - unimplemented!(); + fn award_block_reward(_rt: &RT) { + // TODO add params type and implement + todo!(); } /// Withdraw available funds from reward map - fn withdraw_reward(_rt: &RT) { + fn withdraw_reward(_rt: &RT, _miner_in: &Address) { // TODO - unimplemented!(); + todo!(); } } impl ActorCode for Actor { fn invoke_method(&self, rt: &RT, method: MethodNum, _params: &Serialized) { match Method::from_method_num(method) { - // TODO determine parameters for each method on finished spec Some(Method::Constructor) => Self::constructor(rt), - Some(Method::MintReward) => Self::mint_reward(rt), - Some(Method::WithdrawReward) => Self::withdraw_reward(rt), + Some(Method::AwardBlockReward) => Self::award_block_reward(rt), + Some(Method::WithdrawReward) => Self::withdraw_reward(rt, &Address::default()), _ => { rt.abort(ExitCode::SysErrInvalidMethod, "Invalid method".to_owned()); unreachable!(); diff --git a/vm/src/method.rs b/vm/src/method.rs index 839ea4e52a94..0fad8fadc25d 100644 --- a/vm/src/method.rs +++ b/vm/src/method.rs @@ -26,12 +26,6 @@ impl From for u64 { pub const METHOD_SEND: isize = 0; /// Base actor constructor method pub const METHOD_CONSTRUCTOR: isize = 1; -/// Base actor cron method -pub const METHOD_CRON: isize = 2; - -/// Placeholder for non base methods for actors -// TODO revisit on complete spec -pub const METHOD_PLACEHOLDER: isize = 3; /// Serialized bytes to be used as parameters into actor methods #[derive(Default, Clone, PartialEq, Debug)] From 992cc0a4305e911d6b5cde9566146755943e74ae Mon Sep 17 00:00:00 2001 From: austinabell Date: Sat, 14 Mar 2020 15:37:22 -0400 Subject: [PATCH 05/11] Implement account actor and refactor params serialization and deserialization for invocation --- vm/actor/src/builtin/account/mod.rs | 37 +++++++++++++------ vm/actor/src/builtin/account/state.rs | 3 ++ vm/actor/src/builtin/cron/mod.rs | 19 ++++++---- vm/actor/src/builtin/init/mod.rs | 42 ++++++++++++++++------ vm/actor/src/builtin/power/mod.rs | 13 +++++-- vm/actor/src/builtin/reward/mod.rs | 24 ++++++++++--- vm/actor/src/lib.rs | 17 +++++---- vm/message/src/message_receipt.rs | 5 ++- vm/runtime/src/actor_code.rs | 8 +++-- vm/runtime/src/lib.rs | 52 ++++++++++++--------------- vm/src/method.rs | 11 ++++-- 11 files changed, 150 insertions(+), 81 deletions(-) diff --git a/vm/actor/src/builtin/account/mod.rs b/vm/actor/src/builtin/account/mod.rs index 72881390da9a..6aa7ef7ec8e1 100644 --- a/vm/actor/src/builtin/account/mod.rs +++ b/vm/actor/src/builtin/account/mod.rs @@ -4,7 +4,8 @@ mod state; pub use self::state::State; -use address::Address; +use crate::{assert_empty_params, empty_return}; +use address::{Address, Protocol}; use num_derive::FromPrimitive; use num_traits::FromPrimitive; use runtime::{ActorCode, Runtime}; @@ -28,28 +29,42 @@ impl Method { pub struct Actor; impl Actor { /// Constructor for Account actor - pub fn constructor(_rt: &RT, _address: Address) { - // TODO now updated spec + pub fn constructor(rt: &RT, address: Address) { + rt.validate_immediate_caller_is(&[address.clone()]); + match address.protocol() { + Protocol::Secp256k1 | Protocol::BLS => (), + protocol => rt.abort( + ExitCode::ErrIllegalArgument, + format!("address must use BLS or SECP protocol, got {}", protocol), + ), + } todo!() } // Fetches the pubkey-type address from this actor. - pub fn pubkey_address(_rt: &RT) -> Address { - // TODO - todo!() + pub fn pubkey_address(rt: &RT) -> Address { + rt.validate_immediate_caller_accept_any(); + let st: State = rt.state(); + st.address } } impl ActorCode for Actor { - fn invoke_method(&self, rt: &RT, method: MethodNum, _params: &Serialized) { + fn invoke_method( + &self, + rt: &RT, + method: MethodNum, + params: &Serialized, + ) -> Serialized { match Method::from_method_num(method) { Some(Method::Constructor) => { - // TODO deserialize address from params - Self::constructor(rt, Address::default()) + Self::constructor(rt, params.deserialize().unwrap()); + empty_return() } Some(Method::PubkeyAddress) => { - // TODO assert that no params and handle return - let _ = Self::pubkey_address(rt); + assert_empty_params(params); + Self::pubkey_address(rt); + empty_return() } _ => { rt.abort(ExitCode::SysErrInvalidMethod, "Invalid method".to_owned()); diff --git a/vm/actor/src/builtin/account/state.rs b/vm/actor/src/builtin/account/state.rs index a6d79e6f8628..c86e0731cf6c 100644 --- a/vm/actor/src/builtin/account/state.rs +++ b/vm/actor/src/builtin/account/state.rs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0, MIT use address::Address; +use encoding::Cbor; use serde::{Deserialize, Deserializer, Serialize, Serializer}; /// State includes the address for the actor @@ -28,3 +29,5 @@ impl<'de> Deserialize<'de> for State { Ok(Self { address }) } } + +impl Cbor for State {} diff --git a/vm/actor/src/builtin/cron/mod.rs b/vm/actor/src/builtin/cron/mod.rs index dd0bd65f6ba8..736ef3c67631 100644 --- a/vm/actor/src/builtin/cron/mod.rs +++ b/vm/actor/src/builtin/cron/mod.rs @@ -4,6 +4,7 @@ mod state; pub use self::state::{Entry, State}; +use crate::{assert_empty_params, empty_return}; use num_derive::FromPrimitive; use num_traits::FromPrimitive; use runtime::{ActorCode, Runtime}; @@ -62,7 +63,7 @@ impl Actor { /// epoch_tick executes built-in periodic actions, run at every Epoch. /// epoch_tick(r) is called after all other messages in the epoch have been applied. /// This can be seen as an implicit last message. - fn epoch_tick(&self, _rt: &RT) { + fn epoch_tick(_rt: &RT) { // self.entries is basically a static registry for now, loaded // in the interpreter static registry. // TODO update to new spec @@ -82,15 +83,21 @@ impl Actor { } impl ActorCode for Actor { - fn invoke_method(&self, rt: &RT, method: MethodNum, _params: &Serialized) { + fn invoke_method( + &self, + rt: &RT, + method: MethodNum, + params: &Serialized, + ) -> Serialized { match Method::from_method_num(method) { Some(Method::Constructor) => { - // TODO unfinished spec - Self::constructor(rt, ConstructorParams::default()) + Self::constructor(rt, params.deserialize().unwrap()); + empty_return() } Some(Method::EpochTick) => { - // TODO unfinished spec - self.epoch_tick(rt) + assert_empty_params(params); + Self::epoch_tick(rt); + empty_return() } _ => { rt.abort(ExitCode::SysErrInvalidMethod, "Invalid method".to_owned()); diff --git a/vm/actor/src/builtin/init/mod.rs b/vm/actor/src/builtin/init/mod.rs index 8927825b9245..1e72df61469b 100644 --- a/vm/actor/src/builtin/init/mod.rs +++ b/vm/actor/src/builtin/init/mod.rs @@ -4,9 +4,11 @@ mod state; pub use self::state::State; +use crate::empty_return; use num_derive::FromPrimitive; use num_traits::FromPrimitive; use runtime::{ActorCode, Runtime}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; use vm::{ExitCode, MethodNum, Serialized, METHOD_CONSTRUCTOR}; /// Init actor methods available @@ -40,29 +42,28 @@ impl Actor { } /// Exec init actor - pub fn exec(_rt: &RT, _params: &Serialized) { + pub fn exec(_rt: &RT, _params: &Serialized) -> Serialized { // TODO update and include exec params type and return todo!() } } impl ActorCode for Actor { - fn invoke_method(&self, rt: &RT, method: MethodNum, params: &Serialized) { + fn invoke_method( + &self, + rt: &RT, + method: MethodNum, + params: &Serialized, + ) -> Serialized { // Create mutable copy of params for usage in functions let params: &mut Serialized = &mut params.clone(); match Method::from_method_num(method) { Some(Method::Constructor) => { - // TODO unfinished spec - - Self::constructor( - rt, - ConstructorParams { - network_name: "".into(), - }, - ) + Self::constructor(rt, params.deserialize().unwrap()); + empty_return() } Some(Method::Exec) => { - // TODO deserialize CodeID on finished spec + // TODO update to correct param type Self::exec(rt, params) } _ => { @@ -73,3 +74,22 @@ impl ActorCode for Actor { } } } + +impl Serialize for ConstructorParams { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + [&self.network_name].serialize(serializer) + } +} + +impl<'de> Deserialize<'de> for ConstructorParams { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let [network_name]: [String; 1] = Deserialize::deserialize(deserializer)?; + Ok(Self { network_name }) + } +} diff --git a/vm/actor/src/builtin/power/mod.rs b/vm/actor/src/builtin/power/mod.rs index 30dc337a4a20..40b0b26ac886 100644 --- a/vm/actor/src/builtin/power/mod.rs +++ b/vm/actor/src/builtin/power/mod.rs @@ -4,6 +4,7 @@ mod state; pub use self::state::State; +use crate::{assert_empty_params, empty_return}; use num_derive::FromPrimitive; use num_traits::FromPrimitive; use runtime::{ActorCode, Runtime}; @@ -49,11 +50,17 @@ impl Actor { } impl ActorCode for Actor { - fn invoke_method(&self, rt: &RT, method: MethodNum, _params: &Serialized) { + fn invoke_method( + &self, + rt: &RT, + method: MethodNum, + params: &Serialized, + ) -> Serialized { match Method::from_method_num(method) { Some(Method::Constructor) => { - // TODO make sure params is empty - Self::constructor(rt) + assert_empty_params(params); + Self::constructor(rt); + empty_return() } // TODO handle other methods available _ => { diff --git a/vm/actor/src/builtin/reward/mod.rs b/vm/actor/src/builtin/reward/mod.rs index 0b6d7864e7f2..4d3208d40609 100644 --- a/vm/actor/src/builtin/reward/mod.rs +++ b/vm/actor/src/builtin/reward/mod.rs @@ -4,6 +4,7 @@ mod state; pub use self::state::{Reward, State}; +use crate::{assert_empty_params, empty_return}; use address::Address; use num_derive::FromPrimitive; use num_traits::FromPrimitive; @@ -46,11 +47,26 @@ impl Actor { } impl ActorCode for Actor { - fn invoke_method(&self, rt: &RT, method: MethodNum, _params: &Serialized) { + fn invoke_method( + &self, + rt: &RT, + method: MethodNum, + params: &Serialized, + ) -> Serialized { match Method::from_method_num(method) { - Some(Method::Constructor) => Self::constructor(rt), - Some(Method::AwardBlockReward) => Self::award_block_reward(rt), - Some(Method::WithdrawReward) => Self::withdraw_reward(rt, &Address::default()), + Some(Method::Constructor) => { + assert_empty_params(params); + Self::constructor(rt); + empty_return() + } + Some(Method::AwardBlockReward) => { + Self::award_block_reward(rt); + empty_return() + } + Some(Method::WithdrawReward) => { + Self::withdraw_reward(rt, ¶ms.deserialize().unwrap()); + empty_return() + } _ => { rt.abort(ExitCode::SysErrInvalidMethod, "Invalid method".to_owned()); unreachable!(); diff --git a/vm/actor/src/lib.rs b/vm/actor/src/lib.rs index 82a583b9ea07..8bc03e663ff4 100644 --- a/vm/actor/src/lib.rs +++ b/vm/actor/src/lib.rs @@ -9,15 +9,14 @@ mod singletons; pub use self::builtin::*; pub use self::singletons::*; -pub use vm::{ActorID, ActorState}; +pub use vm::{ActorID, ActorState, Serialized}; -use cid::Cid; +/// Used when invocation requires parameters to be an empty array of bytes +fn assert_empty_params(params: &Serialized) { + params.deserialize::<[u8; 0]>().unwrap(); +} -// TODO implement Actor for builtin actors on finished spec -/// Actor trait which defines the common functionality of system Actors -pub trait Actor { - /// Returns Actor Cid - fn cid(&self) -> &Cid; - /// Actor public key, if it exists - fn public_key(&self) -> Vec; +/// Empty return is an empty serialized array +fn empty_return() -> Serialized { + Serialized::serialize::<[u8; 0]>([]).unwrap() } diff --git a/vm/message/src/message_receipt.rs b/vm/message/src/message_receipt.rs index 5dfe8bab0ab3..5abb69a3959e 100644 --- a/vm/message/src/message_receipt.rs +++ b/vm/message/src/message_receipt.rs @@ -2,13 +2,12 @@ // SPDX-License-Identifier: Apache-2.0, MIT use num_bigint::BigUint; -use vm::ExitCode; +use vm::{ExitCode, Serialized}; /// Result of a state transition from a message #[derive(PartialEq, Clone)] pub struct MessageReceipt { - // TODO: determine if this is necessary, code returned from cbor pub exit_code: ExitCode, - pub return_data: Vec, + pub return_data: Serialized, pub gas_used: BigUint, } diff --git a/vm/runtime/src/actor_code.rs b/vm/runtime/src/actor_code.rs index 95f33e086353..1d459ee852c2 100644 --- a/vm/runtime/src/actor_code.rs +++ b/vm/runtime/src/actor_code.rs @@ -8,6 +8,10 @@ use vm::{MethodNum, Serialized}; pub trait ActorCode { /// Invokes method with runtime on the actor's code. Method number will match one /// defined by the Actor, and parameters will be serialized and used in execution - fn invoke_method(&self, rt: &RT, method: MethodNum, params: &Serialized); - // TODO update output to new spec + fn invoke_method( + &self, + rt: &RT, + method: MethodNum, + params: &Serialized, + ) -> Serialized; } diff --git a/vm/runtime/src/lib.rs b/vm/runtime/src/lib.rs index bfe27ca13a2c..2731164ce8e2 100644 --- a/vm/runtime/src/lib.rs +++ b/vm/runtime/src/lib.rs @@ -52,15 +52,35 @@ pub trait Runtime { entropy: &[u8], ) -> Randomness; - /// Provides a handle for the actor's state object. - fn state(&self) -> &SH; + /// Initializes the state object. + /// This is only valid in a constructor function and when the state has not yet been initialized. + fn create(&self, obj: &C); + + /// Loads a readonly copy of the state of the receiver into the argument. + /// + /// Any modification to the state is illegal and will result in an abort. + fn state(&self) -> C; + + /// Loads a mutable version of the state into the `obj` argument and protects + /// the execution from side effects (including message send). + /// + /// The second argument is a function which allows the caller to mutate the state. + /// The return value from that function will be returned from the call to Transaction(). + /// + /// If the state is modified after this function returns, execution will abort. + /// + /// The gas cost of this method is that of a Store.Put of the mutated state object. + fn transaction(&self, obj: &C, f: F) -> R + where + F: Fn() -> R; + /// Returns reference to blockstore fn store(&self) -> &S; /// Sends a message to another actor, returning the exit code and return value envelope. /// If the invoked method does not return successfully, its state changes (and that of any messages it sent in turn) /// will be rolled back. - fn send( + fn send( &self, to: Address, method: MethodNum, @@ -106,32 +126,6 @@ pub trait MessageInfo { fn value_received(&self) -> TokenAmount; } -/// StateHandle provides mutable, exclusive access to actor state. -pub trait StateHandle { - /// Initializes the state object. - /// This is only valid in a constructor function and when the state has not yet been initialized. - fn create(&self, obj: &C); - - /// Loads a readonly copy of the state into the argument. - /// - /// Any modification to the state is illegal and will result in an abort. - // TODO is this necessary? if we are sure that we can return a reference to data that will for sure be in memory this should return &C - fn readonly(&self) -> C; - - /// Loads a mutable version of the state into the `obj` argument and protects - /// the execution from side effects (including message send). - /// - /// The second argument is a function which allows the caller to mutate the state. - /// The return value from that function will be returned from the call to Transaction(). - /// - /// If the state is modified after this function returns, execution will abort. - /// - /// The gas cost of this method is that of a Store.Put of the mutated state object. - fn transaction(&self, obj: &C, f: F) -> R - where - F: Fn() -> R; -} - /// Pure functions implemented as primitives by the runtime. // TODO this may have to be a trait impl to handle dynamically pub struct Syscalls; diff --git a/vm/src/method.rs b/vm/src/method.rs index 0fad8fadc25d..17f513229a60 100644 --- a/vm/src/method.rs +++ b/vm/src/method.rs @@ -1,7 +1,7 @@ // Copyright 2020 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -use encoding::{de, ser, serde_bytes, to_vec, Error as EncodingError}; +use encoding::{de, from_slice, ser, serde_bytes, to_vec, Error as EncodingError}; use serde::{Deserialize, Serialize}; use std::ops::Deref; @@ -74,7 +74,12 @@ impl Serialized { } /// Returns serialized bytes - pub fn bytes(&self) -> Vec { - self.bytes.clone() + pub fn bytes(&self) -> &[u8] { + &self.bytes + } + + /// Deserializes into a defined type + pub fn deserialize(&self) -> Result { + Ok(from_slice(&self.bytes)?) } } From 14bad867ffc040267f8ecd9f74f922f0d2b521b0 Mon Sep 17 00:00:00 2001 From: austinabell Date: Sat, 14 Mar 2020 17:37:35 -0400 Subject: [PATCH 06/11] Replace todo --- vm/actor/src/builtin/account/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vm/actor/src/builtin/account/mod.rs b/vm/actor/src/builtin/account/mod.rs index 6aa7ef7ec8e1..421d9d59ad6e 100644 --- a/vm/actor/src/builtin/account/mod.rs +++ b/vm/actor/src/builtin/account/mod.rs @@ -38,7 +38,7 @@ impl Actor { format!("address must use BLS or SECP protocol, got {}", protocol), ), } - todo!() + rt.create(&State { address }) } // Fetches the pubkey-type address from this actor. From b4d4252ccc817be1722bcc5ed499bf6fbf86ea3f Mon Sep 17 00:00:00 2001 From: austinabell Date: Sat, 14 Mar 2020 17:41:20 -0400 Subject: [PATCH 07/11] Remove unnecessary params clone --- vm/actor/src/builtin/init/mod.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/vm/actor/src/builtin/init/mod.rs b/vm/actor/src/builtin/init/mod.rs index 1e72df61469b..ddba2f1d1dbb 100644 --- a/vm/actor/src/builtin/init/mod.rs +++ b/vm/actor/src/builtin/init/mod.rs @@ -55,8 +55,6 @@ impl ActorCode for Actor { method: MethodNum, params: &Serialized, ) -> Serialized { - // Create mutable copy of params for usage in functions - let params: &mut Serialized = &mut params.clone(); match Method::from_method_num(method) { Some(Method::Constructor) => { Self::constructor(rt, params.deserialize().unwrap()); From 5475f7d80486b7f4830fcaa6f017170f536c4f17 Mon Sep 17 00:00:00 2001 From: austinabell Date: Sat, 14 Mar 2020 18:06:18 -0400 Subject: [PATCH 08/11] Switch runtime to use iterator to remove clones required --- vm/actor/src/builtin/account/mod.rs | 2 +- vm/runtime/src/lib.rs | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/vm/actor/src/builtin/account/mod.rs b/vm/actor/src/builtin/account/mod.rs index 421d9d59ad6e..84de6d4d13f2 100644 --- a/vm/actor/src/builtin/account/mod.rs +++ b/vm/actor/src/builtin/account/mod.rs @@ -30,7 +30,7 @@ pub struct Actor; impl Actor { /// Constructor for Account actor pub fn constructor(rt: &RT, address: Address) { - rt.validate_immediate_caller_is(&[address.clone()]); + rt.validate_immediate_caller_is(std::iter::once(&address)); match address.protocol() { Protocol::Secp256k1 | Protocol::BLS => (), protocol => rt.abort( diff --git a/vm/runtime/src/lib.rs b/vm/runtime/src/lib.rs index 2731164ce8e2..21fe2807c4a0 100644 --- a/vm/runtime/src/lib.rs +++ b/vm/runtime/src/lib.rs @@ -28,8 +28,12 @@ pub trait Runtime { /// Validates the caller against some predicate. /// Exported actor methods must invoke at least one caller validation before returning. fn validate_immediate_caller_accept_any(&self); - fn validate_immediate_caller_is(&self, addresses: &[Address]); - fn validate_immediate_caller_type(&self, types: &[Cid]); + fn validate_immediate_caller_is<'a, I>(&self, addresses: I) + where + I: Iterator; + fn validate_immediate_caller_type<'a, I>(&self, types: I) + where + I: Iterator; /// The balance of the receiver. fn current_balance(&self) -> TokenAmount; From 8a1dc0667569d094e12e1c3857e1a0ca002b929f Mon Sep 17 00:00:00 2001 From: austinabell Date: Sat, 14 Mar 2020 18:37:11 -0400 Subject: [PATCH 09/11] Add impl on serialized bytes for consistent use --- vm/src/method.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/vm/src/method.rs b/vm/src/method.rs index 17f513229a60..e3c4785a19ba 100644 --- a/vm/src/method.rs +++ b/vm/src/method.rs @@ -1,7 +1,7 @@ // Copyright 2020 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -use encoding::{de, from_slice, ser, serde_bytes, to_vec, Error as EncodingError}; +use encoding::{de, from_slice, ser, serde_bytes, to_vec, Cbor, Error as EncodingError}; use serde::{Deserialize, Serialize}; use std::ops::Deref; @@ -53,6 +53,8 @@ impl<'de> de::Deserialize<'de> for Serialized { } } +impl Cbor for Serialized {} + impl Deref for Serialized { type Target = Vec; fn deref(&self) -> &Self::Target { From c5cd483645260def7813c6a57b2d99a73ca2c054 Mon Sep 17 00:00:00 2001 From: austinabell Date: Sat, 14 Mar 2020 19:08:09 -0400 Subject: [PATCH 10/11] Update runtime blockstore generic --- vm/actor/src/builtin/account/mod.rs | 24 +++++++++++++++-------- vm/actor/src/builtin/cron/mod.rs | 24 +++++++++++++++-------- vm/actor/src/builtin/init/mod.rs | 26 +++++++++++++++---------- vm/actor/src/builtin/power/mod.rs | 18 ++++++++++------- vm/actor/src/builtin/reward/mod.rs | 30 ++++++++++++++++++++--------- vm/runtime/src/actor_code.rs | 11 +++++------ vm/runtime/src/lib.rs | 4 ++-- 7 files changed, 87 insertions(+), 50 deletions(-) diff --git a/vm/actor/src/builtin/account/mod.rs b/vm/actor/src/builtin/account/mod.rs index 84de6d4d13f2..0bc81b99dfba 100644 --- a/vm/actor/src/builtin/account/mod.rs +++ b/vm/actor/src/builtin/account/mod.rs @@ -6,6 +6,7 @@ mod state; pub use self::state::State; use crate::{assert_empty_params, empty_return}; use address::{Address, Protocol}; +use ipld_blockstore::BlockStore; use num_derive::FromPrimitive; use num_traits::FromPrimitive; use runtime::{ActorCode, Runtime}; @@ -29,7 +30,11 @@ impl Method { pub struct Actor; impl Actor { /// Constructor for Account actor - pub fn constructor(rt: &RT, address: Address) { + pub fn constructor(rt: &RT, address: Address) + where + BS: BlockStore, + RT: Runtime, + { rt.validate_immediate_caller_is(std::iter::once(&address)); match address.protocol() { Protocol::Secp256k1 | Protocol::BLS => (), @@ -42,7 +47,11 @@ impl Actor { } // Fetches the pubkey-type address from this actor. - pub fn pubkey_address(rt: &RT) -> Address { + pub fn pubkey_address(rt: &RT) -> Address + where + BS: BlockStore, + RT: Runtime, + { rt.validate_immediate_caller_accept_any(); let st: State = rt.state(); st.address @@ -50,12 +59,11 @@ impl Actor { } impl ActorCode for Actor { - fn invoke_method( - &self, - rt: &RT, - method: MethodNum, - params: &Serialized, - ) -> Serialized { + fn invoke_method(&self, rt: &RT, method: MethodNum, params: &Serialized) -> Serialized + where + BS: BlockStore, + RT: Runtime, + { match Method::from_method_num(method) { Some(Method::Constructor) => { Self::constructor(rt, params.deserialize().unwrap()); diff --git a/vm/actor/src/builtin/cron/mod.rs b/vm/actor/src/builtin/cron/mod.rs index 736ef3c67631..4b4aa4e10c6e 100644 --- a/vm/actor/src/builtin/cron/mod.rs +++ b/vm/actor/src/builtin/cron/mod.rs @@ -5,6 +5,7 @@ mod state; pub use self::state::{Entry, State}; use crate::{assert_empty_params, empty_return}; +use ipld_blockstore::BlockStore; use num_derive::FromPrimitive; use num_traits::FromPrimitive; use runtime::{ActorCode, Runtime}; @@ -56,14 +57,22 @@ impl<'de> Deserialize<'de> for ConstructorParams { pub struct Actor; impl Actor { /// Constructor for Cron actor - fn constructor(_rt: &RT, _params: ConstructorParams) { + fn constructor(_rt: &RT, _params: ConstructorParams) + where + BS: BlockStore, + RT: Runtime, + { // TODO now finished spec todo!() } /// epoch_tick executes built-in periodic actions, run at every Epoch. /// epoch_tick(r) is called after all other messages in the epoch have been applied. /// This can be seen as an implicit last message. - fn epoch_tick(_rt: &RT) { + fn epoch_tick(_rt: &RT) + where + BS: BlockStore, + RT: Runtime, + { // self.entries is basically a static registry for now, loaded // in the interpreter static registry. // TODO update to new spec @@ -83,12 +92,11 @@ impl Actor { } impl ActorCode for Actor { - fn invoke_method( - &self, - rt: &RT, - method: MethodNum, - params: &Serialized, - ) -> Serialized { + fn invoke_method(&self, rt: &RT, method: MethodNum, params: &Serialized) -> Serialized + where + BS: BlockStore, + RT: Runtime, + { match Method::from_method_num(method) { Some(Method::Constructor) => { Self::constructor(rt, params.deserialize().unwrap()); diff --git a/vm/actor/src/builtin/init/mod.rs b/vm/actor/src/builtin/init/mod.rs index ddba2f1d1dbb..d9c80cb3950c 100644 --- a/vm/actor/src/builtin/init/mod.rs +++ b/vm/actor/src/builtin/init/mod.rs @@ -5,6 +5,7 @@ mod state; pub use self::state::State; use crate::empty_return; +use ipld_blockstore::BlockStore; use num_derive::FromPrimitive; use num_traits::FromPrimitive; use runtime::{ActorCode, Runtime}; @@ -34,27 +35,32 @@ pub struct ConstructorParams { pub struct Actor; impl Actor { /// Init actor constructor - pub fn constructor(_rt: &RT, _params: ConstructorParams) { + pub fn constructor(_rt: &RT, _params: ConstructorParams) + where + BS: BlockStore, + RT: Runtime, + { // TODO todo!() - // Acquire state - // Update actor substate } /// Exec init actor - pub fn exec(_rt: &RT, _params: &Serialized) -> Serialized { + pub fn exec(_rt: &RT, _params: &Serialized) -> Serialized + where + BS: BlockStore, + RT: Runtime, + { // TODO update and include exec params type and return todo!() } } impl ActorCode for Actor { - fn invoke_method( - &self, - rt: &RT, - method: MethodNum, - params: &Serialized, - ) -> Serialized { + fn invoke_method(&self, rt: &RT, method: MethodNum, params: &Serialized) -> Serialized + where + BS: BlockStore, + RT: Runtime, + { match Method::from_method_num(method) { Some(Method::Constructor) => { Self::constructor(rt, params.deserialize().unwrap()); diff --git a/vm/actor/src/builtin/power/mod.rs b/vm/actor/src/builtin/power/mod.rs index 40b0b26ac886..0bbb1a029b54 100644 --- a/vm/actor/src/builtin/power/mod.rs +++ b/vm/actor/src/builtin/power/mod.rs @@ -5,6 +5,7 @@ mod state; pub use self::state::State; use crate::{assert_empty_params, empty_return}; +use ipld_blockstore::BlockStore; use num_derive::FromPrimitive; use num_traits::FromPrimitive; use runtime::{ActorCode, Runtime}; @@ -42,7 +43,11 @@ impl Method { pub struct Actor; impl Actor { /// Constructor for StoragePower actor - fn constructor(_rt: &RT) { + fn constructor(_rt: &RT) + where + BS: BlockStore, + RT: Runtime, + { // TODO todo!(); } @@ -50,12 +55,11 @@ impl Actor { } impl ActorCode for Actor { - fn invoke_method( - &self, - rt: &RT, - method: MethodNum, - params: &Serialized, - ) -> Serialized { + fn invoke_method(&self, rt: &RT, method: MethodNum, params: &Serialized) -> Serialized + where + BS: BlockStore, + RT: Runtime, + { match Method::from_method_num(method) { Some(Method::Constructor) => { assert_empty_params(params); diff --git a/vm/actor/src/builtin/reward/mod.rs b/vm/actor/src/builtin/reward/mod.rs index 4d3208d40609..3edda7a48d41 100644 --- a/vm/actor/src/builtin/reward/mod.rs +++ b/vm/actor/src/builtin/reward/mod.rs @@ -6,6 +6,7 @@ mod state; pub use self::state::{Reward, State}; use crate::{assert_empty_params, empty_return}; use address::Address; +use ipld_blockstore::BlockStore; use num_derive::FromPrimitive; use num_traits::FromPrimitive; use runtime::{ActorCode, Runtime}; @@ -30,29 +31,40 @@ impl Method { pub struct Actor; impl Actor { /// Constructor for Reward actor - fn constructor(_rt: &RT) { + fn constructor(_rt: &RT) + where + BS: BlockStore, + RT: Runtime, + { // TODO todo!(); } /// Mints a reward and puts into state reward map - fn award_block_reward(_rt: &RT) { + fn award_block_reward(_rt: &RT) + where + BS: BlockStore, + RT: Runtime, + { // TODO add params type and implement todo!(); } /// Withdraw available funds from reward map - fn withdraw_reward(_rt: &RT, _miner_in: &Address) { + fn withdraw_reward(_rt: &RT, _miner_in: &Address) + where + BS: BlockStore, + RT: Runtime, + { // TODO todo!(); } } impl ActorCode for Actor { - fn invoke_method( - &self, - rt: &RT, - method: MethodNum, - params: &Serialized, - ) -> Serialized { + fn invoke_method(&self, rt: &RT, method: MethodNum, params: &Serialized) -> Serialized + where + BS: BlockStore, + RT: Runtime, + { match Method::from_method_num(method) { Some(Method::Constructor) => { assert_empty_params(params); diff --git a/vm/runtime/src/actor_code.rs b/vm/runtime/src/actor_code.rs index 1d459ee852c2..723b94db92e7 100644 --- a/vm/runtime/src/actor_code.rs +++ b/vm/runtime/src/actor_code.rs @@ -2,16 +2,15 @@ // SPDX-License-Identifier: Apache-2.0, MIT use crate::Runtime; +use ipld_blockstore::BlockStore; use vm::{MethodNum, Serialized}; /// Interface for invoking methods on an Actor pub trait ActorCode { /// Invokes method with runtime on the actor's code. Method number will match one /// defined by the Actor, and parameters will be serialized and used in execution - fn invoke_method( - &self, - rt: &RT, - method: MethodNum, - params: &Serialized, - ) -> Serialized; + fn invoke_method(&self, rt: &RT, method: MethodNum, params: &Serialized) -> Serialized + where + BS: BlockStore, + RT: Runtime; } diff --git a/vm/runtime/src/lib.rs b/vm/runtime/src/lib.rs index 21fe2807c4a0..93cf3db9276d 100644 --- a/vm/runtime/src/lib.rs +++ b/vm/runtime/src/lib.rs @@ -18,7 +18,7 @@ pub struct Randomness; // TODO /// Runtime is the VM's internal runtime object. /// this is everything that is accessible to actors, beyond parameters. -pub trait Runtime { +pub trait Runtime { /// Information related to the current message being executed. fn message(&self) -> I; @@ -79,7 +79,7 @@ pub trait Runtime { F: Fn() -> R; /// Returns reference to blockstore - fn store(&self) -> &S; + fn store(&self) -> &BS; /// Sends a message to another actor, returning the exit code and return value envelope. /// If the invoked method does not return successfully, its state changes (and that of any messages it sent in turn) From 2f1e0b17d9d04dd40222382784dc3aad47687898 Mon Sep 17 00:00:00 2001 From: austinabell Date: Sun, 15 Mar 2020 19:40:24 -0400 Subject: [PATCH 11/11] Add missing empty param check --- vm/actor/src/builtin/reward/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/vm/actor/src/builtin/reward/mod.rs b/vm/actor/src/builtin/reward/mod.rs index 3edda7a48d41..bded579a5ba0 100644 --- a/vm/actor/src/builtin/reward/mod.rs +++ b/vm/actor/src/builtin/reward/mod.rs @@ -72,6 +72,7 @@ impl ActorCode for Actor { empty_return() } Some(Method::AwardBlockReward) => { + assert_empty_params(params); Self::award_block_reward(rt); empty_return() }