diff --git a/vm/actor/tests/common/mod.rs b/vm/actor/tests/common/mod.rs index 72bc4bfaa9f1..c5bb37a250b1 100644 --- a/vm/actor/tests/common/mod.rs +++ b/vm/actor/tests/common/mod.rs @@ -111,6 +111,8 @@ impl<'a, BS: BlockStore> MockRuntime<'a, BS> { fn _get(&self, cid: Cid) -> Result { Ok(self.store.get(&cid).unwrap().unwrap()) } + + #[allow(dead_code)] pub fn get_state(&self) -> Result { let data: T = self .store @@ -128,6 +130,7 @@ impl<'a, BS: BlockStore> MockRuntime<'a, BS> { pub fn expect_validate_caller_any(&self) { self.expect_validate_caller_any.set(true); } + pub fn call( &mut self, to_code: &Cid, @@ -135,6 +138,8 @@ impl<'a, BS: BlockStore> MockRuntime<'a, BS> { params: &Serialized, ) -> Result { self.in_call = true; + let prev_state = self.state.clone(); + let res = match to_code { x if x == &*SYSTEM_ACTOR_CODE_ID => { actor::system::Actor.invoke_method(self, method_num, params) @@ -161,16 +166,20 @@ impl<'a, BS: BlockStore> MockRuntime<'a, BS> { actor::paych::Actor.invoke_method(self, method_num, params) } x if x == &*MULTISIG_ACTOR_CODE_ID => { - actor::cron::Actor.invoke_method(self, method_num, params) + actor::multisig::Actor.invoke_method(self, method_num, params) } x if x == &*REWARD_ACTOR_CODE_ID => { - actor::cron::Actor.invoke_method(self, method_num, params) + actor::reward::Actor.invoke_method(self, method_num, params) } _ => Err(ActorError::new( ExitCode::SysErrForbidden, "invalid method id".to_owned(), )), }; + + if res.is_err() { + self.state = prev_state; + } self.in_call = false; return res; } diff --git a/vm/actor/tests/init_actor_test.rs b/vm/actor/tests/init_actor_test.rs index 4240e985d94a..e2b6dc238dc1 100644 --- a/vm/actor/tests/init_actor_test.rs +++ b/vm/actor/tests/init_actor_test.rs @@ -4,7 +4,7 @@ mod common; use actor::{ - init::{ConstructorParams, ExecParams, ExecReturn, State}, + init::{ConstructorParams, ExecParams, ExecReturn, Method, State}, Multimap, ACCOUNT_ACTOR_CODE_ID, FIRST_NON_SINGLETON_ADDR, INIT_ACTOR_CODE_ID, MINER_ACTOR_CODE_ID, MULTISIG_ACTOR_CODE_ID, PAYCH_ACTOR_CODE_ID, POWER_ACTOR_CODE_ID, STORAGE_POWER_ACTOR_ADDR, SYSTEM_ACTOR_ADDR, SYSTEM_ACTOR_CODE_ID, @@ -20,7 +20,6 @@ use vm::{ActorError, ExitCode, Serialized, TokenAmount, METHOD_CONSTRUCTOR}; fn construct_runtime(bs: &BS) -> MockRuntime<'_, BS> { let receiver = Address::new_id(1000); - let message = UnsignedMessage::builder() .to(receiver.clone()) .from(SYSTEM_ACTOR_ADDR.clone()) @@ -268,7 +267,7 @@ fn construct_and_verify(rt: &mut MockRuntime<'_, BS>) { let ret = rt .call( &*INIT_ACTOR_CODE_ID, - 1, + METHOD_CONSTRUCTOR, &Serialized::serialize(¶ms).unwrap(), ) .unwrap(); @@ -302,20 +301,12 @@ where constructor_params: Serialized::serialize(params).unwrap(), }; - //Get the previous state so if call fails u can revert - let prev_state = rt.state.clone(); - let ret = rt.call( &*INIT_ACTOR_CODE_ID, - 2, + Method::Exec as u64, &Serialized::serialize(&exec_params).unwrap(), ); - // Revert state if call - if ret.is_err() { - rt.state = prev_state; - } - rt.verify(); ret } diff --git a/vm/actor/tests/reward_actor_test.rs b/vm/actor/tests/reward_actor_test.rs new file mode 100644 index 000000000000..ca051fdc7c40 --- /dev/null +++ b/vm/actor/tests/reward_actor_test.rs @@ -0,0 +1,73 @@ +// Copyright 2020 ChainSafe Systems +// SPDX-License-Identifier: Apache-2.0, MIT + +mod common; + +use actor::{ + reward::{AwardBlockRewardParams, Method}, + REWARD_ACTOR_ADDR, REWARD_ACTOR_CODE_ID, SYSTEM_ACTOR_ADDR, SYSTEM_ACTOR_CODE_ID, +}; +use address::Address; +use common::*; +use db::MemoryDB; +use ipld_blockstore::BlockStore; +use message::UnsignedMessage; +use vm::{ExitCode, Serialized, TokenAmount, METHOD_CONSTRUCTOR}; + +fn construct_runtime(bs: &BS) -> MockRuntime<'_, BS> { + let message = UnsignedMessage::builder() + .to(*REWARD_ACTOR_ADDR) + .from(*SYSTEM_ACTOR_ADDR) + .build() + .unwrap(); + let mut rt = MockRuntime::new(bs, message); + rt.caller_type = SYSTEM_ACTOR_CODE_ID.clone(); + return rt; +} + +#[test] +fn balance_less_than_reward() { + let bs = MemoryDB::default(); + let mut rt = construct_runtime(&bs); + construct_and_verify(&mut rt); + + let miner = Address::new_id(1000); + let gas_reward = TokenAmount::from(10u8); + + rt.expect_validate_caller_addr(&[*SYSTEM_ACTOR_ADDR]); + + let params = AwardBlockRewardParams { + miner: miner, + penalty: TokenAmount::from(0u8), + gas_reward: gas_reward, + ticket_count: 0, + }; + + //Expect call to fail because actor doesnt have enough tokens to reward + let call_result = rt.call( + &*REWARD_ACTOR_CODE_ID, + Method::AwardBlockReward as u64, + &Serialized::serialize(¶ms).unwrap(), + ); + + assert_eq!( + ExitCode::ErrInsufficientFunds, + call_result.unwrap_err().exit_code() + ); + + rt.verify() +} + +fn construct_and_verify(rt: &mut MockRuntime<'_, BS>) { + rt.expect_validate_caller_addr(&[SYSTEM_ACTOR_ADDR.clone()]); + let ret = rt + .call( + &*REWARD_ACTOR_CODE_ID, + METHOD_CONSTRUCTOR, + &Serialized::default(), + ) + .unwrap(); + + assert_eq!(Serialized::default(), ret); + rt.verify(); +} diff --git a/vm/interpreter/src/default_runtime.rs b/vm/interpreter/src/default_runtime.rs index 51efd9c4f265..7b39e9010b55 100644 --- a/vm/interpreter/src/default_runtime.rs +++ b/vm/interpreter/src/default_runtime.rs @@ -455,10 +455,10 @@ where actor::paych::Actor.invoke_method(runtime, method_num, msg.params()) } x if x == *MULTISIG_ACTOR_CODE_ID => { - actor::cron::Actor.invoke_method(runtime, method_num, msg.params()) + actor::multisig::Actor.invoke_method(runtime, method_num, msg.params()) } x if x == *REWARD_ACTOR_CODE_ID => { - actor::cron::Actor.invoke_method(runtime, method_num, msg.params()) + actor::reward::Actor.invoke_method(runtime, method_num, msg.params()) } _ => Err(ActorError::new( ExitCode::SysErrorIllegalActor,