Skip to content
This repository has been archived by the owner on Jan 11, 2024. It is now read-only.

Commit

Permalink
Add new custom kernel skeleton
Browse files Browse the repository at this point in the history
  • Loading branch information
fridrik01 committed Dec 4, 2023
1 parent f5c8bcc commit def9cd2
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 2 deletions.
5 changes: 3 additions & 2 deletions fendermint/vm/interpreter/src/fvm/state/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ use fvm::{
state_tree::StateTree,
DefaultKernel,
};
use fvm::kernel::filecoin::DefaultFilecoinKernel;
use fvm_ipld_blockstore::Blockstore;
use fvm_ipld_encoding::RawBytes;
use fvm_shared::{
Expand Down Expand Up @@ -79,13 +78,15 @@ pub struct FvmUpdatableParams {

pub type MachineBlockstore<DB> = <DefaultMachine<DB, FendermintExterns> as Machine>::Blockstore;

use crate::fvm::state::mycustomkernel::DefaultCustomKernel;

/// A state we create for the execution of all the messages in a block.
pub struct FvmExecState<DB>
where
DB: Blockstore + 'static,
{
executor:
DefaultExecutor<DefaultFilecoinKernel<DefaultKernel<DefaultCallManager<DefaultMachine<DB, FendermintExterns>>>>>,
DefaultExecutor<DefaultCustomKernel<DefaultKernel<DefaultCallManager<DefaultMachine<DB, FendermintExterns>>>>>,

/// Hash of the block currently being executed. For queries and checks this is empty.
///
Expand Down
1 change: 1 addition & 0 deletions fendermint/vm/interpreter/src/fvm/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ mod genesis;
pub mod ipc;
mod query;
pub mod snapshot;
pub mod mycustomkernel;

use std::sync::Arc;

Expand Down
171 changes: 171 additions & 0 deletions fendermint/vm/interpreter/src/fvm/state/mycustomkernel.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
// Copyright 2021-2023 Protocol Labs
// SPDX-License-Identifier: Apache-2.0, MIT


use fvm::gas::GasTimer;
use fvm::gas::PriceList;
use fvm::kernel::*;
use fvm::syscalls::InvocationData;
use fvm::syscalls::bind::BindSyscall;
use fvm::call_manager::CallManager;
use fvm::gas::Gas;
use fvm::{
DefaultKernel, ambassador_impl_IpldBlockOps, ambassador_impl_ActorOps, ambassador_impl_CircSupplyOps, ambassador_impl_CryptoOps, ambassador_impl_DebugOps, ambassador_impl_EventOps, ambassador_impl_GasOps, ambassador_impl_MessageOps, ambassador_impl_NetworkOps, ambassador_impl_RandomnessOps, ambassador_impl_SelfOps, ambassador_impl_LimiterOps
};

use fvm_shared::{address::Address, econ::TokenAmount, ActorID, MethodNum, sys::SendFlags};
use fvm_shared::crypto::signature::*;
use fvm_shared::sys::out::vm::MessageContext;
use fvm_shared::sys::out::network::NetworkContext;
use fvm_shared::clock::ChainEpoch;
use fvm_shared::randomness::RANDOMNESS_LENGTH;

use multihash::MultihashGeneric;
use cid::Cid;

use wasmtime::Linker;
use ambassador::Delegate;

// define the custom kernel syscall here
pub trait CustomKernel: Kernel {
fn my_custom_syscall(&self) -> Result<()>;
}

#[derive(Delegate)]
#[delegate(IpldBlockOps)]
#[delegate(ActorOps)]
#[delegate(CircSupplyOps)]
#[delegate(CryptoOps)]
#[delegate(DebugOps)]
#[delegate(EventOps)]
#[delegate(GasOps)]
#[delegate(MessageOps)]
#[delegate(NetworkOps)]
#[delegate(RandomnessOps)]
#[delegate(SelfOps)]
#[delegate(LimiterOps)]
// we define the implementation of the custom kernel here. We use ambassador to delegate most of the existing syscalls to the default kernel
pub struct DefaultCustomKernel<K>(pub K)
where
K: Kernel;

// we need to implement the custom kernel trait for the default custom kernel
impl<C> CustomKernel for DefaultCustomKernel<DefaultKernel<C>>
where
C: CallManager,
DefaultCustomKernel<DefaultKernel<C>>: Kernel,
{
fn my_custom_syscall(&self) -> Result<()> {
// TODO: Implement the kernel syscall here.
Ok(())
}
}

// we need to implement the kernel trait for the default custom kernel, here we simply delegate to the default kernel
impl<C> Kernel for DefaultCustomKernel<DefaultKernel<C>>
where
C: CallManager,
{
type CallManager = C;

fn into_inner(self) -> (Self::CallManager, BlockRegistry)
where
Self: Sized,
{
self.0.into_inner()
}

fn machine(&self) -> &<Self::CallManager as CallManager>::Machine {
self.0.machine()
}

fn send<K: Kernel<CallManager = C>>(
&mut self,
recipient: &Address,
method: u64,
params: BlockId,
value: &TokenAmount,
gas_limit: Option<Gas>,
flags: SendFlags,
) -> Result<CallResult> {
self.0
.send::<Self>(recipient, method, params, value, gas_limit, flags)
}

fn upgrade_actor<K: Kernel<CallManager = Self::CallManager>>(
&mut self,
new_code_cid: Cid,
params_id: BlockId,
) -> Result<CallResult> {
self.0.upgrade_actor::<Self>(new_code_cid, params_id)
}

fn new(
mgr: C,
blocks: BlockRegistry,
caller: ActorID,
actor_id: ActorID,
method: MethodNum,
value_received: TokenAmount,
read_only: bool,
) -> Self {
DefaultCustomKernel(DefaultKernel::new(
mgr,
blocks,
caller,
actor_id,
method,
value_received,
read_only,
))
}
}

// we need to implement the syscall handler for the default custom kernel which binds our syscalls to the wasmtime linker
impl<C> SyscallHandler<DefaultCustomKernel<DefaultKernel<C>>>
for DefaultCustomKernel<DefaultKernel<C>>
where
C: CallManager,
{
fn bind_syscalls(
&self,
linker: &mut Linker<InvocationData<DefaultCustomKernel<DefaultKernel<C>>>>,
) -> anyhow::Result<()> {
self.0.bind_syscalls(linker)?;

// Now bind our custom syscalls
linker.bind(
"my_custom_kernel",
"my_custom_syscall",
my_custom_syscall,
)?;

Ok(())
}
}

// this is the actual syscall implementation as registered in bind_syscalls
pub fn my_custom_syscall(context: fvm::syscalls::Context<'_, impl CustomKernel>) -> Result<()> {
context
.kernel
.my_custom_syscall()?;
Ok(())
}

pub mod sdk {
// This is the direct sdk call the wasm actor calls
pub fn my_custom_syscall() {
unsafe {
sys::my_custom_syscall().unwrap();
}
}

pub mod sys {
use fvm_sdk::fvm_syscalls;

fvm_syscalls!{
module = "my_custom_kernel";
pub fn my_custom_syscall() -> Result<()>;
}
}
}

0 comments on commit def9cd2

Please sign in to comment.