Skip to content

Commit

Permalink
feat: allow all unrestricted method numbers on accounts
Browse files Browse the repository at this point in the history
This patch introduces a few features:

1. The dispatch macro can now pass the "raw" parameters to a method.
2. The dispatch macro can now have an explicit fallback case.

We then use these features to implement a "raw" fallback for both
account types that simply accepts all method calls greater than the max
FRC0042 number.

Alternative to #1081

Fixes #1076
  • Loading branch information
Stebalien committed Jan 20, 2023
1 parent abfb608 commit d0f2072
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 22 deletions.
23 changes: 14 additions & 9 deletions actors/account/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright 2019-2022 ChainSafe Systems
// SPDX-License-Identifier: Apache-2.0, MIT

use fvm_actor_utils::receiver::UniversalReceiverParams;
use fvm_ipld_encoding::ipld_block::IpldBlock;
use fvm_shared::address::{Address, Protocol};
use fvm_shared::crypto::signature::SignatureType::{Secp256k1, BLS};
use fvm_shared::crypto::signature::{Signature, SignatureType};
Expand All @@ -10,9 +10,10 @@ use fvm_shared::{MethodNum, METHOD_CONSTRUCTOR};
use num_derive::FromPrimitive;
use num_traits::FromPrimitive;

use fil_actors_runtime::builtin::shared::restrict_internal_api;
use fil_actors_runtime::builtin::singletons::SYSTEM_ACTOR_ADDR;
use fil_actors_runtime::runtime::{ActorCode, Runtime};
use fil_actors_runtime::{actor_dispatch, restrict_internal_api, ActorDowncast};
use fil_actors_runtime::{actor_dispatch, ActorDowncast, FIRST_EXPORTED_METHOD_NUMBER};
use fil_actors_runtime::{actor_error, ActorError};

use crate::types::AuthenticateMessageParams;
Expand All @@ -35,7 +36,6 @@ pub enum Method {
// Deprecated in v10
// AuthenticateMessage = 3,
AuthenticateMessageExported = frc42_dispatch::method_hash!("AuthenticateMessage"),
UniversalReceiverHook = frc42_dispatch::method_hash!("Receive"),
}

/// Account Actor
Expand Down Expand Up @@ -92,13 +92,18 @@ impl Actor {
Ok(())
}

// Always succeeds, accepting any transfers.
pub fn universal_receiver_hook(
/// Fallback method for unimplemented method numbers.
pub fn fallback(
rt: &mut impl Runtime,
_params: UniversalReceiverParams,
) -> Result<(), ActorError> {
method: MethodNum,
_: Option<IpldBlock>,
) -> Result<Option<IpldBlock>, ActorError> {
rt.validate_immediate_caller_accept_any()?;
Ok(())
if method >= FIRST_EXPORTED_METHOD_NUMBER {
Ok(None)
} else {
Err(actor_error!(unhandled_message; "invalid method: {}", method))
}
}
}

