Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow registering of Actors to the VM #654

Merged
merged 15 commits into from
Aug 27, 2020
Merged
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.

1 change: 1 addition & 0 deletions blockchain/blocks/src/tipset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ impl FullTipset {

// sort blocks on creation to allow for more seamless conversions between FullTipset
// and Tipset
#[allow(clippy::unnecessary_sort_by)]
blocks.sort_by(|block1, block2| block1.header().cmp(block2.header()));
Ok(Self { blocks })
}
Expand Down
1 change: 1 addition & 0 deletions tests/conformance_tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ crypto = { package = "forest_crypto", path = "../../crypto" }
address = { package = "forest_address", path = "../../vm/address" }
regex = "1.0"
lazy_static = "1.4"
actor = { path = "../../vm/actor" }
2 changes: 1 addition & 1 deletion tests/conformance_tests/test-vectors
Submodule test-vectors updated 77 files
+257 −0 .github/labels.yml
+16 −0 .github/workflows/label-syncer.yml
+4 −4 README.md
+1 −1 chaos/actor.go
+4 −4 corpus/actor_creation/addresses--sequential-10.json
+4 −4 corpus/actor_creation/on_transfer--fail-bls-insufficient-balance.json
+4 −4 corpus/actor_creation/on_transfer--fail-secp256k1-insufficient-balance.json
+4 −4 corpus/actor_creation/on_transfer--ok-create-bls.json
+4 −4 corpus/actor_creation/on_transfer--ok-create-secp256k1.json
+4 −4 corpus/actor_creation/x--params--fails-unparsable-constructor-params-via-init-actor.json
+4 −4 corpus/actor_creation/x--params--fails-unparsable-init-actor-exec-msg.json
+4 −4 corpus/msg_application/actor_exec--msg-apply-fail-actor-execution-illegal-arg.json
+4 −4 corpus/msg_application/gas_cost--msg-apply-fail-onchainsize-gas.json
+4 −4 corpus/msg_application/gas_cost--msg-apply-fail-receipt-gas.json
+4 −4 corpus/msg_application/gas_cost--msg-apply-fail-transfer-accountcreation-gas.json
+4 −4 corpus/msg_application/invalid_msgs--msg-apply-fail-invalid-nonce.json
+4 −4 corpus/msg_application/invalid_msgs--msg-apply-fail-invalid-receiver-method.json
+4 −4 corpus/msg_application/unknown_actors--msg-apply-fail-unknown-receiver.json
+4 −4 corpus/msg_application/unknown_actors--msg-apply-fail-unknown-sender.json
+4 −4 corpus/multisig/basic--ok-add-signer.json
+4 −4 corpus/multisig/basic--ok-create.json
+4 −4 corpus/multisig/basic--ok-propose-and-approve.json
+4 −4 corpus/multisig/basic--ok-propose-and-cancel.json
+4 −4 corpus/nested/nested_sends--fail-aborted-exec.json
+4 −4 corpus/nested/nested_sends--fail-inner-abort.json
+7 −5 corpus/nested/nested_sends--fail-insufficient-funds-for-transfer-in-inner-send.json
+4 −4 corpus/nested/nested_sends--fail-invalid-method-num-for-actor.json
+4 −4 corpus/nested/nested_sends--fail-invalid-method-num-new-actor.json
+4 −4 corpus/nested/nested_sends--fail-mismatch-params.json
+4 −4 corpus/nested/nested_sends--fail-missing-params.json
+4 −4 corpus/nested/nested_sends--fail-non-existent-actor-address.json
+4 −4 corpus/nested/nested_sends--fail-non-existent-id-address.json
+4 −4 corpus/nested/nested_sends--ok-basic.json
+4 −4 corpus/nested/nested_sends--ok-non-cbor-params-with-transfer.json
+4 −4 corpus/nested/nested_sends--ok-recursive.json
+4 −4 corpus/nested/nested_sends--ok-to-new-actor-with-invoke.json
+4 −4 corpus/nested/nested_sends--ok-to-new-actor.json
+4 −4 corpus/paych/paych--collect-ok.json
+4 −4 corpus/paych/paych--create-ok.json
+4 −4 corpus/paych/paych--update-ok.json
+4 −4 corpus/transfer/basic--fail-balance-equal-gas.json
+4 −4 corpus/transfer/basic--fail-balance-under-gaslimit.json
+4 −4 corpus/transfer/basic--fail-exceed-balance.json
+4 −4 corpus/transfer/basic--fail-negative-amount.json
+4 −4 corpus/transfer/basic--ok-zero.json
+4 −4 corpus/transfer/basic--ok.json
+4 −4 corpus/transfer/self_transfer--id-to-id-addresses.json
+4 −4 corpus/transfer/self_transfer--id-to-secp-addresses.json
+4 −4 corpus/transfer/self_transfer--secp-to-id-addresses.json
+4 −4 corpus/transfer/self_transfer--secp-to-secp-addresses.json
+55 −0 corpus/transfer/system_receiver--to-burnt-funds-actor.json
+55 −0 corpus/transfer/system_receiver--to-cron-actor.json
+55 −0 corpus/transfer/system_receiver--to-init-actor.json
+55 −0 corpus/transfer/system_receiver--to-reward-actor.json
+55 −0 corpus/transfer/system_receiver--to-storage-market-actor.json
+55 −0 corpus/transfer/system_receiver--to-storage-power-actor.json
+55 −0 corpus/transfer/system_receiver--to-system-actor.json
+55 −0 corpus/transfer/system_receiver--to-verified-registry-actor.json
+4 −4 corpus/transfer/unknown_accounts--fail-unknown-sender-known-receiver.json
+4 −4 corpus/transfer/unknown_accounts--fail-unknown-sender-unknown-receiver.json
+7 −5 corpus/vm_violations/actor_creation--control-ok-with-good-address-good-cid.json
+7 −5 corpus/vm_violations/actor_creation--fails-with-existing-address.json
+7 −5 corpus/vm_violations/actor_creation--fails-with-good-addr-undef-cid.json
+7 −5 corpus/vm_violations/actor_creation--fails-with-undef-actor-cid-undef-addr.json
+7 −5 corpus/vm_violations/actor_creation--fails-with-unknown-actor-cid-undef-addr.json
+7 −5 corpus/vm_violations/actor_creation--fails-with-unknown-actor-cid.json
+7 −5 corpus/vm_violations/caller_validation--nil-allowed-address-set.json
+7 −5 corpus/vm_violations/caller_validation--nil-allowed-type-set.json
+7 −5 corpus/vm_violations/caller_validation--none.json
+7 −5 corpus/vm_violations/caller_validation--twice.json
+15 −2 gen/builders/state_zero.go
+1 −1 gen/suites/nested/main.go
+42 −2 gen/suites/transfer/main.go
+58 −0 gen/suites/transfer/system_receiver.go
+11 −11 gen/suites/vm_violations/main.go
+12 −5 schema.json
+1 −21 schema/schema.go
39 changes: 33 additions & 6 deletions tests/conformance_tests/tests/conformance_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#[macro_use]
extern crate lazy_static;

