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

feat: multisig: accept arbitrary public messages #1252

Merged
merged 12 commits into from
Apr 7, 2023
41 changes: 41 additions & 0 deletions actors/account/tests/account_actor_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use fil_actor_account::types::AuthenticateMessageParams;
use fil_actor_account::{testing::check_state_invariants, Actor as AccountActor, Method, State};
use fil_actors_runtime::builtin::SYSTEM_ACTOR_ADDR;
use fil_actors_runtime::test_utils::*;
use fil_actors_runtime::FIRST_EXPORTED_METHOD_NUMBER;

#[test]
fn construction() {
Expand Down Expand Up @@ -158,6 +159,46 @@ fn authenticate_message() {
.unwrap());
}

#[test]
fn accept_arbitrary() {
vyzo marked this conversation as resolved.
Show resolved Hide resolved
let mut rt = MockRuntime { receiver: Address::new_id(100), ..Default::default() };
rt.set_caller(*SYSTEM_ACTOR_CODE_ID, SYSTEM_ACTOR_ADDR);

let addr = Address::new_secp256k1(&[2; fvm_shared::address::SECP_PUB_LEN]).unwrap();
rt.expect_validate_caller_addr(vec![SYSTEM_ACTOR_ADDR]);
rt.call::<AccountActor>(
Method::Constructor as MethodNum,
IpldBlock::serialize_cbor(&addr).unwrap(),
)
.unwrap();

let state: State = rt.get_state();
assert_eq!(state.address, addr);

// this is arbitrary
let params = IpldBlock::serialize_cbor(&vec![1u8, 2u8, 3u8]).unwrap();

// accept >= 2<<24
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: the accept range is >= 2 ^24 (or >= 1 << 24)

rt.expect_validate_caller_any();
let result =
rt.call::<AccountActor>(FIRST_EXPORTED_METHOD_NUMBER as MethodNum, params.clone()).unwrap();
assert!(result.is_none());

rt.expect_validate_caller_any();
let result = rt
.call::<AccountActor>(FIRST_EXPORTED_METHOD_NUMBER + 1 as MethodNum, params.clone())
.unwrap();
assert!(result.is_none());

// reject < 2<<24
rt.expect_validate_caller_any();
let result =
rt.call::<AccountActor>(FIRST_EXPORTED_METHOD_NUMBER - 1 as MethodNum, params.clone());
assert!(result.is_err());

rt.verify();
}

fn check_state(rt: &MockRuntime) {
let test_address = Address::new_id(1000);
let (_, acc) = check_state_invariants(&rt.get_state(), &test_address);
Expand Down
17 changes: 17 additions & 0 deletions actors/multisig/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@
use fvm_actor_utils::receiver::UniversalReceiverParams;
use std::collections::BTreeSet;

use fil_actors_runtime::FIRST_EXPORTED_METHOD_NUMBER;
use fvm_ipld_blockstore::Blockstore;
use fvm_ipld_encoding::ipld_block::IpldBlock;
use fvm_ipld_encoding::RawBytes;
use fvm_shared::address::Address;
use fvm_shared::econ::TokenAmount;
use fvm_shared::error::ExitCode;
use fvm_shared::MethodNum;
use fvm_shared::{HAMT_BIT_WIDTH, METHOD_CONSTRUCTOR};
use num_derive::FromPrimitive;
use num_traits::Zero;
Expand Down Expand Up @@ -457,6 +460,19 @@ impl Actor {
rt.validate_immediate_caller_accept_any()?;
Ok(())
}

pub fn fallback(
rt: &mut impl Runtime,
method: MethodNum,
_: Option<IpldBlock>,
) -> Result<Option<IpldBlock>, ActorError> {
rt.validate_immediate_caller_accept_any()?;
if method >= FIRST_EXPORTED_METHOD_NUMBER {
Ok(None)
} else {
Err(actor_error!(unhandled_message; "invalid method: {}", method))
}
}
}