Expand All @@ -108,6 +113,6 @@ impl ActorCode for Actor {
Constructor => constructor,
PubkeyAddress => pubkey_address,
AuthenticateMessageExported => authenticate_message,
UniversalReceiverHook => universal_receiver_hook,
_ => fallback [raw],
}
}
2 changes: 1 addition & 1 deletion actors/account/tests/account_actor_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ fn token_receiver() {
rt.expect_validate_caller_any();
let ret = rt
.call::<AccountActor>(
Method::UniversalReceiverHook as MethodNum,
frc42_dispatch::method_hash!("Receive"),
IpldBlock::serialize_cbor(&UniversalReceiverParams {
type_: 0,
payload: RawBytes::new(vec![1, 2, 3]),
Expand Down
20 changes: 12 additions & 8 deletions actors/ethaccount/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pub mod types;

use fvm_actor_utils::receiver::UniversalReceiverParams;
use fvm_ipld_encoding::ipld_block::IpldBlock;
use fvm_shared::address::{Payload, Protocol};
use fvm_shared::crypto::hash::SupportedHashes::Keccak256;
use fvm_shared::error::ExitCode;
Expand All @@ -12,7 +12,7 @@ use crate::types::AuthenticateMessageParams;
use fil_actors_runtime::runtime::{ActorCode, Runtime};
use fil_actors_runtime::{
actor_dispatch, actor_error, restrict_internal_api, ActorDowncast, ActorError, AsActorError,
EAM_ACTOR_ID, SYSTEM_ACTOR_ADDR,
EAM_ACTOR_ID, FIRST_EXPORTED_METHOD_NUMBER, SYSTEM_ACTOR_ADDR,
};

#[cfg(feature = "fil-actor")]
Expand All @@ -24,7 +24,6 @@ fil_actors_runtime::wasm_trampoline!(EthAccountActor);
pub enum Method {
Constructor = METHOD_CONSTRUCTOR,
AuthenticateMessageExported = frc42_dispatch::method_hash!("AuthenticateMessage"),
UniversalReceiverHook = frc42_dispatch::method_hash!("Receive"),
}

/// Ethereum Account actor.
Expand Down Expand Up @@ -128,12 +127,17 @@ impl EthAccountActor {
}

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

Expand All @@ -142,6 +146,6 @@ impl ActorCode for EthAccountActor {
actor_dispatch! {
Constructor => constructor,
AuthenticateMessageExported => authenticate_message,
UniversalReceiverHook => universal_receiver_hook,
_ => fallback [raw],
}
}
36 changes: 32 additions & 4 deletions runtime/src/dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use crate::ActorError;
/// ```
#[macro_export]
macro_rules! actor_dispatch {
($($(#[$m:meta])* $method:ident => $func:ident,)*) => {
($($(#[$m:meta])* $(_)? $($method:ident)? => $func:ident $([$tag:ident])?,)*) => {
fn invoke_method<RT>(
rt: &mut RT,
method: MethodNum,
Expand All @@ -36,16 +36,30 @@ macro_rules! actor_dispatch {
{
restrict_internal_api(rt, method)?;
match FromPrimitive::from_u64(method) {
$($(#[$m])* Some(Self::Methods::$method) => $crate::dispatch(rt, Self::$func, &args),)*
$($(#[$m])*
$crate::actor_dispatch!(@pattern $($method)?) =>
$crate::actor_dispatch!(@target rt args method $func $($tag)?),)*
None => Err(actor_error!(unhandled_message; "invalid method: {}", method)),
}
}
};
(@pattern) => {
None
};
(@pattern $method:ident) => {
Some(Self::Methods::$method)
};
(@target $rt:ident $args:ident $method:ident $func:ident raw) => {
Self::$func($rt, $method, $args)
};
(@target $rt:ident $args:ident $method:ident $func:ident) => {
$crate::dispatch($rt, Self::$func, &$args)
};
}

#[macro_export]
macro_rules! actor_dispatch_unrestricted {
($($(#[$m:meta])* $method:ident => $func:ident,)*) => {
($($(#[$m:meta])* $(_)? $($method:ident)? => $func:ident $([$tag:ident])?,)*) => {
fn invoke_method<RT>(
rt: &mut RT,
method: MethodNum,
Expand All @@ -56,11 +70,25 @@ macro_rules! actor_dispatch_unrestricted {
RT::Blockstore: Clone,
{
match FromPrimitive::from_u64(method) {
$($(#[$m])* Some(Self::Methods::$method) => $crate::dispatch(rt, Self::$func, &args),)*
$($(#[$m])*
$crate::actor_dispatch!(@pattern $($method)?) =>
$crate::actor_dispatch!(@target rt args method $func $($tag)?),)*
None => Err(actor_error!(unhandled_message; "invalid method: {}", method)),
}
}
};
(@pattern) => {
None
};
(@pattern $method:ident) => {
Some(Self::Methods::$method)
};
(@target $rt:ident $args:ident $method:ident $func:ident raw) => {
Self::$func($rt, $method, $args)
};
(@target $rt:ident $args:ident $method:ident $func:ident) => {
$crate::dispatch($rt, Self::$func, &$args)
};
}

pub trait Dispatch<'de, RT> {
Expand Down

0 comments on commit d0f2072

Please sign in to comment.