Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

High-level type signatures for imports and exports in the Miden package #354

Open
greenhat opened this issue Nov 14, 2024 · 0 comments
Open
Assignees
Milestone

Comments

@greenhat
Copy link
Contributor

greenhat commented Nov 14, 2024

Discovered in #353
Ref #346

Why

We need high-level type signatures for linking and cross-context calls to generate lifting and lowering functions for the Miden ABI.
Let's consider the following example:

WIT:

process-list-felt: func(input: list<felt>) -> list<felt>;

Which generates the following Rust bindings:

#[doc(hidden)]
#[allow(non_snake_case)]
pub unsafe fn _export_process_list_felt_cabi<T: Guest>(
    arg0: *mut u8,
    arg1: usize,
) -> *mut u8 {
    #[cfg(target_arch = "wasm32")] _rt::run_ctors_once();
    let len0 = arg1;
    let result1 = T::process_list_felt(
        _rt::Vec::from_raw_parts(arg0.cast(), len0, len0),
    );
    let ptr2 = _RET_AREA.0.as_mut_ptr().cast::<u8>();
    let vec3 = (result1).into_boxed_slice();
    let ptr3 = vec3.as_ptr().cast::<u8>();
    let len3 = vec3.len();
    ::core::mem::forget(vec3);
    *ptr2.add(4).cast::<usize>() = len3;
    *ptr2.add(0).cast::<*mut u8>() = ptr3.cast_mut();
    ptr2
}
#[doc(hidden)]
#[allow(non_snake_case)]
pub unsafe fn __post_return_process_list_felt<T: Guest>(arg0: *mut u8) {
    let l0 = *arg0.add(0).cast::<*mut u8>();
    let l1 = *arg0.add(4).cast::<usize>();
    let base2 = l0;
    let len2 = l1;
    _rt::cabi_dealloc(base2, len2 * 4, 4);
}
pub trait Guest {
    fn process_list_felt(
        input: _rt::Vec<miden::Felt>,
    ) -> _rt::Vec<miden::Felt>;
}

We need to generate lowering and lifting functions for the cross-context calls when process-list-felt
is called from a different package(context).

The process should look like this:

  1. Store the bytes from the caller's memory (pointed by arg0) into the advice provider;
  2. Allocate in the callee memory via callee's exported cabi_realloc and load bytes from the advice
    provider into the callee's(export_process_list_felt_cabi) memory;
  3. Call callee's export function (export_process_list_felt_cabi) passing the pointer to the bytes loaded
    from the advice provider in step 2;
  4. Store the results (returned via a pointer ptr2) into the advice provider;
  5. Release the callee memory allocated for the result by calling post_return_process_list_felt(ptr2);
  6. Allocate and load the bytes from the advice provider into the caller's memory;
  7. Return the pointer to the bytes loaded from the advice provider in step 5 to the caller.

Suggested solution

To store and load bytes to/from the advice provider, we need to provide a high-level type signatures to calculate the byte size of the data to be stored and loaded.
Since we only can do both allocation (step and 6) when linking the caller (we have callee's cabi_realloc exported from their component) we cannot generate the lowering and lifting functions at the time of the caller's compilation.

Alternatives

We will have WIT binary stored in Miden package to use it as a dependency in a Rust project. We could try to parse high-level type signatures from the WIT binary, but we would need to find corresponding low-level Miden package exports and imports (which we don't have BTW) by name, which is error-prone.

Pinging @bitwalker

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant