diff --git a/fvm/src/kernel/default.rs b/fvm/src/kernel/default.rs index d43f74a95..61b0e5275 100644 --- a/fvm/src/kernel/default.rs +++ b/fvm/src/kernel/default.rs @@ -98,7 +98,34 @@ where self.call_manager.machine() } - fn send>( + fn limiter_mut(&mut self) -> &mut Self::Limiter { + self.call_manager.limiter_mut() + } + + fn gas_available(&self) -> Gas { + self.call_manager.gas_tracker().gas_available() + } + + fn charge_gas(&self, name: &str, compute: Gas) -> Result { + self.call_manager.gas_tracker().charge_gas(name, compute) + } +} + +impl DefaultKernel +where + C: CallManager, +{ + /// Returns `Some(actor_state)` or `None` if this actor has been deleted. + fn get_self(&self) -> Result> { + self.call_manager.get_actor(self.actor_id) + } +} + +impl SendOps for DefaultKernel +where + K: Kernel, +{ + fn send( &mut self, recipient: &Address, method: MethodNum, @@ -171,12 +198,13 @@ where }, }) } +} - fn upgrade_actor>( - &mut self, - new_code_cid: Cid, - params_id: BlockId, - ) -> Result { +impl UpgradeOps for DefaultKernel +where + K: Kernel, +{ + fn upgrade_actor(&mut self, new_code_cid: Cid, params_id: BlockId) -> Result { if self.read_only { return Err( syscall_error!(ReadOnly, "upgrade_actor cannot be called while read-only").into(), @@ -265,28 +293,6 @@ where Err(err) => Err(err), } } - - fn limiter_mut(&mut self) -> &mut Self::Limiter { - self.call_manager.limiter_mut() - } - - fn gas_available(&self) -> Gas { - self.call_manager.gas_tracker().gas_available() - } - - fn charge_gas(&self, name: &str, compute: Gas) -> Result { - self.call_manager.gas_tracker().charge_gas(name, compute) - } -} - -impl DefaultKernel -where - C: CallManager, -{ - /// Returns `Some(actor_state)` or `None` if this actor has been deleted. - fn get_self(&self) -> Result> { - self.call_manager.get_actor(self.actor_id) - } } impl SelfOps for DefaultKernel diff --git a/fvm/src/kernel/filecoin.rs b/fvm/src/kernel/filecoin.rs index d847bc6cb..05facafd7 100644 --- a/fvm/src/kernel/filecoin.rs +++ b/fvm/src/kernel/filecoin.rs @@ -97,6 +97,8 @@ pub trait FilecoinKernel: Kernel { #[delegate(NetworkOps, where = "C: CallManager")] #[delegate(RandomnessOps, where = "C: CallManager")] #[delegate(SelfOps, where = "C: CallManager")] +#[delegate(SendOps, generics = "K", where = "C: CallManager, K: FilecoinKernel")] +#[delegate(UpgradeOps, generics = "K", where = "C: CallManager, K: FilecoinKernel")] pub struct DefaultFilecoinKernel(pub DefaultKernel); impl FilecoinKernel for DefaultFilecoinKernel @@ -260,27 +262,6 @@ where self.0.machine() } - fn send>( - &mut self, - recipient: &Address, - method: u64, - params: BlockId, - value: &TokenAmount, - gas_limit: Option, - flags: SendFlags, - ) -> Result { - self.0 - .send::(recipient, method, params, value, gas_limit, flags) - } - - fn upgrade_actor>( - &mut self, - new_code_cid: Cid, - params_id: BlockId, - ) -> Result { - self.0.upgrade_actor::(new_code_cid, params_id) - } - fn new( mgr: C, blocks: BlockRegistry, diff --git a/fvm/src/kernel/mod.rs b/fvm/src/kernel/mod.rs index 34fcba2be..559aa68b7 100644 --- a/fvm/src/kernel/mod.rs +++ b/fvm/src/kernel/mod.rs @@ -66,29 +66,6 @@ pub trait Kernel: SyscallHandler + 'static { /// The kernel's underlying "machine". fn machine(&self) -> &::Machine; - /// Sends a message to another actor. - /// The method type parameter K is the type of the kernel to instantiate for - /// the receiving actor. This is necessary to support wrapping a kernel, so the outer - /// kernel can specify its Self as the receiver's kernel type, rather than the wrapped - /// kernel specifying its Self. - /// This method is part of the Kernel trait so it can refer to the Self::CallManager - /// associated type necessary to constrain K. - fn send>( - &mut self, - recipient: &Address, - method: u64, - params: BlockId, - value: &TokenAmount, - gas_limit: Option, - flags: SendFlags, - ) -> Result; - - fn upgrade_actor>( - &mut self, - new_code_cid: Cid, - params_id: BlockId, - ) -> Result; - /// Give access to the limiter of the underlying call manager. fn limiter_mut(&mut self) -> &mut Self::Limiter; @@ -121,6 +98,34 @@ pub trait MessageOps { fn msg_context(&self) -> Result; } +/// The actor calling operations. +#[delegatable_trait] +pub trait SendOps { + /// Sends a message to another actor. + /// The method type parameter K is the type of the kernel to instantiate for + /// the receiving actor. This is necessary to support wrapping a kernel, so the outer + /// kernel can specify its Self as the receiver's kernel type, rather than the wrapped + /// kernel specifying its Self. + /// This method is part of the Kernel trait so it can refer to the Self::CallManager + /// associated type necessary to constrain K. + fn send( + &mut self, + recipient: &Address, + method: u64, + params: BlockId, + value: &TokenAmount, + gas_limit: Option, + flags: SendFlags, + ) -> Result; +} + +/// The actor upgrade operations. +#[delegatable_trait] +pub trait UpgradeOps { + /// Upgrades the running actor to the specified code CID. + fn upgrade_actor(&mut self, new_code_cid: Cid, params_id: BlockId) -> Result; +} + /// The IPLD subset of the kernel. #[delegatable_trait] pub trait IpldBlockOps { @@ -291,7 +296,8 @@ pub trait EventOps { pub use { ambassador_impl_CryptoOps, ambassador_impl_DebugOps, ambassador_impl_EventOps, ambassador_impl_IpldBlockOps, ambassador_impl_MessageOps, ambassador_impl_NetworkOps, - ambassador_impl_RandomnessOps, ambassador_impl_SelfOps, + ambassador_impl_RandomnessOps, ambassador_impl_SelfOps, ambassador_impl_SendOps, + ambassador_impl_UpgradeOps, }; /// Import this module (with a glob) if you're implementing a kernel, _especially_ if you want to @@ -299,7 +305,7 @@ pub use { pub mod prelude { pub use super::{ ActorOps, CryptoOps, DebugOps, EventOps, IpldBlockOps, MessageOps, NetworkOps, - RandomnessOps, SelfOps, + RandomnessOps, SelfOps, SendOps, UpgradeOps, }; pub use super::{Block, BlockId, BlockRegistry, BlockStat, CallResult, Kernel, SyscallHandler}; pub use crate::gas::{Gas, GasTimer, PriceList}; @@ -323,6 +329,7 @@ pub mod prelude { ambassador_impl_ActorOps, ambassador_impl_CryptoOps, ambassador_impl_DebugOps, ambassador_impl_EventOps, ambassador_impl_IpldBlockOps, ambassador_impl_MessageOps, ambassador_impl_NetworkOps, ambassador_impl_RandomnessOps, ambassador_impl_SelfOps, + ambassador_impl_SendOps, ambassador_impl_UpgradeOps, }; } diff --git a/fvm/src/syscalls/actor.rs b/fvm/src/syscalls/actor.rs index a2ee000b4..6283d2e5a 100644 --- a/fvm/src/syscalls/actor.rs +++ b/fvm/src/syscalls/actor.rs @@ -6,6 +6,7 @@ use fvm_shared::{sys, ActorID}; use super::error::Abort; use super::Context; use super::ControlFlow; +use crate::kernel::UpgradeOps; use crate::kernel::{ActorOps, CallResult, ClassifyResult, Result}; use crate::{syscall_error, Kernel}; @@ -111,8 +112,8 @@ pub fn create_actor( context.kernel.create_actor(typ, actor_id, addr) } -pub fn upgrade_actor( - context: Context<'_, K>, +pub fn upgrade_actor( + context: Context<'_, impl UpgradeOps + Kernel>, new_code_cid_off: u32, params_id: u32, ) -> ControlFlow { @@ -121,7 +122,7 @@ pub fn upgrade_actor( Err(err) => return err.into(), }; - match context.kernel.upgrade_actor::(cid, params_id) { + match context.kernel.upgrade_actor(cid, params_id) { Ok(CallResult { block_id, block_stat, diff --git a/fvm/src/syscalls/mod.rs b/fvm/src/syscalls/mod.rs index d25bd6d86..572d878f6 100644 --- a/fvm/src/syscalls/mod.rs +++ b/fvm/src/syscalls/mod.rs @@ -9,7 +9,7 @@ use crate::gas::{Gas, GasInstant, GasTimer, WasmGasPrices}; use crate::kernel::filecoin::{DefaultFilecoinKernel, FilecoinKernel}; use crate::kernel::{ ActorOps, CryptoOps, DebugOps, EventOps, ExecutionError, IpldBlockOps, MessageOps, NetworkOps, - RandomnessOps, SelfOps, SyscallHandler, + RandomnessOps, SelfOps, SendOps, SyscallHandler, UpgradeOps, }; use crate::machine::limiter::MemoryLimiter; @@ -257,6 +257,8 @@ where K: Kernel + ActorOps + IpldBlockOps + + SendOps + + UpgradeOps + CryptoOps + DebugOps + EventOps @@ -345,6 +347,8 @@ impl SyscallHandler for DefaultFilecoinKernel where K: FilecoinKernel + ActorOps + + SendOps + + UpgradeOps + IpldBlockOps + CryptoOps + DebugOps diff --git a/fvm/src/syscalls/send.rs b/fvm/src/syscalls/send.rs index fbb450d42..17651c5ea 100644 --- a/fvm/src/syscalls/send.rs +++ b/fvm/src/syscalls/send.rs @@ -7,14 +7,13 @@ use fvm_shared::sys::{self, SendFlags}; use super::Context; use crate::gas::Gas; -use crate::kernel::{CallResult, ClassifyResult, Result}; -use crate::Kernel; +use crate::kernel::{CallResult, ClassifyResult, Kernel, Result, SendOps}; /// Send a message to another actor. The result is placed as a CBOR-encoded /// receipt in the block registry, and can be retrieved by the returned BlockId. #[allow(clippy::too_many_arguments)] -pub fn send( - context: Context<'_, K>, +pub fn send( + context: Context<'_, impl SendOps + Kernel>, recipient_off: u32, recipient_len: u32, method: u64, @@ -43,7 +42,7 @@ pub fn send( exit_code, } = context .kernel - .send::(&recipient, method, params_id, &value, gas_limit, flags)?; + .send(&recipient, method, params_id, &value, gas_limit, flags)?; Ok(sys::out::send::Send { exit_code: exit_code.value(), diff --git a/testing/conformance/src/vm.rs b/testing/conformance/src/vm.rs index bfc625388..2d9380fc8 100644 --- a/testing/conformance/src/vm.rs +++ b/testing/conformance/src/vm.rs @@ -169,6 +169,8 @@ type InnerTestKernel = DefaultFilecoinKernel>; #[delegate(NetworkOps)] #[delegate(RandomnessOps)] #[delegate(SelfOps)] +#[delegate(SendOps, generics = "K", where = "K: FilecoinKernel")] +#[delegate(UpgradeOps, generics = "K", where = "K: FilecoinKernel")] pub struct TestKernel(pub InnerTestKernel); impl TestKernel { @@ -215,27 +217,6 @@ impl Kernel for TestKernel { self.0.machine() } - fn send( - &mut self, - recipient: &Address, - method: u64, - params: BlockId, - value: &TokenAmount, - gas_limit: Option, - flags: SendFlags, - ) -> Result { - // Note that KK, the type of the kernel to crate for the receiving actor, is ignored, - // and Self is passed as the type parameter for the nested call. - // If we could find the correct bound to specify KK for the call, we would. - // This restricts the ability for the TestKernel to itself be wrapped by another kernel type. - self.0 - .send::(recipient, method, params, value, gas_limit, flags) - } - - fn upgrade_actor(&mut self, new_code_cid: Cid, params_id: BlockId) -> Result { - self.0.upgrade_actor::(new_code_cid, params_id) - } - fn limiter_mut(&mut self) -> &mut Self::Limiter { self.0.limiter_mut() }