-
Notifications
You must be signed in to change notification settings - Fork 5
Add wasmi recipe #20
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
Add wasmi recipe #20
Changes from all commits
bfcfb81
60e1eb7
79816ad
5884aba
fa0e5c1
d0cfa54
0369540
d022e16
c2713bc
dbc61d2
4c27f03
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| # Do not update. Maintained by programmability team. | ||
|
|
||
| sources: | ||
| "0.42.1": | ||
| url: https://github.com/wasmi-labs/wasmi/archive/refs/tags/v0.42.1.tar.gz | ||
| sha256: 2a5697be33c7afce8f671af4a5a3621d9e93ce55d253d31bd8201458e465fbb8 | ||
| patches: | ||
| "0.42.1": | ||
| - patch_file: "patches/0001-xrplf-0.42.1.patch" | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be much more clear to have 3 patches (as I explained above).
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This patch is inseparable set of changes required to integrate into rippled. You can't create separate patches as the rippled project will be in broken state. This patch created by several people and is a sync point for them. The only thing that can be separated is version, but it is really only refactoring change which is not necessary to put it into individual patch.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not telling them not to apply them, but they are changing different things, and represent different features/problems which are needed to make it work for xrplf, so they should be kept as separate patches
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This patch fix only 1 problem - integration to the rippled. That its only purpose. As you can see there are no changes, or fixes to the original code.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @bthomee could you please take a look here? |
||
| patch_description: Integrate wasmi lib into smart-escrow. | ||
| patch_type: conan | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| from conan import ConanFile, tools | ||
| from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout | ||
| from conan.tools.files import apply_conandata_patches, export_conandata_patches, get | ||
| import os | ||
|
|
||
| required_conan_version = ">=2.0.0" | ||
|
|
||
| class WasmiConan(ConanFile): | ||
| name = "wasmi" | ||
| license = "Apache License v2.0" | ||
| url = "https://github.com/wasmi-labs/wasmi.git" | ||
| description = "WebAssembly (Wasm) interpreter" | ||
| package_type = "library" | ||
| settings = "os", "arch", "compiler", "build_type" | ||
| options = {"shared": [False]} | ||
| default_options = {"shared": False} | ||
mathbunnyru marked this conversation as resolved.
Show resolved
Hide resolved
Comment on lines
+15
to
+16
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Most recipes I've seen have options for
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fpic is only for exe/shared libs |
||
|
|
||
| def export_sources(self): | ||
| export_conandata_patches(self) | ||
|
|
||
| def layout(self): | ||
| cmake_layout(self, src_folder="src") | ||
|
|
||
| def source(self): | ||
| get(self, **self.conan_data["sources"][self.version], strip_root=True) | ||
| apply_conandata_patches(self) | ||
|
|
||
| def generate(self): | ||
| tc = CMakeToolchain(self) | ||
| tc.generate() | ||
|
|
||
| def build(self): | ||
| cmake = CMake(self) | ||
| cmake.configure(build_script_folder=os.path.join(self.source_folder, "crates", "c_api")) | ||
| cmake.build() | ||
|
|
||
| def package(self): | ||
| cmake = CMake(self) | ||
| cmake.install() | ||
|
|
||
| def package_info(self): | ||
| self.cpp_info.libs = ["wasmi"] | ||
bthomee marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,287 @@ | ||
| diff --git a/crates/c_api/CMakeLists.txt b/crates/c_api/CMakeLists.txt | ||
| index b15c787..54eaed2 100644 | ||
| --- a/crates/c_api/CMakeLists.txt | ||
| +++ b/crates/c_api/CMakeLists.txt | ||
| @@ -6,6 +6,8 @@ option(BUILD_SHARED_LIBS "Build using shared libraries" OFF) | ||
| option(WASMI_ALWAYS_BUILD "If cmake should always invoke cargo to build Wasmi" ON) | ||
| set(WASMI_TARGET "" CACHE STRING "Rust target to build for") | ||
|
|
||
| +add_compile_definitions(COMPILING_WASM_RUNTIME_API=1) | ||
| + | ||
| if(NOT WASMI_TARGET) | ||
| execute_process( | ||
| COMMAND rustc -vV | ||
| @@ -43,6 +45,10 @@ endif() | ||
| list(TRANSFORM WASMI_SHARED_FILES PREPEND ${WASMI_TARGET_DIR}/) | ||
| list(TRANSFORM WASMI_STATIC_FILES PREPEND ${WASMI_TARGET_DIR}/) | ||
|
|
||
| +if(NOT BUILD_SHARED_LIBS) | ||
| + set(WASMI_SHARED_FILES) | ||
| +endif() | ||
| + | ||
| # Instructions on how to build and install the Wasmi Rust crate. | ||
| find_program(WASMI_CARGO_BINARY cargo REQUIRED) | ||
| include(ExternalProject) | ||
| @@ -79,7 +85,6 @@ else() | ||
| target_link_libraries(wasmi INTERFACE ${WASMI_STATIC_FILES}) | ||
|
|
||
| if(WASMI_TARGET MATCHES "windows") | ||
| - target_compile_options(wasmi INTERFACE -DWASM_API_EXTERN= -DWASI_API_EXTERN=) | ||
| target_link_libraries(wasmi INTERFACE ws2_32 advapi32 userenv ntdll shell32 ole32 bcrypt) | ||
| elseif(NOT WASMI_TARGET MATCHES "darwin") | ||
| target_link_libraries(wasmi INTERFACE pthread dl m) | ||
| @@ -112,6 +117,7 @@ install( | ||
| DESTINATION ${CMAKE_INSTALL_LIBDIR} | ||
| ) | ||
|
|
||
| +if(BUILD_SHARED_LIBS) | ||
mathbunnyru marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if(WASMI_TARGET MATCHES "darwin") | ||
| set(INSTALLED_LIB "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/libwasmi.dylib") | ||
| install( | ||
| @@ -131,6 +137,7 @@ if(WASMI_TARGET MATCHES "darwin") | ||
| install(CODE "execute_process(COMMAND ${install_name_tool_cmd})") | ||
| endif() | ||
| endif() | ||
| +endif() | ||
|
|
||
| # Documentation Generation via Doxygen: | ||
| set(DOXYGEN_CONF_IN ${CMAKE_CURRENT_SOURCE_DIR}/doxygen.conf.in) | ||
| @@ -141,19 +148,3 @@ add_custom_target(doc | ||
| DEPENDS ${WASMI_GENERATED_CONF_H} ${DOXYGEN_CONF_OUT} | ||
| WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} | ||
| ) | ||
| - | ||
| -# C-Header Formatting via clang-format: | ||
mathbunnyru marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| -find_program(CLANG_FORMAT clang-format REQUIRED) | ||
| -file(GLOB_RECURSE HEADER_FILES | ||
| - ${CMAKE_CURRENT_SOURCE_DIR}/include/wasmi.h | ||
| - ${CMAKE_CURRENT_SOURCE_DIR}/include/wasmi/*.h | ||
| - ${CMAKE_CURRENT_SOURCE_DIR}/include/wasmi/*.hh | ||
| -) | ||
| -add_custom_target(check-format | ||
| - COMMAND ${CLANG_FORMAT} -style=llvm -Werror --dry-run ${HEADER_FILES} | ||
| - COMMENT "clang-format: Check formatting for Wasmi C-API header files" | ||
| -) | ||
| -add_custom_target(format | ||
| - COMMAND ${CLANG_FORMAT} -style=llvm -i ${HEADER_FILES} | ||
| - COMMENT "clang-format: Apply formatting rules for Wasmi C-API header files" | ||
| -) | ||
| diff --git a/crates/c_api/include/wasm.h b/crates/c_api/include/wasm.h | ||
oleks-rip marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| index 5ee617f..a76f10e 100644 | ||
| --- a/crates/c_api/include/wasm.h | ||
| +++ b/crates/c_api/include/wasm.h | ||
| @@ -13,11 +13,17 @@ | ||
| #include <assert.h> | ||
|
|
||
| #ifndef WASM_API_EXTERN | ||
| -#if defined(_WIN32) && !defined(__MINGW32__) && !defined(LIBWASM_STATIC) | ||
| +#if defined(_MSC_BUILD) | ||
| +#if defined(COMPILING_WASM_RUNTIME_API) | ||
| +#define WASM_API_EXTERN __declspec(dllexport) | ||
| +#elif defined(_DLL) | ||
| #define WASM_API_EXTERN __declspec(dllimport) | ||
| #else | ||
| #define WASM_API_EXTERN | ||
| #endif | ||
| +#else | ||
| +#define WASM_API_EXTERN | ||
| +#endif | ||
| #endif | ||
|
|
||
| #ifdef __cplusplus | ||
| @@ -145,7 +151,13 @@ WASM_API_EXTERN own wasm_engine_t* wasm_engine_new_with_config(own wasm_config_t | ||
| WASM_DECLARE_OWN(store) | ||
|
|
||
| WASM_API_EXTERN own wasm_store_t* wasm_store_new(wasm_engine_t*); | ||
| +WASM_API_EXTERN own wasm_store_t* wasm_store_new_with_memory_max_pages(wasm_engine_t*, uint32_t max_pages); | ||
| + | ||
| +// Store fuel functions (forward declarations) | ||
| +struct wasmi_error; | ||
|
|
||
| +WASM_API_EXTERN struct wasmi_error* wasm_store_get_fuel(const wasm_store_t*, uint64_t* fuel); | ||
| +WASM_API_EXTERN struct wasmi_error* wasm_store_set_fuel(wasm_store_t*, uint64_t fuel); | ||
|
|
||
| /////////////////////////////////////////////////////////////////////////////// | ||
| // Type Representations | ||
| diff --git a/crates/c_api/include/wasmi.h b/crates/c_api/include/wasmi.h | ||
oleks-rip marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| index 2caffa3..0c0584e 100644 | ||
| --- a/crates/c_api/include/wasmi.h | ||
| +++ b/crates/c_api/include/wasmi.h | ||
| @@ -10,7 +10,7 @@ | ||
| /** | ||
| * \brief Wasmi version string. | ||
| */ | ||
| -#define WASMI_VERSION "0.35.0" | ||
| +#define WASMI_VERSION "0.42.1" | ||
| /** | ||
| * \brief Wasmi major version number. | ||
| */ | ||
| @@ -18,10 +18,10 @@ | ||
| /** | ||
| * \brief Wasmi minor version number. | ||
| */ | ||
| -#define WASMI_VERSION_MINOR 35 | ||
| +#define WASMI_VERSION_MINOR 42 | ||
| /** | ||
| * \brief Wasmi patch version number. | ||
| */ | ||
| -#define WASMI_VERSION_PATCH 0 | ||
| +#define WASMI_VERSION_PATCH 1 | ||
|
|
||
| #endif // WASMI_H | ||
| diff --git a/crates/c_api/src/store.rs b/crates/c_api/src/store.rs | ||
| index 56d4898..9abda8e 100644 | ||
| --- a/crates/c_api/src/store.rs | ||
| +++ b/crates/c_api/src/store.rs | ||
| @@ -1,7 +1,7 @@ | ||
| use crate::{wasm_engine_t, wasmi_error_t, ForeignData}; | ||
| use alloc::{boxed::Box, sync::Arc}; | ||
| use core::{cell::UnsafeCell, ffi}; | ||
| -use wasmi::{AsContext, AsContextMut, Store, StoreContext, StoreContextMut}; | ||
| +use wasmi::{AsContext, AsContextMut, Store, StoreContext, StoreContextMut, StoreLimits, StoreLimitsBuilder}; | ||
|
|
||
| /// This representation of a `Store` is used to implement the `wasm.h` API (and | ||
| /// *not* the `wasmi.h` API!) | ||
| @@ -16,7 +16,7 @@ use wasmi::{AsContext, AsContextMut, Store, StoreContext, StoreContextMut}; | ||
| /// least Wasmi's implementation). | ||
| #[derive(Clone)] | ||
| pub struct WasmStoreRef { | ||
| - inner: Arc<UnsafeCell<Store<()>>>, | ||
| + inner: Arc<UnsafeCell<Store<StoreLimits>>>, | ||
| } | ||
|
|
||
| impl WasmStoreRef { | ||
| @@ -27,7 +27,7 @@ impl WasmStoreRef { | ||
| /// # Safety | ||
| /// | ||
| /// It is the callers responsibility to provide a valid `self`. | ||
| - pub unsafe fn context(&self) -> StoreContext<'_, ()> { | ||
| + pub unsafe fn context(&self) -> StoreContext<'_, StoreLimits> { | ||
| (*self.inner.get()).as_context() | ||
| } | ||
|
|
||
| @@ -38,7 +38,7 @@ impl WasmStoreRef { | ||
| /// # Safety | ||
| /// | ||
| /// It is the callers responsibility to provide a valid `self`. | ||
| - pub unsafe fn context_mut(&mut self) -> StoreContextMut<'_, ()> { | ||
| + pub unsafe fn context_mut(&mut self) -> StoreContextMut<'_, StoreLimits> { | ||
| (*self.inner.get()).as_context_mut() | ||
| } | ||
| } | ||
| @@ -56,17 +56,71 @@ pub struct wasm_store_t { | ||
|
|
||
| wasmi_c_api_macros::declare_own!(wasm_store_t); | ||
|
|
||
| -/// Creates a new [`Store<()>`](wasmi::Store) for the given `engine`. | ||
| +/// Creates a new [`Store<StoreLimits>`](wasmi::Store) for the given `engine`. | ||
| +/// | ||
| +/// The store is created with no resource limits (original behavior). | ||
| +/// For memory-limited stores, use [`wasm_store_new_with_memory_max_pages`]. | ||
| /// | ||
| /// The returned [`wasm_store_t`] must be freed using [`wasm_store_delete`]. | ||
| /// | ||
| -/// Wraps [`<wasmi::Store<()>>::new`](wasmi::Store::new). | ||
| +/// Wraps [`<wasmi::Store<StoreLimits>>::new`](wasmi::Store::new). | ||
| #[cfg_attr(not(feature = "prefix-symbols"), no_mangle)] | ||
| #[allow(clippy::arc_with_non_send_sync)] | ||
| #[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)] | ||
| pub extern "C" fn wasm_store_new(engine: &wasm_engine_t) -> Box<wasm_store_t> { | ||
| let engine = &engine.inner; | ||
| - let store = Store::new(engine, ()); | ||
| + | ||
| + // Create store with no resource limits (original behavior) | ||
| + let limits = StoreLimitsBuilder::new().build(); | ||
| + let store = Store::new(engine, limits); | ||
| + | ||
| + Box::new(wasm_store_t { | ||
| + inner: WasmStoreRef { | ||
| + inner: Arc::new(UnsafeCell::new(store)), | ||
| + }, | ||
| + }) | ||
| +} | ||
| + | ||
| +/// Creates a new [`Store<StoreLimits>`](wasmi::Store) for the given `engine` with memory limits. | ||
| +/// | ||
| +/// This function creates a store with resource limits suitable for blockchain smart contracts. | ||
| +/// The memory limit is enforced during WebAssembly execution. | ||
| +/// | ||
| +/// If `max_pages` exceeds 1024 (64MB), this function will panic. | ||
| +/// | ||
| +/// The returned [`wasm_store_t`] must be freed using [`wasm_store_delete`]. | ||
| +/// | ||
| +/// Wraps [`<wasmi::Store<StoreLimits>>::new`](wasmi::Store::new). | ||
| +#[cfg_attr(not(feature = "prefix-symbols"), no_mangle)] | ||
| +#[allow(clippy::arc_with_non_send_sync)] | ||
| +#[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)] | ||
| +pub extern "C" fn wasm_store_new_with_memory_max_pages( | ||
| + engine: &wasm_engine_t, | ||
| + max_pages: u32, | ||
| +) -> Box<wasm_store_t> { | ||
| + // Validate max_pages limit (64MB = 1024 pages) | ||
| + if max_pages > 1024 { | ||
| + panic!("max_pages ({}) exceeds maximum allowed value of 1024 pages (64MB)", max_pages); | ||
| + } | ||
| + | ||
| + // Convert pages to bytes (each page is 64KB) | ||
| + let max_memory_bytes = (max_pages as usize) * (64 * 1024); | ||
| + | ||
| + // Create store limits with blockchain-suitable defaults | ||
| + let limits = StoreLimitsBuilder::new() | ||
| + .memory_size(max_memory_bytes) // User-specified memory limit | ||
| + .instances(1) // Single instance for blockchain | ||
| + .tables(1) // Single table for blockchain | ||
| + .memories(1) // Single memory for blockchain | ||
| + .table_elements(64) // Limited table elements for blockchain | ||
| + .trap_on_grow_failure(false) // Return -1 on growth failure instead of trapping | ||
| + .build(); | ||
| + | ||
| + let mut store = Store::new(&engine.inner, limits); | ||
| + | ||
| + // Install the resource limiter | ||
| + store.limiter(|limits| limits); | ||
| + | ||
| Box::new(wasm_store_t { | ||
| inner: WasmStoreRef { | ||
| inner: Arc::new(UnsafeCell::new(store)), | ||
| @@ -175,3 +229,40 @@ pub extern "C" fn wasmi_context_set_fuel( | ||
| ) -> Option<Box<wasmi_error_t>> { | ||
| crate::handle_result(store.set_fuel(fuel), |()| {}) | ||
| } | ||
| + | ||
| +//////////////////////////////////////////////////////////////////////////////////////// | ||
| +//////////////////////////////////////////////////////////////////////////////////////// | ||
| + | ||
| +/// Returns the current fuel of the wasm store context in `fuel`. | ||
| +/// | ||
| +/// Wraps [`Store::get_fuel`]. | ||
| +/// | ||
| +/// # Errors | ||
| +/// | ||
| +/// If [`Store::get_fuel`] errors. | ||
| +#[no_mangle] | ||
| +pub extern "C" fn wasm_store_get_fuel( | ||
| + store: &wasm_store_t, | ||
| + fuel: &mut u64, | ||
| +) -> Option<Box<wasmi_error_t>> { | ||
| + let context = unsafe { store.inner.context() }; | ||
| + crate::handle_result(context.get_fuel(), |amt| { | ||
| + *fuel = amt; | ||
| + }) | ||
| +} | ||
| + | ||
| +/// Sets the current fuel of the wasm store context to `fuel`. | ||
| +/// | ||
| +/// Wraps [`Store::set_fuel`]. | ||
| +/// | ||
| +/// # Errors | ||
| +/// | ||
| +/// If [`Store::set_fuel`] errors. | ||
| +#[no_mangle] | ||
| +pub extern "C" fn wasm_store_set_fuel( | ||
| + store: &mut wasm_store_t, | ||
| + fuel: u64, | ||
| +) -> Option<Box<wasmi_error_t>> { | ||
| + let mut context = unsafe { store.inner.context_mut() }; | ||
| + crate::handle_result(context.set_fuel(fuel), |()| {}) | ||
| +} | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| versions: | ||
| "0.42.1": | ||
| folder: all |
Uh oh!
There was an error while loading. Please reload this page.