Skip to content

Commit

Permalink
fix: bind syscalls in conformance tests
Browse files Browse the repository at this point in the history
Unfortunately, I had to drop the generics to prevent some circular type
constraint evaluation issues. This is likely because:

1. `SyscallHandler` is generic over "self".
2. `SyscallHandler<Self>` is only implemented if `Self: FilecoinKernel`.
3. `FilecoinKernel` is only implemented if `Self: SyscallHandler<Self>`.

Rust _can_ figure all of this out if we specify concrete types, but it
can't yet prove this generically.
  • Loading branch information
Stebalien committed Dec 12, 2023
1 parent d1696f0 commit 6b4e7d0
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 34 deletions.
2 changes: 1 addition & 1 deletion fvm/src/kernel/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ pub trait Kernel: GasOps + SyscallHandler<Self> + 'static {
fn limiter_mut(&mut self) -> &mut Self::Limiter;
}

pub trait SyscallHandler<K: Kernel>: Sized {
pub trait SyscallHandler<K>: Sized {
fn bind_syscalls(linker: &mut Linker<InvocationData<K>>) -> anyhow::Result<()>;
}

Expand Down
24 changes: 16 additions & 8 deletions fvm/src/syscalls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ use anyhow::{anyhow, Context as _};
use num_traits::Zero;
use wasmtime::{AsContextMut, ExternType, Global, Linker, Memory, Module, Val};

use crate::call_manager::{backtrace, CallManager};
use crate::call_manager::backtrace;
use crate::gas::{Gas, GasInstant, GasTimer};
use crate::kernel::filecoin::DefaultFilecoinKernel;
use crate::kernel::filecoin::{DefaultFilecoinKernel, FilecoinKernel};
use crate::kernel::{
ActorOps, CryptoOps, DebugOps, EventOps, ExecutionError, GasOps, IpldBlockOps, MessageOps,
NetworkOps, RandomnessOps, SelfOps, SyscallHandler,
Expand Down Expand Up @@ -329,14 +329,22 @@ where
}
}

impl<C> SyscallHandler<DefaultFilecoinKernel<C>> for DefaultFilecoinKernel<C>
impl<K> SyscallHandler<K> for DefaultFilecoinKernel<K::CallManager>
where
C: CallManager,
K: FilecoinKernel
+ ActorOps
+ IpldBlockOps
+ CryptoOps
+ DebugOps
+ EventOps
+ GasOps
+ MessageOps
+ NetworkOps
+ RandomnessOps
+ SelfOps,
{
fn bind_syscalls(
linker: &mut Linker<InvocationData<DefaultFilecoinKernel<C>>>,
) -> anyhow::Result<()> {
DefaultKernel::<C>::bind_syscalls(linker)?;
fn bind_syscalls(linker: &mut Linker<InvocationData<K>>) -> anyhow::Result<()> {
DefaultKernel::<K::CallManager>::bind_syscalls(linker)?;

// Bind the circulating supply call.
linker.bind(
Expand Down
37 changes: 12 additions & 25 deletions testing/conformance/src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ where
}
}

type InnerTestKernel = DefaultFilecoinKernel<DefaultCallManager<TestMachine>>;

/// A kernel for intercepting syscalls.
// TestKernel is coupled to TestMachine because it needs to use that to plumb the
// TestData through when it's destroyed into a CallManager then recreated by that CallManager.
Expand All @@ -169,16 +171,11 @@ where
#[delegate(NetworkOps)]
#[delegate(RandomnessOps)]
#[delegate(SelfOps)]
pub struct TestKernel<K = DefaultFilecoinKernel<DefaultCallManager<TestMachine>>>(pub K);
pub struct TestKernel(pub InnerTestKernel);

impl<M, C, K> Kernel for TestKernel<K>
where
M: Machine,
C: CallManager<Machine = TestMachine<M>>,
K: Kernel<CallManager = C>,
{
type CallManager = K::CallManager;
type Limiter = K::Limiter;
impl Kernel for TestKernel {
type CallManager = <InnerTestKernel as Kernel>::CallManager;
type Limiter = <InnerTestKernel as Kernel>::Limiter;

fn into_inner(self) -> (Self::CallManager, BlockRegistry)
where
Expand All @@ -188,7 +185,7 @@ where
}

fn new(
mgr: C,
mgr: Self::CallManager,
blocks: BlockRegistry,
caller: ActorID,
actor_id: ActorID,
Expand All @@ -199,7 +196,7 @@ where
where
Self: Sized,
{
TestKernel(K::new(
TestKernel(InnerTestKernel::new(
mgr,
blocks,
caller,
Expand Down Expand Up @@ -240,23 +237,13 @@ where
}
}

impl<M, C, K> SyscallHandler<TestKernel<K>> for TestKernel<K>
where
M: Machine,
C: CallManager<Machine = TestMachine<M>>,
K: Kernel<CallManager = C>,
{
fn bind_syscalls(_linker: &mut Linker<InvocationData<TestKernel<K>>>) -> anyhow::Result<()> {
Ok(())
impl SyscallHandler<TestKernel> for TestKernel {
fn bind_syscalls(linker: &mut Linker<InvocationData<TestKernel>>) -> anyhow::Result<()> {
InnerTestKernel::bind_syscalls(linker)
}
}

impl<M, C, K> FilecoinKernel for TestKernel<K>
where
M: Machine,
C: CallManager<Machine = TestMachine<M>>,
K: FilecoinKernel<CallManager = C>,
{
impl FilecoinKernel for TestKernel {
fn compute_unsealed_sector_cid(
&self,
proof_type: RegisteredSealProof,
Expand Down

0 comments on commit 6b4e7d0

Please sign in to comment.