Skip to content

Commit

Permalink
VM and Runtime updates (#569)
Browse files Browse the repository at this point in the history
* Setup network config params

* Implement total circ supply for default runtime

* Add actor error convenience macro

* Switch actor error usage to macro in default runtime

* updates to runtime functions

* Switch message gas limit to i64

* Remove unnecessary conversions

* Switch to using MessageInfo trait for Runtime and refactor MockRuntime setup

* Update runtime validations and refactor mock runtime usage

* Update error handling in mock runtime

* Update runtime function signatures

* Update empty array CID and bytes references and refactor more methods

* Update state handles

* Add allow internal flag in runtime

* Refactor internal send functions

* misc cleanup

* update actor initialization

* Update gas interfaces

* Update runtime generation

* Update apply ret struct

* Small tweaks around message applying

* Update apply_message

* fix conflicts from merge
  • Loading branch information
austinabell authored Jul 29, 2020
1 parent fc523a3 commit 2863f64
Show file tree
Hide file tree
Showing 45 changed files with 1,081 additions and 844 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 12 additions & 8 deletions blockchain/state_manager/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use cid::Cid;
use clock::ChainEpoch;
use encoding::de::DeserializeOwned;
use encoding::Cbor;
use fil_types::DevnetParams;
use flo_stream::Subscriber;
use forest_blocks::{Block, BlockHeader, FullTipset, Tipset, TipsetKeys};
use futures::channel::oneshot;
Expand Down Expand Up @@ -163,7 +164,8 @@ where
) -> Result<(Cid, Cid), Box<dyn StdError>> {
let mut buf_store = BufferedBlockStore::new(self.bs.as_ref());
// TODO possibly switch out syscalls to be saved at state manager level
let mut vm = VM::new(
// TODO change from statically using devnet params when needed
let mut vm = VM::<_, _, DevnetParams>::new(
ts.parent_state(),
&buf_store,
ts.epoch(),
Expand All @@ -172,7 +174,7 @@ where
)?;

// Apply tipset messages
let receipts = vm.apply_tip_set_messages(ts, callback)?;
let receipts = vm.apply_tipset_messages(ts, callback)?;

// Construct receipt root from receipts
let rect_root = Amt::new_from_slice(self.bs.as_ref(), &receipts)?;
Expand Down Expand Up @@ -238,7 +240,7 @@ where
span!("state_call_raw", {
let block_store = self.get_block_store_ref();
let buf_store = BufferedBlockStore::new(block_store);
let mut vm = VM::new(
let mut vm = VM::<_, _, DevnetParams>::new(
bstate,
&buf_store,
*bheight,
Expand All @@ -261,14 +263,14 @@ where
msg.gas_price(),
msg.value()
);
if let Some(err) = apply_ret.act_error() {
if let Some(err) = &apply_ret.act_error {
warn!("chain call failed: {:?}", err);
}

Ok(InvocResult {
msg: msg.clone(),
msg_rct: Some(apply_ret.msg_receipt().clone()),
actor_error: apply_ret.act_error().map(|e| e.to_string()),
msg_rct: Some(apply_ret.msg_receipt.clone()),
actor_error: apply_ret.act_error.map(|e| e.to_string()),
})
})
}
Expand Down Expand Up @@ -672,7 +674,7 @@ where
Ok(actor.balance)
}

pub fn lookup_id(&self, addr: &Address, ts: &Tipset) -> Result<Address, Error> {
pub fn lookup_id(&self, addr: &Address, ts: &Tipset) -> Result<Option<Address>, Error> {
let state_tree = StateTree::new_from_root(self.bs.as_ref(), ts.parent_state())?;
state_tree.lookup_id(addr).map_err(Error::State)
}
Expand All @@ -681,7 +683,9 @@ where
let market_state: market::State =
self.load_actor_state(&*STORAGE_MARKET_ACTOR_ADDR, ts.parent_state())?;

let new_addr = self.lookup_id(addr, ts)?;
let new_addr = self
.lookup_id(addr, ts)?
.ok_or_else(|| Error::State(format!("Failed to resolve address {}", addr)))?;

let out = MarketBalance {
escrow: {
Expand Down
6 changes: 3 additions & 3 deletions node/state_api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,9 +256,9 @@ where

Ok(InvocResult {
msg,
msg_rct: ret.clone().map(|s| s.msg_receipt().clone()),
msg_rct: ret.as_ref().map(|s| s.msg_receipt.clone()),
actor_error: ret
.map(|act| act.act_error().map(|e| e.to_string()))
.map(|act| act.act_error.map(|e| e.to_string()))
.unwrap_or_default(),
})
}
Expand Down Expand Up @@ -323,7 +323,7 @@ pub fn state_lookup_id<DB>(
state_manager: &StateManager<DB>,
address: &Address,
key: &TipsetKeys,
) -> Result<Address, BoxError>
) -> Result<Option<Address>, BoxError>
where
DB: BlockStore,
{
Expand Down
31 changes: 31 additions & 0 deletions types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,34 @@ pub mod sector;

pub use self::piece::*;
pub use self::sector::*;

use num_bigint::BigInt;

/// Config trait which handles different network configurations.
pub trait NetworkParams {
/// Total filecoin available to network.
const TOTAL_FILECOIN: i64;

/// Available rewards for mining.
const MINING_REWARD_TOTAL: i64;

/// Initial reward actor balance. This function is only called in genesis setting up state.
fn initial_reward_balance() -> BigInt {
BigInt::from(Self::MINING_REWARD_TOTAL) * Self::TOTAL_FILECOIN
}

/// Convert integer value of tokens into BigInt based on the token precision.
fn from_fil(i: i64) -> BigInt {
BigInt::from(i) * FILECOIN_PRECISION
}
}

// Not yet finalized
pub struct DevnetParams;
impl NetworkParams for DevnetParams {
const TOTAL_FILECOIN: i64 = 2_000_000_000;
const MINING_REWARD_TOTAL: i64 = 1_400_000_000;
}

/// Ratio of integer values to token value.
pub const FILECOIN_PRECISION: i64 = 1_000_000_000_000_000_000;
1 change: 1 addition & 0 deletions vm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ cid = { package = "forest_cid", path = "../ipld/cid", version = "0.1", features
num-traits = "0.2"
num-derive = "0.3.0"
thiserror = "1.0.11"
lazy_static = "1.4"

[features]
json = []
4 changes: 2 additions & 2 deletions vm/actor/src/builtin/account/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,12 @@ impl Actor {
}

// Fetches the pubkey-type address from this actor.
pub fn pubkey_address<BS, RT>(rt: &RT) -> Result<Address, ActorError>
pub fn pubkey_address<BS, RT>(rt: &mut RT) -> Result<Address, ActorError>
where
BS: BlockStore,
RT: Runtime<BS>,
{
rt.validate_immediate_caller_accept_any();
rt.validate_immediate_caller_accept_any()?;
let st: State = rt.state()?;
Ok(st.address)
}
Expand Down
2 changes: 1 addition & 1 deletion vm/actor/src/builtin/codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ lazy_static! {
pub static ref PAYCH_ACTOR_CODE_ID: Cid = make_builtin(b"fil/1/paymentchannel");
pub static ref MULTISIG_ACTOR_CODE_ID: Cid = make_builtin(b"fil/1/multisig");
pub static ref REWARD_ACTOR_CODE_ID: Cid = make_builtin(b"fil/1/reward");
pub static ref VERIFIED_ACTOR_CODE_ID: Cid = make_builtin(b"fil/1/verifiedregistry");
pub static ref VERIFREG_ACTOR_CODE_ID: Cid = make_builtin(b"fil/1/verifiedregistry");

// Set of actor code types that can represent external signing parties.
pub static ref CALLER_TYPES_SIGNABLE: [Cid; 2] =
Expand Down
6 changes: 3 additions & 3 deletions vm/actor/src/builtin/cron/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@ impl Actor {
let st: State = rt.state()?;
for entry in st.entries {
let _v = rt.send(
&entry.receiver,
entry.receiver,
entry.method_num,
&Serialized::default(),
&TokenAmount::from(0u8),
Serialized::default(),
TokenAmount::from(0u8),
);
}
Ok(())
Expand Down
19 changes: 8 additions & 11 deletions vm/actor/src/builtin/init/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use ipld_blockstore::BlockStore;
use num_derive::FromPrimitive;
use num_traits::FromPrimitive;
use runtime::{ActorCode, Runtime};
use vm::{ActorError, ExitCode, MethodNum, Serialized, METHOD_CONSTRUCTOR};
use vm::{actor_error, ActorError, ExitCode, MethodNum, Serialized, METHOD_CONSTRUCTOR};

/// Init actor methods available
#[derive(FromPrimitive)]
Expand Down Expand Up @@ -56,17 +56,14 @@ impl Actor {
BS: BlockStore,
RT: Runtime<BS>,
{
rt.validate_immediate_caller_accept_any();
rt.validate_immediate_caller_accept_any()?;
let caller_code = rt
.get_actor_code_cid(rt.message().caller())
.expect("no code for actor");
.get_actor_code_cid(rt.message().caller())?
.ok_or_else(|| actor_error!(ErrForbidden; "No code for actor"))?;
if !can_exec(&caller_code, &params.code_cid) {
return Err(rt.abort(
ExitCode::ErrForbidden,
format!(
return Err(actor_error!(ErrForbidden;
"called type {} cannot exec actor type {}",
&caller_code, &params.code_cid
),
));
}

Expand All @@ -90,10 +87,10 @@ impl Actor {

// Invoke constructor
rt.send(
&id_address,
id_address,
METHOD_CONSTRUCTOR,
&params.constructor_params,
&rt.message().value_received().clone(),
params.constructor_params,
rt.message().value_received().clone(),
)
.map_err(|err| rt.abort(err.exit_code(), "constructor failed"))?;

Expand Down
12 changes: 5 additions & 7 deletions vm/actor/src/builtin/init/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,19 +55,17 @@ impl State {
&self,
store: &BS,
addr: &Address,
) -> Result<Address, String> {
) -> Result<Option<Address>, String> {
if addr.protocol() == Protocol::ID {
return Ok(*addr);
return Ok(Some(*addr));
}

let map: Hamt<BytesKey, _> =
Hamt::load_with_bit_width(&self.address_map, store, HAMT_BIT_WIDTH)?;

let actor_id: ActorID = map
.get(&addr.to_bytes())?
.ok_or_else(|| "Address not found".to_owned())?;

Ok(Address::new_id(actor_id))
Ok(map
.get::<_, ActorID>(&addr.to_bytes())?
.map(Address::new_id))
}
}

Expand Down
70 changes: 33 additions & 37 deletions vm/actor/src/builtin/market/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ use num_derive::FromPrimitive;
use num_traits::{FromPrimitive, Zero};
use runtime::{ActorCode, Runtime};
use vm::{
ActorError, ExitCode, MethodNum, Serialized, TokenAmount, METHOD_CONSTRUCTOR, METHOD_SEND,
actor_error, ActorError, ExitCode, MethodNum, Serialized, TokenAmount, METHOD_CONSTRUCTOR,
METHOD_SEND,
};

/// Market actor methods available
Expand Down Expand Up @@ -154,17 +155,17 @@ impl Actor {
// TODO this will never be hit
if amount_slashed_total > BigInt::zero() {
rt.send(
&*BURNT_FUNDS_ACTOR_ADDR,
*BURNT_FUNDS_ACTOR_ADDR,
METHOD_SEND,
&Serialized::default(),
&amount_slashed_total,
Serialized::default(),
amount_slashed_total,
)?;
}
rt.send(
&recipient,
recipient,
METHOD_SEND,
&Serialized::default(),
&amount_extracted,
Serialized::default(),
amount_extracted,
)?;
Ok(())
}
Expand All @@ -189,10 +190,12 @@ impl Actor {
}

// All deals should have the same provider so get worker once
let provider_raw = &params.deals[0].proposal.provider;
let provider = rt.resolve_address(&provider_raw)?;
let provider_raw = params.deals[0].proposal.provider;
let provider = rt.resolve_address(&provider_raw)?.ok_or_else(
|| actor_error!(ErrNotFound; "failed to resolve provider address {}", provider_raw),
)?;

let (_, worker) = request_miner_control_addrs(rt, &provider)?;
let (_, worker) = request_miner_control_addrs(rt, provider)?;
if &worker != rt.message().caller() {
return Err(ActorError::new(
ExitCode::ErrForbidden,
Expand All @@ -210,18 +213,14 @@ impl Actor {
deal_size: BigInt::from(deal.proposal.piece_size.0),
})?;
rt.send(
&*VERIFIED_REGISTRY_ACTOR_ADDR,
*VERIFIED_REGISTRY_ACTOR_ADDR,
VerifregMethod::UseBytes as u64,
&ser_params,
&TokenAmount::zero(),
ser_params,
TokenAmount::zero(),
)?;
}
}

// All deals should have the same provider so get worker once
let provider_raw = params.deals[0].proposal.provider;
let provider = rt.resolve_address(&provider_raw)?;

let mut new_deal_ids: Vec<DealID> = Vec::new();
rt.transaction(|st: &mut State, rt| {
let mut prop = Amt::load(&st.proposals, rt.store())
Expand All @@ -240,7 +239,10 @@ impl Actor {
));
}

let client = rt.resolve_address(&deal.proposal.client)?;
let client = rt.resolve_address(&deal.proposal.client)?.ok_or_else(|| {
actor_error!(ErrNotFound;
"failed to resolve provider address {}", provider_raw)
})?;
// Normalise provider and client addresses in the proposal stored on chain (after signature verification).
deal.proposal.provider = provider;
deal.proposal.client = client;
Expand Down Expand Up @@ -615,18 +617,18 @@ impl Actor {
deal_size: BigInt::from(d.piece_size.0),
})?;
rt.send(
&*VERIFIED_REGISTRY_ACTOR_ADDR,
*VERIFIED_REGISTRY_ACTOR_ADDR,
VerifregMethod::RestoreBytes as u64,
&ser_params,
&TokenAmount::zero(),
ser_params,
TokenAmount::zero(),
)?;
}

rt.send(
&*BURNT_FUNDS_ACTOR_ADDR,
*BURNT_FUNDS_ACTOR_ADDR,
METHOD_SEND,
&Serialized::default(),
&amount_slashed,
Serialized::default(),
amount_slashed,
)?;
Ok(())
}
Expand Down Expand Up @@ -768,19 +770,13 @@ where
RT: Runtime<BS>,
{
// Resolve the provided address to the canonical form against which the balance is held.
let nominal = rt.resolve_address(addr).map_err(|e| {
ActorError::new(
ExitCode::ErrIllegalArgument,
format!("Failed to resolve address provided: {}", e),
)
})?;
let nominal = rt
.resolve_address(addr)?
.ok_or_else(|| actor_error!(ErrIllegalArgument; "failed to resolve address {}", addr))?;

let code_id = rt.get_actor_code_cid(&nominal).map_err(|e| {
ActorError::new(
ExitCode::ErrIllegalArgument,
format!("Failed to retrieve actor code cid: {}", e),
)
})?;
let code_id = rt
.get_actor_code_cid(&nominal)?
.ok_or_else(|| actor_error!(ErrIllegalArgument; "no code for address {}", nominal))?;

if code_id != *MINER_ACTOR_CODE_ID {
// Ordinary account-style actor entry; funds recipient is just the entry address itself.
Expand All @@ -789,7 +785,7 @@ where
}

// Storage miner actor entry; implied funds recipient is the associated owner address.
let (owner_addr, worker_addr) = request_miner_control_addrs(rt, &nominal)?;
let (owner_addr, worker_addr) = request_miner_control_addrs(rt, nominal)?;
rt.validate_immediate_caller_is([owner_addr, worker_addr].iter())?;
Ok((nominal, owner_addr))
}
Expand Down
Loading

0 comments on commit 2863f64

Please sign in to comment.