use fvm::call_manager::CallManager;
use fvm::gas::Gas;
use fvm::kernel::Result;
use fvm::kernel::filecoin::{DefaultFilecoinKernel, FilecoinKernel};
use fvm::kernel::prelude::*;
use fvm::kernel::{
ActorOps, CryptoOps, DebugOps, EventOps, IpldBlockOps, MessageOps, NetworkOps, RandomnessOps,
SelfOps, SendOps, SyscallHandler, UpgradeOps,
};
use fvm::syscalls::Linker;
use fvm_shared::clock::ChainEpoch;
use fvm_shared::consensus::ConsensusFault;
use fvm_shared::piece::PieceInfo;
use fvm_shared::randomness::RANDOMNESS_LENGTH;
use fvm_shared::sector::{
AggregateSealVerifyProofAndInfos, RegisteredSealProof, ReplicaUpdateInfo, SealVerifyInfo,
};
use fvm_shared::sys::out::network::NetworkContext;
use fvm_shared::sys::out::vm::MessageContext;
use fvm_shared::{ActorID, MethodNum, address::Address, econ::TokenAmount};
use ambassador::Delegate;
use cid::Cid;
pub trait CustomKernel: Kernel {
fn my_custom_syscall(&self, doubleme: i32) -> Result<i32>;
}
#[allow(clippy::duplicated_attributes)]
#[derive(Delegate)]
#[delegate(IpldBlockOps, where = "C: CallManager")]
#[delegate(ActorOps, where = "C: CallManager")]
#[delegate(CryptoOps, where = "C: CallManager")]
#[delegate(DebugOps, where = "C: CallManager")]
#[delegate(EventOps, where = "C: CallManager")]
#[delegate(MessageOps, where = "C: CallManager")]
#[delegate(NetworkOps, where = "C: CallManager")]
#[delegate(RandomnessOps, where = "C: CallManager")]
#[delegate(SelfOps, where = "C: CallManager")]
#[delegate(SendOps<K>, generics = "K", where = "K: CustomKernel")]
#[delegate(UpgradeOps<K>, generics = "K", where = "K: CustomKernel")]
pub struct DefaultCustomKernel<C>(pub DefaultFilecoinKernel<C>);
impl<C> CustomKernel for DefaultCustomKernel<C>
where
C: CallManager,
DefaultCustomKernel<C>: Kernel,
{
fn my_custom_syscall(&self, doubleme: i32) -> Result<i32> {
Ok(doubleme * 2)
}
}
impl<C> DefaultCustomKernel<C>
where
C: CallManager,
{
fn price_list(&self) -> &PriceList {
(self.0).0.call_manager.price_list()
}
}
impl<C> Kernel for DefaultCustomKernel<C>
where
C: CallManager,
{
type CallManager = C;
type Limiter = <DefaultFilecoinKernel<C> as Kernel>::Limiter;
fn into_inner(self) -> (Self::CallManager, BlockRegistry)
where
Self: Sized,
{
self.0.into_inner()
}
fn new(
mgr: C,
blocks: BlockRegistry,
caller: ActorID,
actor_id: ActorID,
method: MethodNum,
value_received: TokenAmount,
read_only: bool,
) -> Self {
DefaultCustomKernel(DefaultFilecoinKernel::new(
mgr,
blocks,
caller,
actor_id,
method,
value_received,
read_only,
))
}
fn machine(&self) -> &<Self::CallManager as CallManager>::Machine {
self.0.machine()
}
fn limiter_mut(&mut self) -> &mut Self::Limiter {
self.0.limiter_mut()
}
fn gas_available(&self) -> Gas {
self.0.gas_available()
}
fn charge_gas(&self, name: &str, compute: Gas) -> Result<GasTimer> {
self.0.charge_gas(name, compute)
}
}
impl<C> FilecoinKernel for DefaultCustomKernel<C>
where
C: CallManager,
{
fn compute_unsealed_sector_cid(
&self,
proof_type: RegisteredSealProof,
pieces: &[PieceInfo],
) -> Result<Cid> {
self.0.compute_unsealed_sector_cid(proof_type, pieces)
}
fn verify_post(&self, verify_info: &fvm_shared::sector::WindowPoStVerifyInfo) -> Result<bool> {
self.0.verify_post(verify_info)
}
fn batch_verify_seals(&self, vis: &[SealVerifyInfo]) -> Result<Vec<bool>> {
Ok(vec![true; vis.len()])
}
fn verify_consensus_fault(
&self,
h1: &[u8],
h2: &[u8],
extra: &[u8],
) -> Result<Option<ConsensusFault>> {
let charge = self
.price_list()
.on_verify_consensus_fault(h1.len(), h2.len(), extra.len());
let _ = self.charge_gas(&charge.name, charge.total())?;
Ok(None)
}
fn verify_aggregate_seals(&self, agg: &AggregateSealVerifyProofAndInfos) -> Result<bool> {
let charge = self.price_list().on_verify_aggregate_seals(agg);
let _ = self.charge_gas(&charge.name, charge.total())?;
Ok(true)
}
fn verify_replica_update(&self, rep: &ReplicaUpdateInfo) -> Result<bool> {
let charge = self.price_list().on_verify_replica_update(rep);
let _ = self.charge_gas(&charge.name, charge.total())?;
Ok(true)
}
fn total_fil_circ_supply(&self) -> Result<TokenAmount> {
self.0.total_fil_circ_supply()
}
}
impl<K> SyscallHandler<K> for DefaultCustomKernel<K::CallManager>
where
K: CustomKernel
+ FilecoinKernel
+ ActorOps
+ SendOps
+ UpgradeOps
+ IpldBlockOps
+ CryptoOps
+ DebugOps
+ EventOps
+ MessageOps
+ NetworkOps
+ RandomnessOps
+ SelfOps,
{
fn link_syscalls(linker: &mut Linker<K>) -> anyhow::Result<()> {
DefaultFilecoinKernel::<K::CallManager>::link_syscalls(linker)?;
linker.link_syscall("my_custom_kernel", "my_custom_syscall", my_custom_syscall)?;
Ok(())
}
}
pub fn my_custom_syscall(
context: fvm::syscalls::Context<'_, impl CustomKernel>,
doubleme: i32,
) -> Result<i32> {
context.kernel.my_custom_syscall(doubleme)
}