fn execute_transaction_if_approved(
Expand Down Expand Up @@ -569,5 +585,6 @@ impl ActorCode for Actor {
ChangeNumApprovalsThreshold => change_num_approvals_threshold,
LockBalance => lock_balance,
UniversalReceiverHook => universal_receiver_hook,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could remove this, since the Universal Receiver Hook's method is in the exported FRC-42 range, so it gets covered by the fallback. But I'd rather keep this explicit branch for clarity. IMO, the account actor should do the same (which it doesn't).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: lets make the change to explicit handling of universal receiver hook to the account actor in this PR

_ => fallback [raw],
ZenGround0 marked this conversation as resolved.
Show resolved Hide resolved
}
}
36 changes: 36 additions & 0 deletions actors/multisig/tests/multisig_actor_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use fil_actor_multisig::{
use fil_actors_runtime::cbor::serialize;
use fil_actors_runtime::runtime::Runtime;
use fil_actors_runtime::test_utils::*;
use fil_actors_runtime::FIRST_EXPORTED_METHOD_NUMBER;
use fil_actors_runtime::{INIT_ACTOR_ADDR, SYSTEM_ACTOR_ADDR};
use fvm_actor_utils::receiver::UniversalReceiverParams;
use fvm_ipld_encoding::ipld_block::IpldBlock;
Expand Down Expand Up @@ -2410,3 +2411,38 @@ fn token_receiver() {
fn to_ipld_block(p: RawBytes) -> Option<IpldBlock> {
Some(IpldBlock { codec: CBOR, data: p.to_vec() })
}

#[test]
fn accept_arbitrary() {
let msig = Address::new_id(1000);
let anne = Address::new_id(101);
let bob = Address::new_id(102);

let mut rt = construct_runtime(msig);
let h = util::ActorHarness::new();
h.construct_and_verify(&mut rt, 2, 0, 0, vec![anne, bob]);

// this is arbitrary
let params = IpldBlock::serialize_cbor(&vec![1u8, 2u8, 3u8]).unwrap();

// accept >= 2<<24
rt.expect_validate_caller_any();
let result = rt
.call::<MultisigActor>(FIRST_EXPORTED_METHOD_NUMBER as MethodNum, params.clone())
.unwrap();
assert!(result.is_none());

rt.expect_validate_caller_any();
let result = rt
.call::<MultisigActor>(FIRST_EXPORTED_METHOD_NUMBER + 1 as MethodNum, params.clone())
.unwrap();
assert!(result.is_none());

// reject < 2<<24
rt.expect_validate_caller_any();
let result =
rt.call::<MultisigActor>(FIRST_EXPORTED_METHOD_NUMBER - 1 as MethodNum, params.clone());
assert!(result.is_err());

rt.verify();
}
16 changes: 16 additions & 0 deletions actors/paych/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ use fvm_ipld_blockstore::Blockstore;
use fvm_ipld_encoding::CBOR;
use fvm_shared::address::Address;

use fil_actors_runtime::FIRST_EXPORTED_METHOD_NUMBER;
use fvm_ipld_encoding::ipld_block::IpldBlock;
use fvm_shared::econ::TokenAmount;
use fvm_shared::error::ExitCode;
use fvm_shared::sys::SendFlags;
use fvm_shared::MethodNum;
use fvm_shared::{METHOD_CONSTRUCTOR, METHOD_SEND};
use num_derive::FromPrimitive;
use num_traits::Zero;
Expand Down Expand Up @@ -298,6 +300,19 @@ impl Actor {

Ok(())
}

pub fn fallback(
rt: &mut impl Runtime,
method: MethodNum,
_: Option<IpldBlock>,
) -> Result<Option<IpldBlock>, ActorError> {
rt.validate_immediate_caller_accept_any()?;
if method >= FIRST_EXPORTED_METHOD_NUMBER {
Ok(None)
} else {
Err(actor_error!(unhandled_message; "invalid method: {}", method))
}
}
}

#[inline]
Expand All @@ -324,5 +339,6 @@ impl ActorCode for Actor {
UpdateChannelState => update_channel_state,
Settle => settle,
Collect => collect,
_ => fallback [raw],
}
}
30 changes: 30 additions & 0 deletions actors/paych/tests/paych_actor_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use fil_actor_paych::{
use fil_actors_runtime::runtime::builtins::Type;
use fil_actors_runtime::runtime::Runtime;
use fil_actors_runtime::test_utils::*;
use fil_actors_runtime::FIRST_EXPORTED_METHOD_NUMBER;
use fil_actors_runtime::INIT_ACTOR_ADDR;
use fvm_ipld_amt::Amt;
use fvm_ipld_encoding::ipld_block::IpldBlock;
Expand All @@ -26,6 +27,7 @@ use fvm_shared::crypto::signature::Signature;
use fvm_shared::econ::TokenAmount;
use fvm_shared::error::ExitCode;
use fvm_shared::sys::SendFlags;
use fvm_shared::MethodNum;
use fvm_shared::METHOD_CONSTRUCTOR;
use num_traits::Zero;

Expand Down Expand Up @@ -1149,3 +1151,31 @@ fn expect_authenticate_message(
None,
)
}

#[test]
fn accept_arbitrary() {
let (mut rt, _) = require_create_channel_with_lanes(1);

// this is arbitrary
let params = IpldBlock::serialize_cbor(&vec![1u8, 2u8, 3u8]).unwrap();

// accept >= 2<<24
rt.expect_validate_caller_any();
let result =
rt.call::<PaychActor>(FIRST_EXPORTED_METHOD_NUMBER as MethodNum, params.clone()).unwrap();
assert!(result.is_none());

rt.expect_validate_caller_any();
let result = rt
.call::<PaychActor>(FIRST_EXPORTED_METHOD_NUMBER + 1 as MethodNum, params.clone())
.unwrap();
assert!(result.is_none());

// reject < 2<<24
rt.expect_validate_caller_any();
let result =
rt.call::<PaychActor>(FIRST_EXPORTED_METHOD_NUMBER - 1 as MethodNum, params.clone());
assert!(result.is_err());

rt.verify();
}