diff --git a/actors/multisig/src/lib.rs b/actors/multisig/src/lib.rs index b8ed85651..647cbc021 100644 --- a/actors/multisig/src/lib.rs +++ b/actors/multisig/src/lib.rs @@ -71,7 +71,7 @@ impl Actor { let mut resolved_signers = Vec::with_capacity(params.signers.len()); let mut dedup_signers = BTreeSet::new(); for signer in ¶ms.signers { - let resolved = resolve_to_actor_id(rt, signer)?; + let resolved = resolve_to_actor_id(rt, signer, true)?; if !dedup_signers.insert(resolved) { return Err( actor_error!(illegal_argument; "duplicate signer not allowed: {}", signer), @@ -257,7 +257,7 @@ impl Actor { pub fn add_signer(rt: &mut impl Runtime, params: AddSignerParams) -> Result<(), ActorError> { let receiver = rt.message().receiver(); rt.validate_immediate_caller_is(std::iter::once(&receiver))?; - let resolved_new_signer = resolve_to_actor_id(rt, ¶ms.signer)?; + let resolved_new_signer = resolve_to_actor_id(rt, ¶ms.signer, true)?; rt.transaction(|st: &mut State, _| { if st.signers.len() >= SIGNERS_MAX { @@ -288,7 +288,7 @@ impl Actor { ) -> Result<(), ActorError> { let receiver = rt.message().receiver(); rt.validate_immediate_caller_is(std::iter::once(&receiver))?; - let resolved_old_signer = resolve_to_actor_id(rt, ¶ms.signer)?; + let resolved_old_signer = resolve_to_actor_id(rt, ¶ms.signer, false)?; rt.transaction(|st: &mut State, rt| { if !st.is_signer(&Address::new_id(resolved_old_signer)) { @@ -335,8 +335,8 @@ impl Actor { pub fn swap_signer(rt: &mut impl Runtime, params: SwapSignerParams) -> Result<(), ActorError> { let receiver = rt.message().receiver(); rt.validate_immediate_caller_is(std::iter::once(&receiver))?; - let from_resolved = resolve_to_actor_id(rt, ¶ms.from)?; - let to_resolved = resolve_to_actor_id(rt, ¶ms.to)?; + let from_resolved = resolve_to_actor_id(rt, ¶ms.from, false)?; + let to_resolved = resolve_to_actor_id(rt, ¶ms.to, true)?; rt.transaction(|st: &mut State, rt| { if !st.is_signer(&Address::new_id(from_resolved)) { diff --git a/actors/multisig/tests/multisig_actor_test.rs b/actors/multisig/tests/multisig_actor_test.rs index f0f8ccdf6..c7d31f5f5 100644 --- a/actors/multisig/tests/multisig_actor_test.rs +++ b/actors/multisig/tests/multisig_actor_test.rs @@ -8,24 +8,42 @@ use fil_actors_runtime::runtime::Runtime; use fil_actors_runtime::test_utils::*; use fil_actors_runtime::{INIT_ACTOR_ADDR, SYSTEM_ACTOR_ADDR}; use fvm_actor_utils::receiver::UniversalReceiverParams; +use fvm_ipld_encoding::ipld_block::IpldBlock; use fvm_ipld_encoding::tuple::*; use fvm_ipld_encoding::{RawBytes, CBOR}; use fvm_shared::address::{Address, BLS_PUB_LEN}; - -use fvm_ipld_encoding::ipld_block::IpldBlock; use fvm_shared::bigint::Zero; use fvm_shared::clock::ChainEpoch; use fvm_shared::econ::TokenAmount; use fvm_shared::error::ExitCode; use fvm_shared::{MethodNum, METHOD_SEND}; +use std::collections::HashMap; mod util; +const TEST_MSIG_ADDR: u64 = 100; +const TEST_ANNE_ADDR: u64 = 101; +const TEST_BOB_ADDR: u64 = 102; +const TEST_CHUCK_ADDR: u64 = 103; +const TEST_DARLENE_ADDR: u64 = 104; + fn construct_runtime(receiver: Address) -> MockRuntime { + let test_msig_addr = Address::new_id(TEST_MSIG_ADDR); + let test_anne_addr = Address::new_id(TEST_ANNE_ADDR); + let test_bob_addr = Address::new_id(TEST_BOB_ADDR); + let test_chuck_addr = Address::new_id(TEST_CHUCK_ADDR); + let test_darlene_addr = Address::new_id(TEST_DARLENE_ADDR); + let mut actor_code_cids = HashMap::default(); + actor_code_cids.insert(test_msig_addr, *ACCOUNT_ACTOR_CODE_ID); + actor_code_cids.insert(test_anne_addr, *ACCOUNT_ACTOR_CODE_ID); + actor_code_cids.insert(test_bob_addr, *ACCOUNT_ACTOR_CODE_ID); + actor_code_cids.insert(test_chuck_addr, *ACCOUNT_ACTOR_CODE_ID); + actor_code_cids.insert(test_darlene_addr, *ACCOUNT_ACTOR_CODE_ID); MockRuntime { receiver, caller: SYSTEM_ACTOR_ADDR, caller_type: *SYSTEM_ACTOR_CODE_ID, + actor_code_cids, ..Default::default() } } diff --git a/actors/paych/src/lib.rs b/actors/paych/src/lib.rs index 3e01e85ae..f4aa5d397 100644 --- a/actors/paych/src/lib.rs +++ b/actors/paych/src/lib.rs @@ -5,7 +5,7 @@ use fil_actors_runtime::runtime::builtins::Type; use fil_actors_runtime::runtime::{ActorCode, Runtime}; use fil_actors_runtime::{ actor_dispatch, actor_error, extract_send_result, resolve_to_actor_id, ActorDowncast, - ActorError, Array, AsActorError, + ActorError, Array, }; use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::CBOR; @@ -54,16 +54,9 @@ impl Actor { // behalf of the payer/payee. rt.validate_immediate_caller_type(std::iter::once(&Type::Init))?; - // Resolve both parties, confirming they exist in the state tree. - let to = Self::resolve_address(rt, ¶ms.to) - .with_context_code(ExitCode::USR_ILLEGAL_ARGUMENT, || { - format!("to address not found {}", params.to) - })?; - - let from = Self::resolve_address(rt, ¶ms.from) - .with_context_code(ExitCode::USR_ILLEGAL_ARGUMENT, || { - format!("from address not found {}", params.from) - })?; + // Check both parties are capable of signing vouchers + let to = resolve_to_actor_id(rt, ¶ms.to, true).map(Address::new_id)?; + let from = resolve_to_actor_id(rt, ¶ms.from, true).map(Address::new_id)?; let empty_arr_cid = Array::<(), _>::new_with_bit_width(rt.store(), LANE_STATES_AMT_BITWIDTH) @@ -76,16 +69,6 @@ impl Actor { Ok(()) } - /// Resolves an address to a canonical ID address and confirms it exists in the state tree. - fn resolve_address(rt: &mut impl Runtime, raw: &Address) -> Result { - let resolved = resolve_to_actor_id(rt, raw)?; - - // so long as we can find code for this, return `resolved` - rt.get_actor_code_cid(&resolved) - .map(|_| Address::new_id(resolved)) - .ok_or_else(|| actor_error!(illegal_argument, "no code for address {}", resolved)) - } - pub fn update_channel_state( rt: &mut impl Runtime, params: UpdateChannelStateParams, diff --git a/actors/paych/tests/paych_actor_test.rs b/actors/paych/tests/paych_actor_test.rs index 909aef0c7..ff4d6b76c 100644 --- a/actors/paych/tests/paych_actor_test.rs +++ b/actors/paych/tests/paych_actor_test.rs @@ -118,7 +118,7 @@ mod paych_constructor { &mut rt, METHOD_CONSTRUCTOR, IpldBlock::serialize_cbor(¶ms).unwrap(), - ExitCode::USR_ILLEGAL_ARGUMENT, + ExitCode::USR_NOT_FOUND, ); } diff --git a/actors/verifreg/src/lib.rs b/actors/verifreg/src/lib.rs index b22090cbb..47c777624 100644 --- a/actors/verifreg/src/lib.rs +++ b/actors/verifreg/src/lib.rs @@ -105,7 +105,7 @@ impl Actor { )); } - let verifier = resolve_to_actor_id(rt, ¶ms.address)?; + let verifier = resolve_to_actor_id(rt, ¶ms.address, true)?; let verifier = Address::new_id(verifier); @@ -135,7 +135,7 @@ impl Actor { } pub fn remove_verifier(rt: &mut impl Runtime, params: Address) -> Result<(), ActorError> { - let verifier = resolve_to_actor_id(rt, ¶ms)?; + let verifier = resolve_to_actor_id(rt, ¶ms, false)?; let verifier = Address::new_id(verifier); let state: State = rt.state()?; @@ -162,7 +162,7 @@ impl Actor { )); } - let client = resolve_to_actor_id(rt, ¶ms.address)?; + let client = resolve_to_actor_id(rt, ¶ms.address, true)?; let client = Address::new_id(client); let st: State = rt.state()?; @@ -216,13 +216,13 @@ impl Actor { rt: &mut impl Runtime, params: RemoveDataCapParams, ) -> Result { - let client = resolve_to_actor_id(rt, ¶ms.verified_client_to_remove)?; + let client = resolve_to_actor_id(rt, ¶ms.verified_client_to_remove, false)?; let client = Address::new_id(client); - let verifier_1 = resolve_to_actor_id(rt, ¶ms.verifier_request_1.verifier)?; + let verifier_1 = resolve_to_actor_id(rt, ¶ms.verifier_request_1.verifier, true)?; let verifier_1 = Address::new_id(verifier_1); - let verifier_2 = resolve_to_actor_id(rt, ¶ms.verifier_request_2.verifier)?; + let verifier_2 = resolve_to_actor_id(rt, ¶ms.verifier_request_2.verifier, true)?; let verifier_2 = Address::new_id(verifier_2); if verifier_1 == verifier_2 { diff --git a/actors/verifreg/tests/harness/mod.rs b/actors/verifreg/tests/harness/mod.rs index 895865f07..d1cdd9f40 100644 --- a/actors/verifreg/tests/harness/mod.rs +++ b/actors/verifreg/tests/harness/mod.rs @@ -1,18 +1,3 @@ -use frc46_token::receiver::{FRC46TokenReceived, FRC46_TOKEN_TYPE}; -use frc46_token::token::types::{BurnParams, BurnReturn, TransferParams}; -use frc46_token::token::TOKEN_PRECISION; -use fvm_actor_utils::receiver::UniversalReceiverParams; -use fvm_ipld_encoding::RawBytes; -use fvm_shared::address::Address; -use fvm_shared::bigint::bigint_ser::{BigIntDe, BigIntSer}; -use fvm_shared::clock::ChainEpoch; -use fvm_shared::econ::TokenAmount; -use fvm_shared::error::ExitCode; -use fvm_shared::piece::PaddedPieceSize; -use fvm_shared::sector::SectorNumber; -use fvm_shared::{ActorID, MethodNum, HAMT_BIT_WIDTH}; -use num_traits::{ToPrimitive, Zero}; - use fil_actor_verifreg::testing::check_state_invariants; use fil_actor_verifreg::{ ext, Actor as VerifregActor, AddVerifiedClientParams, AddVerifierParams, Allocation, @@ -33,15 +18,51 @@ use fil_actors_runtime::{ make_empty_map, ActorError, AsActorError, BatchReturn, DATACAP_TOKEN_ACTOR_ADDR, STORAGE_MARKET_ACTOR_ADDR, SYSTEM_ACTOR_ADDR, VERIFIED_REGISTRY_ACTOR_ADDR, }; +use frc46_token::receiver::{FRC46TokenReceived, FRC46_TOKEN_TYPE}; +use frc46_token::token::types::{BurnParams, BurnReturn, TransferParams}; +use frc46_token::token::TOKEN_PRECISION; +use fvm_actor_utils::receiver::UniversalReceiverParams; use fvm_ipld_encoding::ipld_block::IpldBlock; +use fvm_ipld_encoding::RawBytes; +use fvm_shared::address::Address; +use fvm_shared::bigint::bigint_ser::{BigIntDe, BigIntSer}; +use fvm_shared::clock::ChainEpoch; +use fvm_shared::econ::TokenAmount; +use fvm_shared::error::ExitCode; +use fvm_shared::piece::PaddedPieceSize; +use fvm_shared::sector::SectorNumber; +use fvm_shared::{ActorID, MethodNum, HAMT_BIT_WIDTH}; +use num_traits::{ToPrimitive, Zero}; +use std::collections::HashMap; pub const ROOT_ADDR: Address = Address::new_id(101); +const TEST_VERIFIER_ADDR: u64 = 201; +const TEST_VERIFIER2_ADDR: u64 = 202; +const TEST_CLIENT_ADDR: u64 = 301; +const TEST_CLIENT2_ADDR: u64 = 302; +const TEST_CLIENT3_ADDR: u64 = 303; +const TEST_CLIENT4_ADDR: u64 = 304; + pub fn new_runtime() -> MockRuntime { + let test_verifier_addr = Address::new_id(TEST_VERIFIER_ADDR); + let test_verifier2_addr = Address::new_id(TEST_VERIFIER2_ADDR); + let test_client_addr = Address::new_id(TEST_CLIENT_ADDR); + let test_client2_addr = Address::new_id(TEST_CLIENT2_ADDR); + let test_client3_addr = Address::new_id(TEST_CLIENT3_ADDR); + let test_client4_addr = Address::new_id(TEST_CLIENT4_ADDR); + let mut actor_code_cids = HashMap::default(); + actor_code_cids.insert(test_verifier_addr, *ACCOUNT_ACTOR_CODE_ID); + actor_code_cids.insert(test_verifier2_addr, *ACCOUNT_ACTOR_CODE_ID); + actor_code_cids.insert(test_client_addr, *ACCOUNT_ACTOR_CODE_ID); + actor_code_cids.insert(test_client2_addr, *ACCOUNT_ACTOR_CODE_ID); + actor_code_cids.insert(test_client3_addr, *ACCOUNT_ACTOR_CODE_ID); + actor_code_cids.insert(test_client4_addr, *ACCOUNT_ACTOR_CODE_ID); MockRuntime { receiver: VERIFIED_REGISTRY_ACTOR_ADDR, caller: SYSTEM_ACTOR_ADDR, caller_type: *SYSTEM_ACTOR_CODE_ID, + actor_code_cids, ..Default::default() } } diff --git a/runtime/src/builtin/shared.rs b/runtime/src/builtin/shared.rs index aa10f62a6..cd4bbd65f 100644 --- a/runtime/src/builtin/shared.rs +++ b/runtime/src/builtin/shared.rs @@ -21,22 +21,33 @@ pub const FIRST_ACTOR_SPECIFIC_EXIT_CODE: u32 = 32; pub fn resolve_to_actor_id( rt: &mut impl Runtime, address: &Address, + check_existence: bool, ) -> Result { + let mut actor_id = None; // if we are able to resolve it to an ID address, return the resolved address if let Some(id) = rt.resolve_address(address) { - return Ok(id); - } + actor_id = Some(id) + } else { + // send 0 balance to the account so an ID address for it is created and then try to resolve + extract_send_result(rt.send_simple( + address, + METHOD_SEND, + Default::default(), + Default::default(), + )) + .with_context(|| format!("failed to send zero balance to address {}", address))?; - // send 0 balance to the account so an ID address for it is created and then try to resolve - extract_send_result(rt.send_simple( - address, - METHOD_SEND, - Default::default(), - Default::default(), - )) - .with_context(|| format!("failed to send zero balance to address {}", address))?; + if let Some(id) = rt.resolve_address(address) { + actor_id = Some(id) + } + } - if let Some(id) = rt.resolve_address(address) { + if let Some(id) = actor_id { + // check for actor existence + if check_existence { + rt.get_actor_code_cid(&id) + .ok_or_else(|| actor_error!(not_found, "no code for address {}", address))?; + } return Ok(id); }