use actor::{CHAOS_ACTOR_CODE_ID, PUPPET_ACTOR_CODE_ID};
use address::Address;
use blockstore::BlockStore;
use cid::Cid;
Expand Down Expand Up @@ -125,12 +126,20 @@ struct MessageVector {
epoch: Option<ChainEpoch>,
}

#[derive(Debug, Deserialize)]
struct Selector {
#[serde(default)]
puppet_actor: Option<String>,
#[serde(default)]
chaos_actor: Option<String>,
}

#[derive(Debug, Deserialize)]
#[serde(tag = "class")]
enum TestVector {
#[serde(rename = "message")]
Message {
selector: Option<String>,
selector: Option<Selector>,
#[serde(rename = "_meta")]
meta: Option<MetaData>,

Expand All @@ -142,19 +151,19 @@ enum TestVector {
},
#[serde(rename = "block")]
Block {
selector: Option<String>,
selector: Option<Selector>,
#[serde(rename = "_meta")]
meta: Option<MetaData>,
},
#[serde(rename = "tipset")]
Tipset {
selector: Option<String>,
selector: Option<Selector>,
#[serde(rename = "_meta")]
meta: Option<MetaData>,
},
#[serde(rename = "chain")]
Chain {
selector: Option<String>,
selector: Option<Selector>,
#[serde(rename = "_meta")]
meta: Option<MetaData>,
},
Expand Down Expand Up @@ -228,6 +237,7 @@ fn execute_message(
pre_root: &Cid,
bs: &db::MemoryDB,
epoch: ChainEpoch,
selector: &Option<Selector>,
) -> Result<(ApplyRet, Cid), Box<dyn StdError>> {
let mut vm = VM::<_, _, _>::new(
pre_root,
Expand All @@ -238,6 +248,23 @@ fn execute_message(
BASE_FEE.clone(),
)?;

if let Some(s) = &selector {
if s.puppet_actor
.as_ref()
.map(|s| s == "true")
.unwrap_or_default()
{
vm.register_actor(PUPPET_ACTOR_CODE_ID.clone());
}
if s.chaos_actor
.as_ref()
.map(|s| s == "true")
.unwrap_or_default()
{
vm.register_actor(CHAOS_ACTOR_CODE_ID.clone());
}
}

// TODO register puppet actor (and conditionally chaos actor)

let ret = vm.apply_message(msg)?;
Expand All @@ -247,7 +274,7 @@ fn execute_message(
}

fn execute_message_vector(
_selector: Option<String>,
selector: Option<Selector>,
car: Vec<u8>,
preconditions: PreConditions,
apply_messages: Vec<MessageVector>,
Expand All @@ -274,7 +301,7 @@ fn execute_message_vector(
epoch = ep;
}

let (ret, post_root) = execute_message(&msg, &root, &bs, epoch)?;
let (ret, post_root) = execute_message(&msg, &root, &bs, epoch, &selector)?;
root = post_root;

let receipt = &postconditions.receipts[i];
Expand Down
38 changes: 29 additions & 9 deletions vm/interpreter/src/default_runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use num_bigint::BigInt;
use runtime::{ActorCode, MessageInfo, Runtime, Syscalls};
use state_tree::StateTree;
use std::cell::RefCell;
use std::collections::HashSet;
use std::marker::PhantomData;
use std::rc::Rc;
use vm::{
Expand Down Expand Up @@ -54,7 +55,7 @@ impl MessageInfo for VMMsg {
}

/// Implementation of the Runtime trait.
pub struct DefaultRuntime<'db, 'msg, 'st, 'sys, 'r, BS, SYS, R, P = DevnetParams> {
pub struct DefaultRuntime<'db, 'msg, 'st, 'sys, 'r, 'act, BS, SYS, R, P = DevnetParams> {
state: &'st mut StateTree<'db, BS>,
store: GasBlockStore<'db, BS>,
syscalls: GasSyscalls<'sys, SYS>,
Expand All @@ -69,11 +70,12 @@ pub struct DefaultRuntime<'db, 'msg, 'st, 'sys, 'r, BS, SYS, R, P = DevnetParams
rand: &'r R,
caller_validated: bool,
allow_internal: bool,
registered_actors: &'act HashSet<Cid>,
params: PhantomData<P>,
}

impl<'db, 'msg, 'st, 'sys, 'r, BS, SYS, R, P>
DefaultRuntime<'db, 'msg, 'st, 'sys, 'r, BS, SYS, R, P>
impl<'db, 'msg, 'st, 'sys, 'r, 'act, BS, SYS, R, P>
DefaultRuntime<'db, 'msg, 'st, 'sys, 'r, 'act, BS, SYS, R, P>
where
BS: BlockStore,
SYS: Syscalls,
Expand All @@ -93,6 +95,7 @@ where
origin_nonce: u64,
num_actors_created: u64,
rand: &'r R,
registered_actors: &'act HashSet<Cid>,
) -> Result<Self, ActorError> {
let price_list = price_list_by_epoch(epoch);
let gas_tracker = Rc::new(RefCell::new(GasTracker::new(message.gas_limit(), gas_used)));
Expand Down Expand Up @@ -133,6 +136,7 @@ where
num_actors_created,
price_list,
rand,
registered_actors,
allow_internal: true,
caller_validated: false,
params: PhantomData,
Expand Down Expand Up @@ -307,7 +311,7 @@ where
}
}

impl<BS, SYS, R, P> Runtime<BS> for DefaultRuntime<'_, '_, '_, '_, '_, BS, SYS, R, P>
impl<BS, SYS, R, P> Runtime<BS> for DefaultRuntime<'_, '_, '_, '_, '_, '_, BS, SYS, R, P>
where
BS: BlockStore,
SYS: Syscalls,
Expand Down Expand Up @@ -602,8 +606,8 @@ where

/// Shared logic between the DefaultRuntime and the Interpreter.
/// It invokes methods on different Actors based on the Message.
pub fn vm_send<'db, 'msg, 'st, 'sys, 'r, BS, SYS, R, P>(
rt: &mut DefaultRuntime<'db, 'msg, 'st, 'sys, 'r, BS, SYS, R, P>,
pub fn vm_send<'db, 'msg, 'st, 'sys, 'r, 'act, BS, SYS, R, P>(
rt: &mut DefaultRuntime<'db, 'msg, 'st, 'sys, 'r, 'act, BS, SYS, R, P>,
msg: &UnsignedMessage,
gas_cost: Option<GasCharge>,
) -> Result<Serialized, ActorError>
Expand Down Expand Up @@ -708,8 +712,8 @@ fn transfer<BS: BlockStore>(
}

/// Calls actor code with method and parameters.
fn invoke<'db, 'msg, 'st, 'sys, 'r, BS, SYS, R, P>(
rt: &mut DefaultRuntime<'db, 'msg, 'st, 'sys, 'r, BS, SYS, R, P>,
fn invoke<'db, 'msg, 'st, 'sys, 'r, 'act, BS, SYS, R, P>(
rt: &mut DefaultRuntime<'db, 'msg, 'st, 'sys, 'r, 'act, BS, SYS, R, P>,
code: Cid,
method_num: MethodNum,
params: &Serialized,
Expand All @@ -733,7 +737,23 @@ where
x if x == *MULTISIG_ACTOR_CODE_ID => multisig::Actor.invoke_method(rt, method_num, params),
x if x == *REWARD_ACTOR_CODE_ID => reward::Actor.invoke_method(rt, method_num, params),
x if x == *VERIFREG_ACTOR_CODE_ID => verifreg::Actor.invoke_method(rt, method_num, params),
_ => Err(actor_error!(SysErrorIllegalActor; "no code for actor at address {}", to)),
x => {
if rt.registered_actors.contains(&x) {
match x {
x if x == *PUPPET_ACTOR_CODE_ID => {
ec2 marked this conversation as resolved.
Show resolved Hide resolved
puppet::Actor.invoke_method(rt, method_num, params)
}
x if x == *CHAOS_ACTOR_CODE_ID => {
chaos::Actor.invoke_method(rt, method_num, params)
}
_ => Err(
actor_error!(SysErrorIllegalActor; "no code for registered actor at address {}", to),
),
}
} else {
Err(actor_error!(SysErrorIllegalActor; "no code for actor at address {}", to))
ec2 marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
}

Expand Down
16 changes: 15 additions & 1 deletion vm/interpreter/src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ pub struct VM<'db, 'r, DB, SYS, R, P = DevnetParams> {
syscalls: SYS,
rand: &'r R,
base_fee: BigInt,
registered_actors: HashSet<Cid>,
params: PhantomData<P>,
}

Expand All @@ -59,17 +60,29 @@ where
base_fee: BigInt,
) -> Result<Self, String> {
let state = StateTree::new_from_root(store, root)?;
let registered_actors = HashSet::new();
Ok(VM {
state,
store,
epoch,
syscalls,
rand,
base_fee,
registered_actors,
params: PhantomData,
})
}

/// Registers an actor that is not part of the set of default builtin actors by providing the code cid
pub fn register_actor(&mut self, code_cid: Cid) -> bool {
self.registered_actors.insert(code_cid)
}

/// Gets registered actors that are not part of the set of default builtin actors
pub fn registered_actors(&self) -> &HashSet<Cid> {
&self.registered_actors
}

/// Flush stores in VM and return state root.
pub fn flush(&mut self) -> Result<Cid, String> {
self.state.flush()
Expand Down Expand Up @@ -422,7 +435,7 @@ where
gas_cost: Option<GasCharge>,
) -> (
Serialized,
Option<DefaultRuntime<'db, 'm, '_, '_, '_, DB, SYS, R, P>>,
Option<DefaultRuntime<'db, 'm, '_, '_, '_, '_, DB, SYS, R, P>>,
Option<ActorError>,
) {
let res = DefaultRuntime::new(
Expand All @@ -436,6 +449,7 @@ where
msg.sequence(),
0,
self.rand,
&self.registered_actors,
);

match res {
Expand Down
3 changes: 3 additions & 0 deletions vm/interpreter/tests/transfer_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use ipld_blockstore::BlockStore;
use ipld_hamt::Hamt;
use message::UnsignedMessage;
use state_tree::StateTree;
use std::collections::HashSet;
use vm::{ActorState, Serialized};

#[test]
Expand Down Expand Up @@ -93,6 +94,7 @@ fn transfer_test() {
let default_syscalls = DefaultSyscalls::new(&store);

let dummy_rand = ChainRand::new(TipsetKeys::new(vec![]));
let registered = HashSet::new();
let mut runtime = DefaultRuntime::<_, _, _>::new(
&mut state,
&store,
Expand All @@ -104,6 +106,7 @@ fn transfer_test() {
0,
0,
&dummy_rand,
&registered,
)
.unwrap();
let _serialized = vm_send(&mut runtime, &message, None).unwrap();
Expand Down