From b9d9d6e4a05da777cd7dd2cdfb49cf12cfd8b04b Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Fri, 1 May 2026 23:09:59 +0300 Subject: [PATCH 01/10] feat(workspace): add global separation of syscall kind --- core/backend/src/env.rs | 10 +-- core/backend/src/lib.rs | 61 +++++++++++-------- core/processor/src/common.rs | 4 +- core/processor/src/context.rs | 5 +- core/processor/src/executor.rs | 6 +- core/processor/src/processing.rs | 1 + core/src/code/mod.rs | 12 +++- core/src/code/utils.rs | 4 +- ethexe/runtime/common/src/lib.rs | 49 +++++++-------- ethexe/runtime/src/wasm/api/instrument.rs | 3 +- examples/async-init/Cargo.toml | 2 +- examples/async/Cargo.toml | 2 +- examples/ctor/Cargo.toml | 2 +- examples/panic-payload/Cargo.toml | 2 +- examples/piggy-bank/Cargo.toml | 2 +- examples/ping/Cargo.toml | 2 +- examples/reply-callback/Cargo.toml | 2 +- examples/syscalls-ethexe/Cargo.toml | 2 +- examples/value-sender-ethexe/Cargo.toml | 2 +- gcore/src/exec.rs | 5 +- gcore/src/lib.rs | 1 + gcore/src/prog.rs | 1 - gstd/src/lib.rs | 1 + gstd/src/prog/basic.rs | 2 - gstd/src/prog/encoded.rs | 2 - gstd/src/prog/generator.rs | 4 -- gsys/src/lib.rs | 3 + gtest/Cargo.toml | 4 ++ gtest/src/lib.rs | 12 ++++ gtest/src/manager/block_exec.rs | 3 +- gtest/src/manager/memory.rs | 3 +- gtest/src/program.rs | 3 +- pallets/gear/src/benchmarking/mod.rs | 18 +++--- pallets/gear/src/benchmarking/utils.rs | 4 +- pallets/gear/src/lib.rs | 7 ++- pallets/gear/src/queue.rs | 10 ++- pallets/gear/src/runtime_api.rs | 5 +- pallets/gear/src/tests.rs | 6 ++ utils/calc-stack-height/src/main.rs | 3 +- utils/wasm-builder/Cargo.toml | 4 ++ utils/wasm-builder/src/code_validator.rs | 8 +-- utils/wasm-builder/src/lib.rs | 9 +++ .../wasm-gen/src/config/syscalls/injection.rs | 8 +-- utils/wasm-gen/src/generator.rs | 9 ++- .../src/generator/syscalls/imports.rs | 26 ++++++-- utils/wasm-gen/src/tests.rs | 8 ++- utils/wasm-instrument/src/syscalls.rs | 5 +- 47 files changed, 226 insertions(+), 121 deletions(-) diff --git a/core/backend/src/env.rs b/core/backend/src/env.rs index c00041c034c..3ec643dd58a 100644 --- a/core/backend/src/env.rs +++ b/core/backend/src/env.rs @@ -43,8 +43,8 @@ use gear_sandbox::{ default_executor::{EnvironmentDefinitionBuilder, Instance, Store}, }; use gear_wasm_instrument::{ - GLOBAL_NAME_GAS, - syscalls::SyscallName::{self, *}, + GLOBAL_NAME_GAS, SyscallKind, + SyscallName::{self, *}, }; #[cfg(feature = "std")] use { @@ -162,7 +162,8 @@ where EntryPoint: WasmEntryPoint, { #[rustfmt::skip] - fn bind_funcs(builder: &mut EnvBuilder) { + fn bind_funcs(builder: &mut EnvBuilder, _syscall_kind: SyscallKind) { + // FIXME: do not bind all syscalls here macro_rules! add_function { ($syscall:ident, $func:ident) => { builder.add_func($syscall, wrap_syscall!($func, $syscall)); @@ -271,6 +272,7 @@ where entry_point: EntryPoint, entries: BTreeSet, mem_size: WasmPagesAmount, + syscall_kind: SyscallKind, ) -> Result { use EnvironmentError::*; use SystemEnvironmentError::*; @@ -290,7 +292,7 @@ where builder.add_memory(memory.clone()); - Self::bind_funcs(&mut builder); + Self::bind_funcs(&mut builder, syscall_kind); // Check that we have implementations for all the syscalls. // This is intended to panic during any testing, when the diff --git a/core/backend/src/lib.rs b/core/backend/src/lib.rs index e98ec059e2f..451821b66a9 100644 --- a/core/backend/src/lib.rs +++ b/core/backend/src/lib.rs @@ -74,34 +74,43 @@ mod tests { .with_test_writer() .init(); - // Make module with one empty function. - let mut module = ModuleBuilder::default(); - module.add_func(FuncType::new([], []), Function::default()); - - // Insert syscalls imports. - for name in SyscallName::instrumentable(SyscallKind::Vara) { - let sign = name.signature(); - let type_no = module.push_type(sign.func_type()); - - module.push_import(Import::func("env", name.to_str(), type_no)); - } - - let module = InstrumentationBuilder::new("env") - .with_gas_limiter(|_| CustomConstantCostRules::default()) - .instrument(module.build()) + for syscall_kind in [SyscallKind::Vara, SyscallKind::Eth] { + // Make module with one empty function. + let mut module = ModuleBuilder::default(); + module.add_func(FuncType::new([], []), Function::default()); + + // Insert syscalls imports. + for name in SyscallName::instrumentable(syscall_kind) { + let sign = name.signature(); + let type_no = module.push_type(sign.func_type()); + + module.push_import(Import::func("env", name.to_str(), type_no)); + } + + let module = InstrumentationBuilder::new("env") + .with_gas_limiter(|_| CustomConstantCostRules::default()) + .instrument(module.build()) + .unwrap(); + let code = module.serialize().unwrap(); + + // Execute wasm and check success. + let ext = MockExt::default(); + let env = Environment::new( + ext, + &code, + DispatchKind::Init, + Default::default(), + 0.into(), + syscall_kind, + ) .unwrap(); - let code = module.serialize().unwrap(); - - // Execute wasm and check success. - let ext = MockExt::default(); - let env = - Environment::new(ext, &code, DispatchKind::Init, Default::default(), 0.into()).unwrap(); - let report = env.execute(|_, _, _| {}).unwrap(); + let report = env.execute(|_, _, _| {}).unwrap(); - let BackendReport { - termination_reason, .. - } = report; + let BackendReport { + termination_reason, .. + } = report; - assert_eq!(termination_reason, ActorTerminationReason::Success.into()); + assert_eq!(termination_reason, ActorTerminationReason::Success.into()); + } } } diff --git a/core/processor/src/common.rs b/core/processor/src/common.rs index 057e1f254e8..05ff6706f54 100644 --- a/core/processor/src/common.rs +++ b/core/processor/src/common.rs @@ -22,7 +22,7 @@ use crate::{context::SystemReservationContext, precharge::PreChargeGasOperation} use actor_system_error::actor_system_error; use alloc::{collections::BTreeMap, string::String, vec::Vec}; use gear_core::{ - code::{CodeMetadata, InstrumentedCode}, + code::{CodeMetadata, InstrumentedCode, SyscallKind}, env::MessageWaitedType, gas::{GasAllowanceCounter, GasAmount, GasCounter}, ids::{ActorId, CodeId, MessageId, ReservationId}, @@ -542,4 +542,6 @@ pub(crate) struct WasmExecutionContext { pub program: Program, /// Size of the memory block. pub memory_size: WasmPagesAmount, + /// What kind of syscall is being executed (Vara or Vara.ETH). + pub syscall_kind: SyscallKind, } diff --git a/core/processor/src/context.rs b/core/processor/src/context.rs index 57dd9c2661a..4ffc04a5256 100644 --- a/core/processor/src/context.rs +++ b/core/processor/src/context.rs @@ -23,7 +23,7 @@ use crate::{ precharge::{ContextCharged, ForModuleInstantiation}, }; use gear_core::{ - code::InstrumentedCodeAndMetadata, + code::{InstrumentedCodeAndMetadata, SyscallKind}, gas::{GasAllowanceCounter, GasCounter}, ids::ActorId, message::IncomingDispatch, @@ -41,6 +41,7 @@ pub struct ProcessExecutionContext { pub(crate) balance: u128, pub(crate) program: Program, pub(crate) memory_size: WasmPagesAmount, + pub(crate) syscall_kind: SyscallKind, } impl ProcessExecutionContext { @@ -49,6 +50,7 @@ impl ProcessExecutionContext { context: ContextCharged, instrumented_code_and_metadata: InstrumentedCodeAndMetadata, balance: u128, + syscall_kind: SyscallKind, ) -> Self { let ( destination_id, @@ -82,6 +84,7 @@ impl ProcessExecutionContext { balance, program, memory_size: allocations_data.memory_size, + syscall_kind, } } diff --git a/core/processor/src/executor.rs b/core/processor/src/executor.rs index 0f2a9a126f9..97c989d1f44 100644 --- a/core/processor/src/executor.rs +++ b/core/processor/src/executor.rs @@ -26,7 +26,7 @@ use crate::{ }; use alloc::{format, string::String, vec::Vec}; use gear_core::{ - code::{CodeMetadata, InstrumentedCode}, + code::{CodeMetadata, InstrumentedCode, SyscallKind}, env::{Externalities, WasmEntryPoint}, gas::{GasAllowanceCounter, GasCounter, ValueCounter}, ids::ActorId, @@ -66,6 +66,7 @@ where gas_reserver, program, memory_size, + syscall_kind, } = context; // TODO: consider avoiding cloning here. @@ -135,6 +136,7 @@ where kind, program.code_metadata.exports().clone(), memory_size, + syscall_kind, )?; env.execute(|ctx, memory, globals_config| { Ext::lazy_pages_init_for_program( @@ -252,6 +254,7 @@ pub fn execute_for_reply( payload: Vec, gas_limit: u64, block_info: BlockInfo, + syscall_kind: SyscallKind, ) -> Result, String> where Ext: ProcessorExternalities + BackendExternalities + Send + 'static, @@ -334,6 +337,7 @@ where function, program.code_metadata.exports().clone(), memory_size, + syscall_kind, )?; env.execute(|ctx, memory, globals_config| { Ext::lazy_pages_init_for_program( diff --git a/core/processor/src/processing.rs b/core/processor/src/processing.rs index 91827ca34e8..bb28d8c726a 100644 --- a/core/processor/src/processing.rs +++ b/core/processor/src/processing.rs @@ -99,6 +99,7 @@ where gas_reserver: execution_context.gas_reserver, program: execution_context.program, memory_size: execution_context.memory_size, + syscall_kind: execution_context.syscall_kind, }; // Sending fee: double write cost for addition and removal some time soon diff --git a/core/src/code/mod.rs b/core/src/code/mod.rs index 88aac3a6639..7564582c956 100644 --- a/core/src/code/mod.rs +++ b/core/src/code/mod.rs @@ -31,6 +31,7 @@ mod metadata; mod utils; pub use errors::*; +pub use gear_wasm_instrument::SyscallKind; pub use instrumented::*; pub use metadata::*; pub use utils::{ALLOWED_EXPORTS, MAX_WASM_PAGES_AMOUNT, REQUIRED_EXPORTS}; @@ -73,6 +74,8 @@ pub struct TryNewCodeConfig { pub check_table_section: bool, /// Make wasmparser validation pub make_validation: bool, + /// Syscall kind for imports check + pub syscall_kind: SyscallKind, } impl TryNewCodeConfig { @@ -103,6 +106,7 @@ impl Default for TryNewCodeConfig { check_data_section: true, check_table_section: true, make_validation: true, + syscall_kind: SyscallKind::default(), } } } @@ -161,7 +165,7 @@ impl Code { utils::check_exports(&module)?; } if config.check_imports { - utils::check_imports(&module)?; + utils::check_imports(&module, config.syscall_kind)?; } if let Some(limit) = config.type_section_params_per_type_limit { utils::check_type_section(&module, limit)?; @@ -299,6 +303,7 @@ impl Code { /// ) /// ) /// ``` + #[allow(clippy::too_many_arguments)] pub fn try_new( original_code: Vec, version: u32, @@ -307,6 +312,7 @@ impl Code { data_segments_amount_limit: Option, type_section_len_limit: Option, type_section_params_per_type_limit: Option, + syscall_kind: SyscallKind, ) -> Result where R: Rules, @@ -321,6 +327,7 @@ impl Code { data_segments_amount_limit, type_section_len_limit, type_section_params_per_type_limit, + syscall_kind, ..Default::default() }, ) @@ -454,7 +461,7 @@ mod tests { use crate::{ code::{ Code, CodeError, DataSectionError, ExportError, GENERIC_OS_PAGE_SIZE, ImportError, - StackEndError, TryNewCodeConfig, TypeSectionError, utils::REF_TYPE_SIZE, + StackEndError, SyscallKind, TryNewCodeConfig, TypeSectionError, utils::REF_TYPE_SIZE, }, gas_metering::CustomConstantCostRules, }; @@ -793,6 +800,7 @@ mod tests { None, None, None, + SyscallKind::Vara, ); assert_code_err!(res, CodeError::Validation(_)); diff --git a/core/src/code/utils.rs b/core/src/code/utils.rs index bc100f6adea..59aa8de4c79 100644 --- a/core/src/code/utils.rs +++ b/core/src/code/utils.rs @@ -148,7 +148,7 @@ pub fn check_exports(module: &Module) -> Result<(), CodeError> { .map_err(CodeError::Export) } -pub fn check_imports(module: &Module) -> Result<(), CodeError> { +pub fn check_imports(module: &Module, kind: SyscallKind) -> Result<(), CodeError> { let types = module .type_section .as_ref() @@ -159,7 +159,7 @@ pub fn check_imports(module: &Module) -> Result<(), CodeError> { .as_ref() .ok_or(SectionError::NotFound(SectionName::Import))?; - let syscalls = SyscallName::instrumentable_map(SyscallKind::Vara); + let syscalls = SyscallName::instrumentable_map(kind); let mut visited_imports = BTreeSet::new(); diff --git a/ethexe/runtime/common/src/lib.rs b/ethexe/runtime/common/src/lib.rs index 650ca34408b..58e55e9c97a 100644 --- a/ethexe/runtime/common/src/lib.rs +++ b/ethexe/runtime/common/src/lib.rs @@ -36,7 +36,10 @@ use ethexe_common::{ }; use ext::Ext; use gear_core::{ - code::{CodeMetadata, InstrumentedCode, InstrumentedCodeAndMetadata, MAX_WASM_PAGES_AMOUNT}, + code::{ + CodeMetadata, InstrumentedCode, InstrumentedCodeAndMetadata, MAX_WASM_PAGES_AMOUNT, + SyscallKind, + }, gas::GasAllowanceCounter, gas_metering::Schedule, ids::ActorId, @@ -185,29 +188,26 @@ where let block_config = BlockConfig { block_info: ctx.block_info, forbidden_funcs: [ - // Deprecated - SyscallName::CreateProgramWGas, - SyscallName::ReplyCommitWGas, - SyscallName::ReplyDeposit, - SyscallName::ReplyInputWGas, - SyscallName::ReplyWGas, - SyscallName::ReservationReplyCommit, - SyscallName::ReservationReply, - SyscallName::ReservationSendCommit, - SyscallName::ReservationSend, - SyscallName::ReserveGas, - SyscallName::SendCommitWGas, - SyscallName::SendInputWGas, - SyscallName::SendWGas, - SyscallName::SystemReserveGas, - SyscallName::UnreserveGas, - SyscallName::Wait, - // TBD about deprecation - SyscallName::SignalCode, - SyscallName::SignalFrom, - // Temporary forbidden (unimplemented) - SyscallName::CreateProgram, - SyscallName::Random, + SyscallName::CreateProgramWGas, // Deprecated + SyscallName::CreateProgram, // Unimplemented + SyscallName::ReplyDeposit, // Deprecated + SyscallName::SignalCode, // TBD about deprecation + SyscallName::Random, // Unimplemented + SyscallName::ReplyCommitWGas, // Deprecated + SyscallName::SignalFrom, // TBD about deprecation + SyscallName::ReplyInputWGas, // Deprecated + SyscallName::ReplyWGas, // Deprecated + SyscallName::ReservationReplyCommit, // Deprecated + SyscallName::ReservationReply, // Deprecated + SyscallName::ReservationSendCommit, // Deprecated + SyscallName::ReservationSend, // Deprecated + SyscallName::ReserveGas, // Deprecated + SyscallName::SendCommitWGas, // Deprecated + SyscallName::SendInputWGas, // Deprecated + SyscallName::SendWGas, // Deprecated + SyscallName::SystemReserveGas, // Deprecated + SyscallName::UnreserveGas, // Deprecated + SyscallName::Wait, // Deprecated ] .into(), gas_multiplier: GasMultiplier::from_value_per_gas(100), @@ -457,6 +457,7 @@ where metadata: code_metadata.clone(), }, program_state.balance, + SyscallKind::Eth, ); let random_data = ri.random_data(); diff --git a/ethexe/runtime/src/wasm/api/instrument.rs b/ethexe/runtime/src/wasm/api/instrument.rs index 82a9fce22e3..b36b8ddf5ca 100644 --- a/ethexe/runtime/src/wasm/api/instrument.rs +++ b/ethexe/runtime/src/wasm/api/instrument.rs @@ -18,7 +18,7 @@ use alloc::vec::Vec; use gear_core::{ - code::{Code, CodeError, CodeMetadata, InstrumentedCode}, + code::{Code, CodeError, CodeMetadata, InstrumentedCode, SyscallKind}, gas_metering::Schedule, }; @@ -42,6 +42,7 @@ pub fn instrument_code(original_code: Vec) -> Option<(InstrumentedCode, Code schedule.limits.data_segments_amount.into(), schedule.limits.type_section_len.into(), schedule.limits.parameters.into(), + SyscallKind::Eth, ) .map_err(|e: CodeError| { log::debug!("Failed to validate or instrument code: {e:?}"); diff --git a/examples/async-init/Cargo.toml b/examples/async-init/Cargo.toml index 1b8cb712ef1..e0e78ba68f0 100644 --- a/examples/async-init/Cargo.toml +++ b/examples/async-init/Cargo.toml @@ -20,4 +20,4 @@ gear-wasm-builder.workspace = true debug = ["gstd/debug"] default = ["std"] std = [] -ethexe = ["gstd/ethexe"] +ethexe = ["gstd/ethexe", "gear-wasm-builder/ethexe"] diff --git a/examples/async/Cargo.toml b/examples/async/Cargo.toml index 9e023cfe791..7d70b3c2af7 100644 --- a/examples/async/Cargo.toml +++ b/examples/async/Cargo.toml @@ -19,4 +19,4 @@ gear-wasm-builder.workspace = true debug = ["gstd/debug"] default = ["std"] std = [] -ethexe = ["gstd/ethexe"] +ethexe = ["gstd/ethexe", "gear-wasm-builder/ethexe"] diff --git a/examples/ctor/Cargo.toml b/examples/ctor/Cargo.toml index 004deaf1410..21a40ed9ff1 100644 --- a/examples/ctor/Cargo.toml +++ b/examples/ctor/Cargo.toml @@ -21,4 +21,4 @@ gear-wasm-builder.workspace = true debug = ["gstd/debug"] default = ["std"] std = [] -ethexe = ["gstd/ethexe"] +ethexe = ["gstd/ethexe", "gtest/ethexe", "gear-wasm-builder/ethexe"] diff --git a/examples/panic-payload/Cargo.toml b/examples/panic-payload/Cargo.toml index 9373b6cb214..38044106239 100644 --- a/examples/panic-payload/Cargo.toml +++ b/examples/panic-payload/Cargo.toml @@ -22,4 +22,4 @@ gear-wasm-builder.workspace = true debug = ["gstd/debug"] default = ["std"] std = [] -ethexe = ["gstd/ethexe"] +ethexe = ["gstd/ethexe", "gtest/ethexe", "gear-wasm-builder/ethexe"] diff --git a/examples/piggy-bank/Cargo.toml b/examples/piggy-bank/Cargo.toml index ae04bf2c482..20432fa6eb9 100644 --- a/examples/piggy-bank/Cargo.toml +++ b/examples/piggy-bank/Cargo.toml @@ -18,4 +18,4 @@ gear-wasm-builder.workspace = true debug = ["gstd/debug"] default = ["std"] std = [] -ethexe = ["gstd/ethexe"] +ethexe = ["gstd/ethexe", "gear-wasm-builder/ethexe"] diff --git a/examples/ping/Cargo.toml b/examples/ping/Cargo.toml index 4350063695a..b605f662856 100644 --- a/examples/ping/Cargo.toml +++ b/examples/ping/Cargo.toml @@ -18,4 +18,4 @@ gear-wasm-builder.workspace = true debug = ["gstd/debug"] default = ["std"] std = [] -ethexe = ["gstd/ethexe"] +ethexe = ["gstd/ethexe", "gear-wasm-builder/ethexe"] diff --git a/examples/reply-callback/Cargo.toml b/examples/reply-callback/Cargo.toml index fd52c91ff86..58152200f2a 100644 --- a/examples/reply-callback/Cargo.toml +++ b/examples/reply-callback/Cargo.toml @@ -18,4 +18,4 @@ gear-wasm-builder.workspace = true debug = ["gstd/debug"] default = ["std"] std = [] -ethexe = ["gstd/ethexe"] +ethexe = ["gstd/ethexe", "gear-wasm-builder/ethexe"] diff --git a/examples/syscalls-ethexe/Cargo.toml b/examples/syscalls-ethexe/Cargo.toml index 9b755530366..ed3726c13cc 100644 --- a/examples/syscalls-ethexe/Cargo.toml +++ b/examples/syscalls-ethexe/Cargo.toml @@ -19,4 +19,4 @@ gear-wasm-builder.workspace = true debug = ["gstd/debug"] std = ["parity-scale-codec/std"] default = ["std"] -ethexe = ["gstd/ethexe"] +ethexe = ["gstd/ethexe", "gear-wasm-builder/ethexe"] diff --git a/examples/value-sender-ethexe/Cargo.toml b/examples/value-sender-ethexe/Cargo.toml index b3de8ae37a2..029dfa3b64b 100644 --- a/examples/value-sender-ethexe/Cargo.toml +++ b/examples/value-sender-ethexe/Cargo.toml @@ -18,4 +18,4 @@ gear-wasm-builder.workspace = true debug = ["gstd/debug"] std = [] default = ["std"] -ethexe = ["gstd/ethexe"] +ethexe = ["gstd/ethexe", "gear-wasm-builder/ethexe"] diff --git a/gcore/src/exec.rs b/gcore/src/exec.rs index f09ecd21aab..33770936754 100644 --- a/gcore/src/exec.rs +++ b/gcore/src/exec.rs @@ -27,11 +27,10 @@ use crate::{ utils::AsRawPtr, }; use core::mem::MaybeUninit; -use gsys::BlockNumberWithHash; #[cfg(not(feature = "ethexe"))] use { crate::ReservationId, - gsys::{ErrorWithGas, ErrorWithHash}, + gsys::{BlockNumberWithHash, ErrorWithGas, ErrorWithHash}, }; /// Get current version of environment variables. @@ -352,6 +351,7 @@ pub fn value_available() -> u128 { /// exec::wait(); /// } /// ``` +#[cfg(not(feature = "ethexe"))] pub fn wait() -> ! { unsafe { gsys::gr_wait() } } @@ -453,6 +453,7 @@ pub fn program_id() -> ActorId { /// let (seed, block_number) = exec::random(subject).expect("Error in random"); /// } /// ``` +#[cfg(not(feature = "ethexe"))] pub fn random(subject: [u8; 32]) -> Result<([u8; 32], u32)> { let mut res: BlockNumberWithHash = Default::default(); diff --git a/gcore/src/lib.rs b/gcore/src/lib.rs index def87320236..0be83ca1cb8 100644 --- a/gcore/src/lib.rs +++ b/gcore/src/lib.rs @@ -74,6 +74,7 @@ pub mod ctor; pub mod errors; pub mod exec; pub mod msg; +#[cfg(not(feature = "ethexe"))] pub mod prog; pub use gear_stack_buffer as stack_buffer; #[cfg(not(feature = "ethexe"))] diff --git a/gcore/src/prog.rs b/gcore/src/prog.rs index ffb1ecdd85f..e041e6b291b 100644 --- a/gcore/src/prog.rs +++ b/gcore/src/prog.rs @@ -121,7 +121,6 @@ pub fn create_program( } /// Same as [`create_program`], but with an explicit gas limit. -#[cfg(not(feature = "ethexe"))] pub fn create_program_with_gas( code_id: CodeId, salt: &[u8], diff --git a/gstd/src/lib.rs b/gstd/src/lib.rs index 12f6d02c0b1..1ac7c2e3bed 100644 --- a/gstd/src/lib.rs +++ b/gstd/src/lib.rs @@ -156,6 +156,7 @@ pub mod exec; mod macros; pub mod msg; pub mod prelude; +#[cfg(not(feature = "ethexe"))] pub mod prog; #[cfg(not(feature = "ethexe"))] mod reservations; diff --git a/gstd/src/prog/basic.rs b/gstd/src/prog/basic.rs index 65713c8b96f..0a42f7386d5 100644 --- a/gstd/src/prog/basic.rs +++ b/gstd/src/prog/basic.rs @@ -89,7 +89,6 @@ pub fn create_program_bytes_delayed( } /// Same as [`create_program_bytes`], but with an explicit gas limit. -#[cfg(not(feature = "ethexe"))] #[wait_create_program_for_reply] pub fn create_program_bytes_with_gas( code_id: CodeId, @@ -103,7 +102,6 @@ pub fn create_program_bytes_with_gas( /// Same as [`create_program_bytes_with_gas`], but creates a new program after /// the `delay` expressed in block count. -#[cfg(not(feature = "ethexe"))] pub fn create_program_bytes_with_gas_delayed( code_id: CodeId, salt: impl AsRef<[u8]>, diff --git a/gstd/src/prog/encoded.rs b/gstd/src/prog/encoded.rs index 28695da883f..6dcc77830d7 100644 --- a/gstd/src/prog/encoded.rs +++ b/gstd/src/prog/encoded.rs @@ -50,7 +50,6 @@ pub fn create_program_delayed( } /// Same as [`create_program`], but with an explicit gas limit. -#[cfg(not(feature = "ethexe"))] #[wait_create_program_for_reply] pub fn create_program_with_gas( code_id: CodeId, @@ -66,7 +65,6 @@ pub fn create_program_with_gas( /// Same as [`create_program_with_gas`], but creates a new program after the /// `delay` expressed in block count. -#[cfg(not(feature = "ethexe"))] pub fn create_program_with_gas_delayed( code_id: CodeId, salt: impl AsRef<[u8]>, diff --git a/gstd/src/prog/generator.rs b/gstd/src/prog/generator.rs index 9c48397b9f9..579b044daef 100644 --- a/gstd/src/prog/generator.rs +++ b/gstd/src/prog/generator.rs @@ -108,7 +108,6 @@ impl ProgramGenerator { /// Same as [`create_program_bytes`](Self::create_program_bytes), but with /// an explicit gas limit. - #[cfg(not(feature = "ethexe"))] #[wait_create_program_for_reply(Self)] pub fn create_program_bytes_with_gas( code_id: CodeId, @@ -121,7 +120,6 @@ impl ProgramGenerator { /// Same as [`create_program_bytes_with_gas`](Self::create_program_bytes_with_gas), but /// creates a new program after the `delay` expressed in block count. - #[cfg(not(feature = "ethexe"))] pub fn create_program_bytes_with_gas_delayed( code_id: CodeId, payload: impl AsRef<[u8]>, @@ -167,7 +165,6 @@ impl ProgramGenerator { /// Same as [`create_program`](Self::create_program), but with an explicit /// gas limit. - #[cfg(not(feature = "ethexe"))] #[wait_create_program_for_reply(Self)] pub fn create_program_with_gas( code_id: CodeId, @@ -182,7 +179,6 @@ impl ProgramGenerator { /// Same as [`create_program_with_gas`](Self::create_program_with_gas), but /// creates a new program after the `delay` expressed in block count. - #[cfg(not(feature = "ethexe"))] pub fn create_program_with_gas_delayed( code_id: CodeId, payload: E, diff --git a/gsys/src/lib.rs b/gsys/src/lib.rs index e81298082d1..10a1c488d9b 100644 --- a/gsys/src/lib.rs +++ b/gsys/src/lib.rs @@ -493,6 +493,7 @@ syscalls! { /// - `delay`: `u32` amount of blocks to delay. /// - `err_mid_pid`: `mut ptr` for concatenated error code, message id /// and program id. + #[cfg(not(feature = "ethexe"))] pub fn gr_create_program( cid_value: *const HashWithValue, salt: *const SizedBufferStart, @@ -576,6 +577,7 @@ syscalls! { /// Arguments type: /// - `subject`: `const ptr` for the subject. /// - `bn_random`: `mut ptr` for concatenated block number with hash. + #[cfg(not(feature = "ethexe"))] pub fn gr_random(subject: *const Hash, bn_random: *mut BlockNumberWithHash); // TODO: issue #1859 @@ -954,6 +956,7 @@ syscalls! { pub fn gr_wait_up_to(duration: BlockNumber) -> !; /// Infallible `gr_wait` control syscall. + #[cfg(not(feature = "ethexe"))] pub fn gr_wait() -> !; /// Fallible `gr_wake` control syscall. diff --git a/gtest/Cargo.toml b/gtest/Cargo.toml index 88cec179e11..3b72145b4c5 100644 --- a/gtest/Cargo.toml +++ b/gtest/Cargo.toml @@ -48,3 +48,7 @@ demo-futures-unordered.workspace = true demo-constructor = { workspace = true, features = ["std"] } demo-delayed-sender.workspace = true gear-core = { workspace = true, features = ["mock"] } + +[features] +## Disables unsupported syscalls and their calls for executing on ethexe. +ethexe = ["gprimitives/ethexe", "gsys/ethexe"] diff --git a/gtest/src/lib.rs b/gtest/src/lib.rs index 01caf9c1e81..6abf2be0b86 100644 --- a/gtest/src/lib.rs +++ b/gtest/src/lib.rs @@ -521,6 +521,8 @@ pub(crate) use constants::*; /// Module containing constants of Gear protocol. pub mod constants { + use gear_core::code::SyscallKind; + /* Constant types */ use gear_common::GasMultiplier; @@ -534,6 +536,16 @@ pub mod constants { /// Numeric type representing blocks in Gear protocol. pub type BlockNumber = u32; + /* Syscall-related constants */ + + /// Syscall kind for executing syscalls in Gear protocol (Vara). + #[cfg(not(feature = "ethexe"))] + pub(crate) const SYSCALL_KIND: SyscallKind = SyscallKind::Vara; + + /// Syscall kind for executing syscalls in Gear protocol (Vara.ETH). + #[cfg(feature = "ethexe")] + pub(crate) const SYSCALL_KIND: SyscallKind = SyscallKind::Eth; + /* Gas logic related constants */ /// Gas allowance for executing user dispatch and set of generated diff --git a/gtest/src/manager/block_exec.rs b/gtest/src/manager/block_exec.rs index 5bd43889e3b..56c733a1945 100644 --- a/gtest/src/manager/block_exec.rs +++ b/gtest/src/manager/block_exec.rs @@ -18,7 +18,7 @@ use super::*; use crate::{ - WasmProgram, + SYSCALL_KIND, WasmProgram, builtins::{self, BLS12_381_ID, BlsOpsGasCostsImpl, ETH_BRIDGE_ID}, state::{ blocks, @@ -630,6 +630,7 @@ impl ExtManager { metadata: code_metadata, }, balance, + SYSCALL_KIND, ), ( blocks::current_epoch_random(), diff --git a/gtest/src/manager/memory.rs b/gtest/src/manager/memory.rs index 419df3f3a5c..b12494a0789 100644 --- a/gtest/src/manager/memory.rs +++ b/gtest/src/manager/memory.rs @@ -17,7 +17,7 @@ // along with this program. If not, see . use super::*; -use crate::state::programs::GTestProgram; +use crate::{SYSCALL_KIND, state::programs::GTestProgram}; impl ExtManager { /// Call non-void meta function from actor stored in manager. @@ -70,6 +70,7 @@ impl ExtManager { payload, MAX_USER_GAS_LIMIT, self.blocks_manager.get(), + SYSCALL_KIND, ) .map_err(TestError::ReadStateError) } diff --git a/gtest/src/program.rs b/gtest/src/program.rs index e9b88d42042..0d29c0bcd27 100644 --- a/gtest/src/program.rs +++ b/gtest/src/program.rs @@ -17,7 +17,7 @@ // along with this program. If not, see . use crate::{ - MAX_USER_GAS_LIMIT, Result, Value, default_users_list, + MAX_USER_GAS_LIMIT, Result, SYSCALL_KIND, Value, default_users_list, error::usage_panic, manager::{CUSTOM_WASM_PROGRAM_CODE_ID, ExtManager}, state::programs::{GTestProgram, PLACEHOLDER_MESSAGE_ID, ProgramsStorageManager}, @@ -276,6 +276,7 @@ impl ProgramBuilder { schedule.limits.data_segments_amount.into(), schedule.limits.type_section_len.into(), schedule.limits.parameters.into(), + SYSCALL_KIND, ) .expect("Failed to create Program from provided code"); diff --git a/pallets/gear/src/benchmarking/mod.rs b/pallets/gear/src/benchmarking/mod.rs index ebaf74d14e6..0aec288e4ec 100644 --- a/pallets/gear/src/benchmarking/mod.rs +++ b/pallets/gear/src/benchmarking/mod.rs @@ -76,7 +76,7 @@ use frame_support::traits::{Currency, Get, Hooks}; use frame_system::{Pallet as SystemPallet, RawOrigin}; use gear_core::{ buffer::Payload, - code::{Code, CodeAndId}, + code::{Code, CodeAndId, SyscallKind}, ids::{ActorId, CodeId, MessageId, prelude::*}, memory::Memory, message::{DispatchKind, Salt}, @@ -92,9 +92,7 @@ use gear_core_backend::{ }; use gear_core_errors::*; use gear_sandbox::{SandboxMemory, SandboxStore, default_executor::Store}; -use gear_wasm_instrument::{ - BlockType, BrTable, Instruction, MemArg, ValType, syscalls::SyscallName, -}; +use gear_wasm_instrument::{BlockType, BrTable, Instruction, MemArg, SyscallName, ValType}; use pallet_authorship::Pallet as AuthorshipPallet; use parity_scale_codec::Encode; use sp_consensus_babe::{ @@ -387,7 +385,7 @@ benchmarks! { let WasmModule { code, .. } = WasmModule::::sized(c * 1024, Location::Init); let ext = Ext::new(ProcessorContext::new_mock()); }: { - Environment::new(ext, &code, DispatchKind::Init, Default::default(), max_pages::().into()).unwrap(); + Environment::new(ext, &code, DispatchKind::Init, Default::default(), max_pages::().into(), SyscallKind::Vara).unwrap(); } // `d`: Size of the data section in kilobytes. @@ -397,7 +395,7 @@ benchmarks! { let WasmModule { code, .. } = WasmModule::::sized_data_section(d * 1024, MAX_NUMBER_OF_DATA_SEGMENTS); let ext = Ext::new(ProcessorContext::new_mock()); }: { - Environment::new(ext, &code, DispatchKind::Init, Default::default(), max_pages::().into()).unwrap(); + Environment::new(ext, &code, DispatchKind::Init, Default::default(), max_pages::().into(), SyscallKind::Vara).unwrap(); } // `g`: Size of the global section in kilobytes. @@ -407,7 +405,7 @@ benchmarks! { let WasmModule { code, .. } = WasmModule::::sized_global_section(g * 1024); let ext = Ext::new(ProcessorContext::new_mock()); }: { - Environment::new(ext, &code, DispatchKind::Init, Default::default(), max_pages::().into()).unwrap(); + Environment::new(ext, &code, DispatchKind::Init, Default::default(), max_pages::().into(), SyscallKind::Vara).unwrap(); } // `t`: Size of the memory allocated for the table after instantiation, in kilobytes. @@ -417,7 +415,7 @@ benchmarks! { let WasmModule { code, .. } = WasmModule::::sized_table_section(t * 1024, None); let ext = Ext::new(ProcessorContext::new_mock()); }: { - Environment::new(ext, &code, DispatchKind::Init, Default::default(), max_pages::().into()).unwrap(); + Environment::new(ext, &code, DispatchKind::Init, Default::default(), max_pages::().into(), SyscallKind::Vara).unwrap(); } // `e`: Size of the element section in kilobytes. @@ -428,7 +426,7 @@ benchmarks! { let WasmModule { code, .. } = WasmModule::::sized_table_section(max_table_size, Some(e * 1024)); let ext = Ext::new(ProcessorContext::new_mock()); }: { - Environment::new(ext, &code, DispatchKind::Init, Default::default(), max_pages::().into()).unwrap(); + Environment::new(ext, &code, DispatchKind::Init, Default::default(), max_pages::().into(), SyscallKind::Vara).unwrap(); } // `t`: Size of the type section in kilobytes. @@ -438,7 +436,7 @@ benchmarks! { let WasmModule { code, .. } = WasmModule::::sized_type_section(t * 1024); let ext = Ext::new(ProcessorContext::new_mock()); }: { - Environment::new(ext, &code, DispatchKind::Init, Default::default(), max_pages::().into()).unwrap(); + Environment::new(ext, &code, DispatchKind::Init, Default::default(), max_pages::().into(), SyscallKind::Vara).unwrap(); } claim_value { diff --git a/pallets/gear/src/benchmarking/utils.rs b/pallets/gear/src/benchmarking/utils.rs index 4c99490ae34..e13378b0730 100644 --- a/pallets/gear/src/benchmarking/utils.rs +++ b/pallets/gear/src/benchmarking/utils.rs @@ -32,7 +32,7 @@ use core_processor::{ }; use frame_support::traits::{Currency, Get}; use gear_core::{ - code::{Code, CodeAndId, InstrumentedCodeAndMetadata}, + code::{Code, CodeAndId, InstrumentedCodeAndMetadata, SyscallKind}, ids::{ActorId, CodeId, MessageId, prelude::*}, limited::LimitedVecError, message::{Dispatch, DispatchKind, Message, ReplyDetails, SignalDetails}, @@ -98,6 +98,7 @@ where schedule.limits.data_segments_amount.into(), schedule.limits.type_section_len.into(), schedule.limits.parameters.into(), + SyscallKind::Vara, ) .map_err(|_| "Code failed to load")?; @@ -290,6 +291,7 @@ where metadata: code_metadata, }, balance, + SyscallKind::Vara, ); Ok(Exec { diff --git a/pallets/gear/src/lib.rs b/pallets/gear/src/lib.rs index bedcf83b932..17caaa672db 100644 --- a/pallets/gear/src/lib.rs +++ b/pallets/gear/src/lib.rs @@ -92,7 +92,10 @@ use frame_system::{ }; use gear_core::{ buffer::*, - code::{Code, CodeAndId, CodeError, CodeMetadata, InstrumentationStatus, InstrumentedCode}, + code::{ + Code, CodeAndId, CodeError, CodeMetadata, InstrumentationStatus, InstrumentedCode, + SyscallKind, + }, env::MessageWaitedType, ids::{ActorId, CodeId, MessageId, ReservationId, prelude::*}, limited::LimitedVecError, @@ -1094,6 +1097,7 @@ pub mod pallet { schedule.limits.data_segments_amount.into(), schedule.limits.type_section_len.into(), schedule.limits.parameters.into(), + SyscallKind::Vara, ) { Ok(code) => { let instrumented_code_and_metadata = code.into_instrumented_code_and_metadata(); @@ -1135,6 +1139,7 @@ pub mod pallet { schedule.limits.data_segments_amount.into(), schedule.limits.type_section_len.into(), schedule.limits.parameters.into(), + SyscallKind::Vara, ) .map_err(|e| { log::debug!("Code checking or instrumentation failed: {e}"); diff --git a/pallets/gear/src/queue.rs b/pallets/gear/src/queue.rs index aa4eb963fae..22babe20dae 100644 --- a/pallets/gear/src/queue.rs +++ b/pallets/gear/src/queue.rs @@ -278,8 +278,14 @@ where core_processor::process::( block_config, - ProcessExecutionContext::new - (context, InstrumentedCodeAndMetadata{instrumented_code, metadata: code_metadata}, balance), + ProcessExecutionContext::new( + context, + InstrumentedCodeAndMetadata { + instrumented_code, + metadata: code_metadata + }, + balance, SyscallKind::Vara, + ), (random.encode(), bn.unique_saturated_into()), ) .unwrap_or_else(|e| { diff --git a/pallets/gear/src/runtime_api.rs b/pallets/gear/src/runtime_api.rs index f762b591199..004ec059fcc 100644 --- a/pallets/gear/src/runtime_api.rs +++ b/pallets/gear/src/runtime_api.rs @@ -21,7 +21,7 @@ use crate::queue::QueueStep; use core::convert::TryFrom; use frame_support::{dispatch::RawOrigin, traits::PalletInfo}; use gear_core::{ - code::{InstrumentedCodeAndMetadata, TryNewCodeConfig}, + code::{InstrumentedCodeAndMetadata, SyscallKind, TryNewCodeConfig}, pages::{WasmPage, numerated::tree::IntervalsTree}, program::{ActiveProgram, MemoryInfix}, rpc::ReplyInfo, @@ -444,6 +444,7 @@ where payload, gas_allowance, block_info, + SyscallKind::Vara, ) } @@ -483,6 +484,7 @@ where payload, gas_allowance, block_info, + SyscallKind::Vara, ) } @@ -521,6 +523,7 @@ where Default::default(), gas_allowance, block_info, + SyscallKind::Vara, ) .and_then(|bytes| { H256::decode(&mut bytes.as_ref()).map_err(|_| "Failed to decode hash".into()) diff --git a/pallets/gear/src/tests.rs b/pallets/gear/src/tests.rs index 9565ec13c3d..5e638b5922a 100644 --- a/pallets/gear/src/tests.rs +++ b/pallets/gear/src/tests.rs @@ -47,6 +47,7 @@ use gear_core::{ buffer::Payload, code::{ self, Code, CodeError, ExportError, InstrumentedCodeAndMetadata, MAX_WASM_PAGES_AMOUNT, + SyscallKind, }, gas_metering::CustomConstantCostRules, ids::{ActorId, CodeId, MessageId, prelude::*}, @@ -409,6 +410,7 @@ fn state_rpc_calls_trigger_reinstrumentation() { schedule.limits.data_segments_amount.into(), schedule.limits.type_section_len.into(), schedule.limits.parameters.into(), + SyscallKind::Vara, ) .expect("Failed to create dummy code"); @@ -4952,6 +4954,7 @@ fn test_code_submission_pass() { schedule.limits.data_segments_amount.into(), schedule.limits.type_section_len.into(), schedule.limits.parameters.into(), + SyscallKind::Vara, ) .expect("Error creating Code"); assert_eq!( @@ -6882,6 +6885,7 @@ fn test_create_program_works() { schedule.limits.data_segments_amount.into(), schedule.limits.type_section_len.into(), schedule.limits.parameters.into(), + SyscallKind::Vara, ) .expect("Code failed to load"); @@ -10587,6 +10591,7 @@ fn test_mad_big_prog_instrumentation() { schedule.limits.data_segments_amount.into(), schedule.limits.type_section_len.into(), schedule.limits.parameters.into(), + SyscallKind::Vara, ); // In any case of the defined weights on the platform, instrumentation of the valid // huge wasm mustn't fail @@ -13583,6 +13588,7 @@ fn wrong_entry_type() { None, None, None, + SyscallKind::Vara, ), Err(CodeError::Export(ExportError::InvalidExportFnSignature(0))) )); diff --git a/utils/calc-stack-height/src/main.rs b/utils/calc-stack-height/src/main.rs index db497b93387..b1a00c957a6 100644 --- a/utils/calc-stack-height/src/main.rs +++ b/utils/calc-stack-height/src/main.rs @@ -18,7 +18,7 @@ use anyhow::{Context, ensure}; use gear_core::{ - code::{Code, TryNewCodeConfig}, + code::{Code, SyscallKind, TryNewCodeConfig}, gas_metering::Schedule, }; use gear_wasm_instrument::{STACK_HEIGHT_EXPORT_NAME, SystemBreakCode}; @@ -128,6 +128,7 @@ fn main() -> anyhow::Result<()> { schedule.limits.data_segments_amount.into(), schedule.limits.type_section_len.into(), schedule.limits.parameters.into(), + SyscallKind::Vara, ) .context("Code error")?; diff --git a/utils/wasm-builder/Cargo.toml b/utils/wasm-builder/Cargo.toml index 9cf8951da1e..1e855ff600e 100644 --- a/utils/wasm-builder/Cargo.toml +++ b/utils/wasm-builder/Cargo.toml @@ -27,3 +27,7 @@ gear-wasm-instrument.workspace = true gear-wasm-optimizer.workspace = true itertools = { workspace = true, features = ["use_std"] } gear-workspace-hack.workspace = true + +[features] +## Disables unsupported syscalls and their calls for executing on ethexe. +ethexe = [] diff --git a/utils/wasm-builder/src/code_validator.rs b/utils/wasm-builder/src/code_validator.rs index a635c92ed5e..de1d9d9db48 100644 --- a/utils/wasm-builder/src/code_validator.rs +++ b/utils/wasm-builder/src/code_validator.rs @@ -16,14 +16,13 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use crate::SYSCALL_KIND; use anyhow::{anyhow, bail, ensure}; use gear_core::{ code::{Code, CodeError, ExportError, ImportError}, gas_metering::Schedule, }; -use gear_wasm_instrument::{ - Export, ExternalKind, FuncType, Module, SyscallKind, SyscallName, TypeRef, ValType, -}; +use gear_wasm_instrument::{Export, ExternalKind, FuncType, Module, SyscallName, TypeRef, ValType}; use std::fmt; use thiserror::Error; @@ -239,7 +238,7 @@ impl TryFrom<(Module, ImportError)> for ImportErrorWithContext { name: import_name, }, InvalidImportFnSignature(_) => { - let syscalls = SyscallName::instrumentable_map(SyscallKind::Vara); + let syscalls = SyscallName::instrumentable_map(SYSCALL_KIND); let Some(syscall) = syscalls.get(&import_name) else { bail!("failed to get syscall by name"); }; @@ -332,6 +331,7 @@ pub fn validate_program(code: Vec, check_len: bool) -> anyhow::Result<()> { schedule.limits.data_segments_amount.into(), schedule.limits.type_section_len.into(), schedule.limits.parameters.into(), + SYSCALL_KIND, ); match code { diff --git a/utils/wasm-builder/src/lib.rs b/utils/wasm-builder/src/lib.rs index a7381edad7c..8eed18a1c32 100644 --- a/utils/wasm-builder/src/lib.rs +++ b/utils/wasm-builder/src/lib.rs @@ -25,6 +25,7 @@ pub use wasm_project::{PreProcessor, PreProcessorResult, PreProcessorTarget}; use crate::wasm_project::WasmProject; use anyhow::Result; +use gear_core::code::SyscallKind; use regex::Regex; use std::{env, path::PathBuf, process}; @@ -37,6 +38,14 @@ mod wasm_project; pub const TARGET: &str = env!("TARGET"); +/// Syscall kind for executing syscalls in Gear protocol (Vara). +#[cfg(not(feature = "ethexe"))] +pub(crate) const SYSCALL_KIND: SyscallKind = SyscallKind::Vara; + +/// Syscall kind for executing syscalls in Gear protocol (Vara.ETH). +#[cfg(feature = "ethexe")] +pub(crate) const SYSCALL_KIND: SyscallKind = SyscallKind::Eth; + /// WASM building tool. pub struct WasmBuilder { wasm_project: WasmProject, diff --git a/utils/wasm-gen/src/config/syscalls/injection.rs b/utils/wasm-gen/src/config/syscalls/injection.rs index de9eb37f78c..0ac00850a49 100644 --- a/utils/wasm-gen/src/config/syscalls/injection.rs +++ b/utils/wasm-gen/src/config/syscalls/injection.rs @@ -103,7 +103,7 @@ impl SyscallsInjectionTypes { let instrumentable_syscalls = SyscallName::instrumentable(syscall_kind).collect::>(); Self { syscall_kind, - inner: SyscallName::instrumentable(SyscallKind::Vara) + inner: SyscallName::instrumentable(syscall_kind) .map(|name| { let range = unstructured.int_in_range(1..=3).unwrap() ..=unstructured.int_in_range(3..=20).unwrap(); @@ -115,7 +115,7 @@ impl SyscallsInjectionTypes { (InvocableSyscall::Loose(name), injection_type) }) .chain( - SyscallName::instrumentable(SyscallKind::Vara) + SyscallName::instrumentable(syscall_kind) .filter(|&name| InvocableSyscall::has_precise_variant(name)) .map(|name| { let injection_type = if instrumentable_syscalls.contains(&name) { @@ -143,7 +143,7 @@ impl SyscallsInjectionTypes { let instrumentable_syscalls = SyscallName::instrumentable(syscall_kind).collect::>(); Self { syscall_kind, - inner: SyscallName::instrumentable(SyscallKind::Vara) + inner: SyscallName::instrumentable(syscall_kind) .map(|name| { ( InvocableSyscall::Loose(name), @@ -155,7 +155,7 @@ impl SyscallsInjectionTypes { ) }) .chain( - SyscallName::instrumentable(SyscallKind::Vara).filter_map(|name| { + SyscallName::instrumentable(syscall_kind).filter_map(|name| { InvocableSyscall::has_precise_variant(name).then_some(( InvocableSyscall::Precise(name), if instrumentable_syscalls.contains(&name) { diff --git a/utils/wasm-gen/src/generator.rs b/utils/wasm-gen/src/generator.rs index fe3ddf28da1..74e4d46f114 100644 --- a/utils/wasm-gen/src/generator.rs +++ b/utils/wasm-gen/src/generator.rs @@ -54,7 +54,7 @@ pub use entry_points::*; pub use memory::*; pub use syscalls::*; -use crate::{GearWasmGeneratorConfig, WasmModule, utils}; +use crate::{GearWasmGeneratorConfig, SyscallKind, WasmModule, utils}; use arbitrary::{Result, Unstructured}; use gear_wasm_instrument::Module; use std::{collections::HashSet, ops::RangeInclusive}; @@ -114,6 +114,7 @@ impl<'a, 'b> GearWasmGenerator<'a, 'b> { /// Run all generators, while mediating between them. pub fn generate(self) -> Result { + let syscall_kind = self.config.syscalls_config.injection_types().syscall_kind(); let (disabled_mem_gen, frozen_gear_wasm_gen, mem_imports_gen_proof) = self.generate_memory_export(); @@ -122,7 +123,8 @@ impl<'a, 'b> GearWasmGenerator<'a, 'b> { .generate_entry_points(mem_imports_gen_proof)?; let (disabled_syscalls_invocator, frozen_gear_wasm_gen) = - Self::from((disabled_ep_gen, frozen_gear_wasm_gen)).generate_syscalls(ep_gen_proof)?; + Self::from((disabled_ep_gen, frozen_gear_wasm_gen)) + .generate_syscalls(ep_gen_proof, syscall_kind)?; let config = frozen_gear_wasm_gen.melt(); let module = ModuleWithCallIndexes::from(disabled_syscalls_invocator) @@ -183,11 +185,12 @@ impl<'a, 'b> GearWasmGenerator<'a, 'b> { pub fn generate_syscalls( self, ep_gen_proof: GearEntryPointGenerationProof, + syscall_kind: SyscallKind, ) -> Result<(DisabledSyscallsInvocator, FrozenGearWasmGenerator<'a, 'b>)> { let syscalls_imports_gen_instantiator = SyscallsImportsGeneratorInstantiator::from((self, ep_gen_proof)); let (syscalls_imports_gen, frozen_gear_wasm_gen) = syscalls_imports_gen_instantiator.into(); - let syscalls_imports_gen_res = syscalls_imports_gen.generate()?; + let syscalls_imports_gen_res = syscalls_imports_gen.generate(syscall_kind)?; let ad_injector = AdditionalDataInjector::from(syscalls_imports_gen_res); let data_injection_res = ad_injector.inject(); diff --git a/utils/wasm-gen/src/generator/syscalls/imports.rs b/utils/wasm-gen/src/generator/syscalls/imports.rs index 951424f6744..5668a1bafc9 100644 --- a/utils/wasm-gen/src/generator/syscalls/imports.rs +++ b/utils/wasm-gen/src/generator/syscalls/imports.rs @@ -145,26 +145,30 @@ impl<'a, 'b> SyscallsImportsGenerator<'a, 'b> { /// Returns disabled syscalls imports generator and a proof that imports from config were generated. pub fn generate( mut self, + syscall_kind: SyscallKind, ) -> Result<( DisabledSyscallsImportsGenerator<'a, 'b>, SyscallsImportsGenerationProof, )> { log::trace!("Generating syscalls imports"); - let syscalls_proof = self.generate_syscalls_imports()?; - self.generate_precise_syscalls()?; + let syscalls_proof = self.generate_syscalls_imports(syscall_kind)?; + self.generate_precise_syscalls(syscall_kind)?; Ok((self.disable(), syscalls_proof)) } /// Generates syscalls imports from config, used to instantiate the generator. - pub fn generate_syscalls_imports(&mut self) -> Result { + pub fn generate_syscalls_imports( + &mut self, + syscall_kind: SyscallKind, + ) -> Result { log::trace!( "Random data before syscalls imports - {}", self.unstructured.len() ); - for syscall in SyscallName::instrumentable(SyscallKind::Vara) { + for syscall in SyscallName::instrumentable(syscall_kind) { let syscall_generation_data = self.generate_syscall_import(syscall)?; if let Some(syscall_generation_data) = syscall_generation_data { self.syscalls_imports @@ -176,7 +180,7 @@ impl<'a, 'b> SyscallsImportsGenerator<'a, 'b> { } /// Generates precise syscalls and handles errors if any occurred during generation. - fn generate_precise_syscalls(&mut self) -> Result<()> { + fn generate_precise_syscalls(&mut self, syscall_kind: SyscallKind) -> Result<()> { use SyscallName::*; #[allow(clippy::type_complexity)] @@ -186,12 +190,24 @@ impl<'a, 'b> SyscallsImportsGenerator<'a, 'b> { ); 5] = [ (ReservationSend, Self::generate_send_from_reservation), (ReservationReply, Self::generate_reply_from_reservation), + // Avaliable for both `SyscallKind::Vara` and `SyscallKind::Eth` (SendCommit, Self::generate_send_commit), (SendCommitWGas, Self::generate_send_commit_with_gas), (ReplyDeposit, Self::generate_reply_deposit), ]; for (precise_syscall, generate_method) in precise_syscalls { + // Check if precise syscall is applicable for the current syscall kind. If not, skip it. + match syscall_kind { + SyscallKind::Vara if !precise_syscall.is_vara() => { + continue; + } + SyscallKind::Eth if !precise_syscall.is_eth() => { + continue; + } + _ => {} + } + let syscall_injection_type = self .config .injection_type(InvocableSyscall::Precise(precise_syscall)); diff --git a/utils/wasm-gen/src/tests.rs b/utils/wasm-gen/src/tests.rs index 16c2e98613f..125bfc5e8c8 100644 --- a/utils/wasm-gen/src/tests.rs +++ b/utils/wasm-gen/src/tests.rs @@ -19,7 +19,7 @@ use super::*; use arbitrary::Unstructured; use gear_core::{ - code::Code, + code::{Code, SyscallKind}, gas::{GasAllowanceCounter, GasCounter, ValueCounter}, gas_metering::CustomConstantCostRules, ids::{ActorId, CodeId, prelude::*}, @@ -64,7 +64,7 @@ proptest! { let original_code = generate_gear_program_code(&mut u, configs_bundle) .expect("failed generating wasm"); - let _code = Code::try_new(original_code.clone(), 1, |_| CustomConstantCostRules::default(), None, None, None, None).unwrap(); + let _code = Code::try_new(original_code.clone(), 1, |_| CustomConstantCostRules::default(), None, None, None, None, SyscallKind::Vara).unwrap(); } #[test] @@ -93,7 +93,7 @@ proptest! { let original_code = generate_gear_program_code(&mut u, configs_bundle) .expect("failed generating wasm"); - let code_res = Code::try_new(original_code, 1, |_| CustomConstantCostRules::default(), None, None, None, None); + let code_res = Code::try_new(original_code, 1, |_| CustomConstantCostRules::default(), None, None, None, None, SyscallKind::Vara); assert!(code_res.is_ok()); } @@ -1069,6 +1069,7 @@ fn execute_wasm_with_custom_configs( None, None, None, + SyscallKind::Vara, ) .expect("Failed to create Code"); @@ -1109,6 +1110,7 @@ fn execute_wasm_with_custom_configs( DispatchKind::Init, vec![DispatchKind::Init].into_iter().collect(), (INITIAL_PAGES as u16).into(), + SyscallKind::Vara, ) .expect("Failed to create environment"); diff --git a/utils/wasm-instrument/src/syscalls.rs b/utils/wasm-instrument/src/syscalls.rs index 4777dd8e976..aa99bddc131 100644 --- a/utils/wasm-instrument/src/syscalls.rs +++ b/utils/wasm-instrument/src/syscalls.rs @@ -231,10 +231,12 @@ impl SyscallName { !matches!( self, Self::CreateProgramWGas + | Self::CreateProgram | Self::ReplyDeposit | Self::SignalCode - | Self::SignalFrom + | Self::Random | Self::ReplyCommitWGas + | Self::SignalFrom | Self::ReplyInputWGas | Self::ReplyWGas | Self::ReservationReplyCommit @@ -247,6 +249,7 @@ impl SyscallName { | Self::SendWGas | Self::SystemReserveGas | Self::UnreserveGas + | Self::Wait ) } From 04b53efc6783da8c202b564f3f33f75900860552 Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Fri, 1 May 2026 23:30:16 +0300 Subject: [PATCH 02/10] fix typo and bind_funcs --- core/backend/src/env.rs | 9 ++++++--- utils/wasm-gen/src/generator/syscalls/imports.rs | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/core/backend/src/env.rs b/core/backend/src/env.rs index 3ec643dd58a..3f61f5da53e 100644 --- a/core/backend/src/env.rs +++ b/core/backend/src/env.rs @@ -162,11 +162,14 @@ where EntryPoint: WasmEntryPoint, { #[rustfmt::skip] - fn bind_funcs(builder: &mut EnvBuilder, _syscall_kind: SyscallKind) { - // FIXME: do not bind all syscalls here + fn bind_funcs(builder: &mut EnvBuilder, syscall_kind: SyscallKind) { macro_rules! add_function { ($syscall:ident, $func:ident) => { - builder.add_func($syscall, wrap_syscall!($func, $syscall)); + match syscall_kind { + SyscallKind::Vara if !$syscall.is_vara() => {}, + SyscallKind::Eth if !$syscall.is_eth() => {}, + _ => builder.add_func($syscall, wrap_syscall!($func, $syscall)), + } }; } diff --git a/utils/wasm-gen/src/generator/syscalls/imports.rs b/utils/wasm-gen/src/generator/syscalls/imports.rs index 5668a1bafc9..f63246e5e18 100644 --- a/utils/wasm-gen/src/generator/syscalls/imports.rs +++ b/utils/wasm-gen/src/generator/syscalls/imports.rs @@ -190,7 +190,7 @@ impl<'a, 'b> SyscallsImportsGenerator<'a, 'b> { ); 5] = [ (ReservationSend, Self::generate_send_from_reservation), (ReservationReply, Self::generate_reply_from_reservation), - // Avaliable for both `SyscallKind::Vara` and `SyscallKind::Eth` + // Available for both `SyscallKind::Vara` and `SyscallKind::Eth` (SendCommit, Self::generate_send_commit), (SendCommitWGas, Self::generate_send_commit_with_gas), (ReplyDeposit, Self::generate_reply_deposit), From dba746381a9ee9efaa5a9795e79fbb0a47c0aeaf Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Sat, 2 May 2026 07:26:48 +0300 Subject: [PATCH 03/10] trigger build From 3b3c8d5ce4c9b11bc9f673c6b1f6fdcab663b6b5 Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Mon, 4 May 2026 14:23:40 +0300 Subject: [PATCH 04/10] fix review --- core/backend/src/env.rs | 11 ++++++++--- utils/wasm-gen/src/generator/syscalls/imports.rs | 8 ++------ utils/wasm-instrument/src/syscalls.rs | 5 +++++ 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/core/backend/src/env.rs b/core/backend/src/env.rs index 3f61f5da53e..723c25a5f9d 100644 --- a/core/backend/src/env.rs +++ b/core/backend/src/env.rs @@ -166,7 +166,7 @@ where macro_rules! add_function { ($syscall:ident, $func:ident) => { match syscall_kind { - SyscallKind::Vara if !$syscall.is_vara() => {}, + SyscallKind::Vara if !$syscall.is_vara_including_system_break() => {}, SyscallKind::Eth if !$syscall.is_eth() => {}, _ => builder.add_func($syscall, wrap_syscall!($func, $syscall)), } @@ -300,9 +300,14 @@ where // Check that we have implementations for all the syscalls. // This is intended to panic during any testing, when the // condition is not met. + let expected_count = match syscall_kind { + SyscallKind::Vara => SyscallName::all().count(), + SyscallKind::Eth => SyscallName::all() + .filter(|syscall| syscall.is_eth()) + .count(), + }; assert_eq!( - builder.funcs_count, - SyscallName::all().count(), + builder.funcs_count, expected_count, "Not all existing syscalls were added to the module's env." ); diff --git a/utils/wasm-gen/src/generator/syscalls/imports.rs b/utils/wasm-gen/src/generator/syscalls/imports.rs index f63246e5e18..cabf6f81a3a 100644 --- a/utils/wasm-gen/src/generator/syscalls/imports.rs +++ b/utils/wasm-gen/src/generator/syscalls/imports.rs @@ -199,12 +199,8 @@ impl<'a, 'b> SyscallsImportsGenerator<'a, 'b> { for (precise_syscall, generate_method) in precise_syscalls { // Check if precise syscall is applicable for the current syscall kind. If not, skip it. match syscall_kind { - SyscallKind::Vara if !precise_syscall.is_vara() => { - continue; - } - SyscallKind::Eth if !precise_syscall.is_eth() => { - continue; - } + SyscallKind::Vara if !precise_syscall.is_vara() => continue, + SyscallKind::Eth if !precise_syscall.is_eth() => continue, _ => {} } diff --git a/utils/wasm-instrument/src/syscalls.rs b/utils/wasm-instrument/src/syscalls.rs index aa99bddc131..3681cd71ba7 100644 --- a/utils/wasm-instrument/src/syscalls.rs +++ b/utils/wasm-instrument/src/syscalls.rs @@ -223,6 +223,11 @@ impl SyscallName { self != Self::SystemBreak } + /// Checks whether the syscall is available in the Vara runtime (including SystemBreak). + pub const fn is_vara_including_system_break(self) -> bool { + true + } + /// Checks whether the syscall is available under the `ethexe` feature. /// /// Keep this in sync with the `#[cfg(not(feature = "ethexe"))]` gates in From f67fc1579aadcd3e2d72b9566691e2ce1dd6fa05 Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Mon, 4 May 2026 18:16:41 +0300 Subject: [PATCH 05/10] fix ci --- examples/async-init/Cargo.toml | 2 +- examples/async/Cargo.toml | 2 +- examples/ctor/Cargo.toml | 2 +- examples/panic-payload/Cargo.toml | 2 +- examples/piggy-bank/Cargo.toml | 2 +- examples/ping/Cargo.toml | 2 +- examples/reply-callback/Cargo.toml | 2 +- examples/syscalls-ethexe/Cargo.toml | 2 +- examples/syscalls-ethexe/src/lib.rs | 3 --- examples/syscalls-ethexe/src/wasm.rs | 8 ------ examples/value-sender-ethexe/Cargo.toml | 2 +- gstd/src/msg/async.rs | 2 ++ utils/wasm-builder/src/code_validator.rs | 32 ++++++++++++++++-------- utils/wasm-builder/src/crate_info.rs | 6 ++++- utils/wasm-builder/src/lib.rs | 4 +-- utils/wasm-builder/src/wasm_project.rs | 31 +++++++++++++++-------- utils/wasm-proc/src/main.rs | 4 +-- 17 files changed, 63 insertions(+), 45 deletions(-) diff --git a/examples/async-init/Cargo.toml b/examples/async-init/Cargo.toml index e0e78ba68f0..1b8cb712ef1 100644 --- a/examples/async-init/Cargo.toml +++ b/examples/async-init/Cargo.toml @@ -20,4 +20,4 @@ gear-wasm-builder.workspace = true debug = ["gstd/debug"] default = ["std"] std = [] -ethexe = ["gstd/ethexe", "gear-wasm-builder/ethexe"] +ethexe = ["gstd/ethexe"] diff --git a/examples/async/Cargo.toml b/examples/async/Cargo.toml index 7d70b3c2af7..9e023cfe791 100644 --- a/examples/async/Cargo.toml +++ b/examples/async/Cargo.toml @@ -19,4 +19,4 @@ gear-wasm-builder.workspace = true debug = ["gstd/debug"] default = ["std"] std = [] -ethexe = ["gstd/ethexe", "gear-wasm-builder/ethexe"] +ethexe = ["gstd/ethexe"] diff --git a/examples/ctor/Cargo.toml b/examples/ctor/Cargo.toml index 21a40ed9ff1..2d7c11e69c8 100644 --- a/examples/ctor/Cargo.toml +++ b/examples/ctor/Cargo.toml @@ -21,4 +21,4 @@ gear-wasm-builder.workspace = true debug = ["gstd/debug"] default = ["std"] std = [] -ethexe = ["gstd/ethexe", "gtest/ethexe", "gear-wasm-builder/ethexe"] +ethexe = ["gstd/ethexe", "gtest/ethexe"] diff --git a/examples/panic-payload/Cargo.toml b/examples/panic-payload/Cargo.toml index 38044106239..dcb43b89481 100644 --- a/examples/panic-payload/Cargo.toml +++ b/examples/panic-payload/Cargo.toml @@ -22,4 +22,4 @@ gear-wasm-builder.workspace = true debug = ["gstd/debug"] default = ["std"] std = [] -ethexe = ["gstd/ethexe", "gtest/ethexe", "gear-wasm-builder/ethexe"] +ethexe = ["gstd/ethexe", "gtest/ethexe"] diff --git a/examples/piggy-bank/Cargo.toml b/examples/piggy-bank/Cargo.toml index 20432fa6eb9..ae04bf2c482 100644 --- a/examples/piggy-bank/Cargo.toml +++ b/examples/piggy-bank/Cargo.toml @@ -18,4 +18,4 @@ gear-wasm-builder.workspace = true debug = ["gstd/debug"] default = ["std"] std = [] -ethexe = ["gstd/ethexe", "gear-wasm-builder/ethexe"] +ethexe = ["gstd/ethexe"] diff --git a/examples/ping/Cargo.toml b/examples/ping/Cargo.toml index b605f662856..4350063695a 100644 --- a/examples/ping/Cargo.toml +++ b/examples/ping/Cargo.toml @@ -18,4 +18,4 @@ gear-wasm-builder.workspace = true debug = ["gstd/debug"] default = ["std"] std = [] -ethexe = ["gstd/ethexe", "gear-wasm-builder/ethexe"] +ethexe = ["gstd/ethexe"] diff --git a/examples/reply-callback/Cargo.toml b/examples/reply-callback/Cargo.toml index 58152200f2a..fd52c91ff86 100644 --- a/examples/reply-callback/Cargo.toml +++ b/examples/reply-callback/Cargo.toml @@ -18,4 +18,4 @@ gear-wasm-builder.workspace = true debug = ["gstd/debug"] default = ["std"] std = [] -ethexe = ["gstd/ethexe", "gear-wasm-builder/ethexe"] +ethexe = ["gstd/ethexe"] diff --git a/examples/syscalls-ethexe/Cargo.toml b/examples/syscalls-ethexe/Cargo.toml index ed3726c13cc..9b755530366 100644 --- a/examples/syscalls-ethexe/Cargo.toml +++ b/examples/syscalls-ethexe/Cargo.toml @@ -19,4 +19,4 @@ gear-wasm-builder.workspace = true debug = ["gstd/debug"] std = ["parity-scale-codec/std"] default = ["std"] -ethexe = ["gstd/ethexe", "gear-wasm-builder/ethexe"] +ethexe = ["gstd/ethexe"] diff --git a/examples/syscalls-ethexe/src/lib.rs b/examples/syscalls-ethexe/src/lib.rs index a1537f9941b..bf2bcfb8d02 100644 --- a/examples/syscalls-ethexe/src/lib.rs +++ b/examples/syscalls-ethexe/src/lib.rs @@ -111,9 +111,6 @@ pub enum FuzzCommand { repeat: u16, }, - /// Execute `exec::wait()` — pauses execution (terminates this handle call). - /// Only the *last* command in a sequence should use this. - WaitCmd, /// Execute `exec::wait_for(duration)`. WaitForCmd(u32), /// Execute `exec::wait_up_to(duration)`. diff --git a/examples/syscalls-ethexe/src/wasm.rs b/examples/syscalls-ethexe/src/wasm.rs index ceb0ae9c068..db276c5a56d 100644 --- a/examples/syscalls-ethexe/src/wasm.rs +++ b/examples/syscalls-ethexe/src/wasm.rs @@ -185,14 +185,6 @@ extern "C" fn handle() { assert_eq!(state[index], expected, "state read mismatch"); } } - - FuzzCommand::WaitCmd => { - // Send ok before waiting so the loader gets a reply - if !replied { - msg::reply_bytes(b"ok-wait", 0).expect("reply before wait failed"); - } - exec::wait(); - } FuzzCommand::WaitForCmd(duration) => { let dur = duration.clamp(1, 100); if !replied { diff --git a/examples/value-sender-ethexe/Cargo.toml b/examples/value-sender-ethexe/Cargo.toml index 029dfa3b64b..b3de8ae37a2 100644 --- a/examples/value-sender-ethexe/Cargo.toml +++ b/examples/value-sender-ethexe/Cargo.toml @@ -18,4 +18,4 @@ gear-wasm-builder.workspace = true debug = ["gstd/debug"] std = [] default = ["std"] -ethexe = ["gstd/ethexe", "gear-wasm-builder/ethexe"] +ethexe = ["gstd/ethexe"] diff --git a/gstd/src/msg/async.rs b/gstd/src/msg/async.rs index 45358a99292..17ea8896783 100644 --- a/gstd/src/msg/async.rs +++ b/gstd/src/msg/async.rs @@ -272,6 +272,7 @@ impl_futures!( /// } /// # fn main() {} /// ``` +#[cfg(not(feature = "ethexe"))] pub struct CreateProgramFuture { /// A message identifier for an expected reply. pub waiting_reply_to: MessageId, @@ -283,6 +284,7 @@ pub struct CreateProgramFuture { pub(crate) reply_deposit: u64, } +#[cfg(not(feature = "ethexe"))] impl_futures!( CreateProgramFuture, (ActorId, Vec), diff --git a/utils/wasm-builder/src/code_validator.rs b/utils/wasm-builder/src/code_validator.rs index de1d9d9db48..4d317f0aceb 100644 --- a/utils/wasm-builder/src/code_validator.rs +++ b/utils/wasm-builder/src/code_validator.rs @@ -16,13 +16,14 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use crate::SYSCALL_KIND; use anyhow::{anyhow, bail, ensure}; use gear_core::{ code::{Code, CodeError, ExportError, ImportError}, gas_metering::Schedule, }; -use gear_wasm_instrument::{Export, ExternalKind, FuncType, Module, SyscallName, TypeRef, ValType}; +use gear_wasm_instrument::{ + Export, ExternalKind, FuncType, Module, SyscallKind, SyscallName, TypeRef, ValType, +}; use std::fmt; use thiserror::Error; @@ -207,10 +208,12 @@ pub enum ImportErrorWithContext { UnexpectedImportKind { kind: String, name: String }, } -impl TryFrom<(Module, ImportError)> for ImportErrorWithContext { +impl TryFrom<(Module, ImportError, SyscallKind)> for ImportErrorWithContext { type Error = anyhow::Error; - fn try_from((module, import_error): (Module, ImportError)) -> Result { + fn try_from( + (module, import_error, syscall_kind): (Module, ImportError, SyscallKind), + ) -> Result { use ImportError::*; let idx = match import_error { @@ -238,7 +241,7 @@ impl TryFrom<(Module, ImportError)> for ImportErrorWithContext { name: import_name, }, InvalidImportFnSignature(_) => { - let syscalls = SyscallName::instrumentable_map(SYSCALL_KIND); + let syscalls = SyscallName::instrumentable_map(syscall_kind); let Some(syscall) = syscalls.get(&import_name) else { bail!("failed to get syscall by name"); }; @@ -290,7 +293,11 @@ pub enum CodeErrorWithContext { } impl CodeErrorWithContext { - fn new(module: Module, error: CodeError) -> Result { + fn new( + module: Module, + error: CodeError, + syscall_kind: SyscallKind, + ) -> Result { use CodeError::*; match error { Validation(_) | Module(_) | Section(_) | Memory(_) | StackEnd(_) | DataSection(_) @@ -300,7 +307,8 @@ impl CodeErrorWithContext { Ok(Self::Export(error_with_context)) } Import(error) => { - let error_with_context: ImportErrorWithContext = (module, error).try_into()?; + let error_with_context: ImportErrorWithContext = + (module, error, syscall_kind).try_into()?; Ok(Self::Import(error_with_context)) } } @@ -309,7 +317,11 @@ impl CodeErrorWithContext { /// Validates wasm code in the same way as /// `pallet_gear::pallet::Pallet::upload_program(...)`. -pub fn validate_program(code: Vec, check_len: bool) -> anyhow::Result<()> { +pub fn validate_program( + code: Vec, + check_len: bool, + syscall_kind: SyscallKind, +) -> anyhow::Result<()> { let module = Module::new(&code)?; let schedule = Schedule::default(); @@ -331,7 +343,7 @@ pub fn validate_program(code: Vec, check_len: bool) -> anyhow::Result<()> { schedule.limits.data_segments_amount.into(), schedule.limits.type_section_len.into(), schedule.limits.parameters.into(), - SYSCALL_KIND, + syscall_kind, ); match code { @@ -348,6 +360,6 @@ pub fn validate_program(code: Vec, check_len: bool) -> anyhow::Result<()> { Ok(()) } - Err(code_error) => Err(CodeErrorWithContext::new(module, code_error)?)?, + Err(code_error) => Err(CodeErrorWithContext::new(module, code_error, syscall_kind)?)?, } } diff --git a/utils/wasm-builder/src/crate_info.rs b/utils/wasm-builder/src/crate_info.rs index 87354279758..89faa539c09 100644 --- a/utils/wasm-builder/src/crate_info.rs +++ b/utils/wasm-builder/src/crate_info.rs @@ -18,7 +18,7 @@ use crate::{builder_error::BuilderError, multiple_crate_versions}; use anyhow::{Context, Result, ensure}; -use cargo_metadata::{CrateType, Metadata, MetadataCommand, Package}; +use cargo_metadata::{CrateType, Dependency, Metadata, MetadataCommand, Package}; use std::{collections::BTreeMap, path::Path}; /// Helper to get a crate info extracted from the `Cargo.toml`. @@ -30,6 +30,8 @@ pub struct CrateInfo { pub snake_case_name: String, /// Crate version. pub version: String, + /// Crate dependencies. + pub dependencies: Vec, /// Crate features. pub features: BTreeMap>, /// Crate custom profiles @@ -80,12 +82,14 @@ impl CrateInfo { let name = root_package.name.clone().into_inner(); let snake_case_name = name.replace('-', "_"); let version = root_package.version.to_string(); + let dependencies = root_package.dependencies.clone(); let features = root_package.features.clone(); Ok(Self { name, snake_case_name, version, + dependencies, features, profiles, patch, diff --git a/utils/wasm-builder/src/lib.rs b/utils/wasm-builder/src/lib.rs index 8eed18a1c32..53451d37313 100644 --- a/utils/wasm-builder/src/lib.rs +++ b/utils/wasm-builder/src/lib.rs @@ -121,7 +121,7 @@ impl WasmBuilder { } fn build_project(mut self) -> Result> { - self.wasm_project.generate()?; + let crate_info = self.wasm_project.generate()?; self.cargo .set_manifest_path(self.wasm_project.manifest_path()); @@ -132,7 +132,7 @@ impl WasmBuilder { self.cargo.set_features(&self.enabled_features()?); self.cargo.run()?; - self.wasm_project.postprocess() + self.wasm_project.postprocess(crate_info) } fn manifest_path(&self) -> Result { diff --git a/utils/wasm-builder/src/wasm_project.rs b/utils/wasm-builder/src/wasm_project.rs index 64764ecb266..e9b79205526 100644 --- a/utils/wasm-builder/src/wasm_project.rs +++ b/utils/wasm-builder/src/wasm_project.rs @@ -16,9 +16,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use crate::{code_validator::validate_program, crate_info::CrateInfo, smart_fs}; +use crate::{SYSCALL_KIND, code_validator::validate_program, crate_info::CrateInfo, smart_fs}; use anyhow::{Context, Result, anyhow}; use chrono::offset::Local as ChronoLocal; +use gear_wasm_instrument::SyscallKind; use gear_wasm_optimizer::{self as optimize, Optimizer}; use std::{ env, @@ -161,18 +162,18 @@ impl WasmProject { /// Generate a temporary cargo project that includes the original package as /// a dependency. - pub fn generate(&mut self) -> Result<()> { + pub fn generate(&mut self) -> Result { let original_manifest = self.original_dir.join("Cargo.toml"); let crate_info = CrateInfo::from_manifest(&original_manifest)?; self.file_base_name = Some(crate_info.snake_case_name.clone()); let mut package = Table::new(); package.insert("name".into(), format!("{}-wasm", &crate_info.name).into()); - package.insert("version".into(), crate_info.version.into()); + package.insert("version".into(), crate_info.version.clone().into()); package.insert("edition".into(), "2024".into()); let mut lib = Table::new(); - lib.insert("name".into(), crate_info.snake_case_name.into()); + lib.insert("name".into(), crate_info.snake_case_name.clone().into()); lib.insert("crate-type".into(), vec!["cdylib".to_string()].into()); let mut dev_profile = Table::new(); @@ -186,13 +187,13 @@ impl WasmProject { let mut production_profile = Table::new(); production_profile.insert("inherits".into(), "release".into()); - let mut profile = crate_info.profiles; + let mut profile = crate_info.profiles.clone(); profile.insert("dev".into(), dev_profile.clone().into()); profile.insert("release".into(), release_profile.into()); profile.insert("production".into(), production_profile.into()); let mut crate_package = Table::new(); - crate_package.insert("package".into(), crate_info.name.into()); + crate_package.insert("package".into(), crate_info.name.clone().into()); crate_package.insert( "path".into(), self.original_dir.display().to_string().into(), @@ -213,7 +214,7 @@ impl WasmProject { } self.features = Some(features.keys().cloned().collect()); - let mut patch = crate_info.patch; + let mut patch = crate_info.patch.clone(); if let Some(crates_io) = patch.get_mut("crates-io").and_then(|v| v.as_table_mut()) { crates_io.remove("gear-workspace-hack"); } @@ -249,7 +250,7 @@ impl WasmProject { fs::create_dir_all(&src_dir).context("Failed to create `src` directory")?; smart_fs::write(src_dir.join("lib.rs"), source_code)?; - Ok(()) + Ok(crate_info) } fn generate_bin_path(&self, file_base_name: &String) -> Result<()> { @@ -333,7 +334,7 @@ pub const WASM_BINARY_OPT: &[u8] = include_bytes!("{}");"#, /// `target/wasm32-gear/` /// - Generate optimized binary from the built program /// - Generate `wasm_binary.rs` source file in `OUT_DIR` - pub fn postprocess(&self) -> Result> { + pub fn postprocess(&self, crate_info: CrateInfo) -> Result> { let file_base_name = self .file_base_name .as_ref() @@ -408,11 +409,21 @@ pub const WASM_BINARY_OPT: &[u8] = include_bytes!("{}");"#, wasm_paths = Some((wasm_path.clone(), wasm_opt)); } + let is_workspace_hack = crate_info + .dependencies + .iter() + .any(|dep| dep.name == "gear-workspace-hack"); + let syscall_kind = if is_workspace_hack { + SyscallKind::Vara + } else { + SYSCALL_KIND + }; + for (wasm_path, _) in &wasm_files { let code = fs::read(wasm_path)?; let is_release = self.profile != "debug"; - validate_program(code, is_release)?; + validate_program(code, is_release, syscall_kind)?; } if env::var("__GEAR_WASM_BUILDER_NO_FEATURES_TRACKING").as_deref() != Ok("1") { diff --git a/utils/wasm-proc/src/main.rs b/utils/wasm-proc/src/main.rs index e65ef5eb1d4..67796c3ce84 100644 --- a/utils/wasm-proc/src/main.rs +++ b/utils/wasm-proc/src/main.rs @@ -21,7 +21,7 @@ use gear_wasm_builder::{ code_validator::validate_program, optimize::{self, Optimizer}, }; -use gear_wasm_instrument::{Module, TypeRef}; +use gear_wasm_instrument::{Module, SyscallKind, TypeRef}; use std::{collections::HashSet, fs, path::PathBuf}; use tracing_subscriber::EnvFilter; @@ -290,7 +290,7 @@ fn main() -> Result<(), Box> { optimized_wasm_path.display() ); - validate_program(code, false)?; + validate_program(code, false, SyscallKind::Vara)?; } Ok(()) From 67eef4705211e6e80cee2ced7bc8462f925a98da Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Mon, 4 May 2026 18:32:43 +0300 Subject: [PATCH 06/10] fix build --- examples/delayed-sender-ethexe/src/wasm.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/delayed-sender-ethexe/src/wasm.rs b/examples/delayed-sender-ethexe/src/wasm.rs index 9a036104f27..f5c9d58c7ef 100644 --- a/examples/delayed-sender-ethexe/src/wasm.rs +++ b/examples/delayed-sender-ethexe/src/wasm.rs @@ -110,6 +110,6 @@ extern "C" fn handle() { MID = Some(msg::id()); } - exec::wait(); + // exec::wait(); } } From f4cf763c2b8812caee0abce146a54e7269cb31d5 Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Tue, 5 May 2026 19:17:53 +0300 Subject: [PATCH 07/10] fix docs --- gcore/src/exec.rs | 15 +++++++++++---- gstd/src/msg/async.rs | 6 +++++- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/gcore/src/exec.rs b/gcore/src/exec.rs index 33770936754..ff34347c23a 100644 --- a/gcore/src/exec.rs +++ b/gcore/src/exec.rs @@ -356,7 +356,8 @@ pub fn wait() -> ! { unsafe { gsys::gr_wait() } } -/// Same as [`wait`], but delays handling for a specific number of blocks. +#[cfg_attr(not(feature = "ethexe"), doc = "Same as [`wait`], but delays handling for a specific number of blocks.")] +#[cfg_attr(feature = "ethexe", doc = "Same as `wait`, but delays handling for a specific number of blocks.")] /// /// # Panics /// @@ -365,15 +366,21 @@ pub fn wait_for(duration: u32) -> ! { unsafe { gsys::gr_wait_for(duration) } } -/// Same as [`wait`], but delays handling for the maximum number of blocks that -/// can be paid for and doesn't exceed the given `duration`. +#[cfg_attr( + not(feature = "ethexe"), + doc = "Same as [`wait`], but delays handling for the maximum number of blocks that can be paid for and doesn't exceed the given `duration`." +)] +#[cfg_attr( + feature = "ethexe", + doc = "Same as `wait`, but delays handling for the maximum number of blocks that can be paid for and doesn't exceed the given `duration`." +)] pub fn wait_up_to(duration: u32) -> ! { unsafe { gsys::gr_wait_up_to(duration) } } /// Resume previously paused message handling. /// -/// Suppose a message has been paused using the [`wait`] function. In that case, +/// Suppose a message has been paused using the `wait` function. In that case, /// it is possible to continue its execution by calling this function. /// /// `message_id` specifies a particular message to be taken out of the *waiting diff --git a/gstd/src/msg/async.rs b/gstd/src/msg/async.rs index 17ea8896783..270a850f36d 100644 --- a/gstd/src/msg/async.rs +++ b/gstd/src/msg/async.rs @@ -16,8 +16,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +#[cfg(not(feature = "ethexe"))] +use crate::ActorId; use crate::{ - ActorId, Config, MessageId, + Config, MessageId, async_runtime::{self, Lock, ReplyPoll, signals}, errors::{Error, Result}, prelude::Vec, @@ -159,6 +161,7 @@ impl_futures!( /// } /// # fn main() {} /// ``` +#[cfg(not(feature = "ethexe"))] pub struct CodecCreateProgramFuture { /// A message identifier for an expected reply. pub waiting_reply_to: MessageId, @@ -177,6 +180,7 @@ pub struct CodecCreateProgramFuture { pub(crate) _marker: PhantomData, } +#[cfg(not(feature = "ethexe"))] impl_futures!( CodecCreateProgramFuture, D, From 48a939a7f18e585ebb55b5f3dd702eb2b5a43989 Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Tue, 5 May 2026 19:18:20 +0300 Subject: [PATCH 08/10] fmt --- gcore/src/exec.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/gcore/src/exec.rs b/gcore/src/exec.rs index ff34347c23a..33a9375f1de 100644 --- a/gcore/src/exec.rs +++ b/gcore/src/exec.rs @@ -356,8 +356,14 @@ pub fn wait() -> ! { unsafe { gsys::gr_wait() } } -#[cfg_attr(not(feature = "ethexe"), doc = "Same as [`wait`], but delays handling for a specific number of blocks.")] -#[cfg_attr(feature = "ethexe", doc = "Same as `wait`, but delays handling for a specific number of blocks.")] +#[cfg_attr( + not(feature = "ethexe"), + doc = "Same as [`wait`], but delays handling for a specific number of blocks." +)] +#[cfg_attr( + feature = "ethexe", + doc = "Same as `wait`, but delays handling for a specific number of blocks." +)] /// /// # Panics /// From 489a215bfe1b5d8104652dc78db6c3d54bbfc60f Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Wed, 6 May 2026 11:06:12 +0300 Subject: [PATCH 09/10] remove gtest/ethexe --- examples/ctor/Cargo.toml | 2 +- examples/panic-payload/Cargo.toml | 2 +- gtest/Cargo.toml | 4 ---- gtest/src/lib.rs | 12 ------------ gtest/src/manager/block_exec.rs | 6 +++--- gtest/src/manager/memory.rs | 5 +++-- gtest/src/program.rs | 6 +++--- 7 files changed, 11 insertions(+), 26 deletions(-) diff --git a/examples/ctor/Cargo.toml b/examples/ctor/Cargo.toml index 2d7c11e69c8..004deaf1410 100644 --- a/examples/ctor/Cargo.toml +++ b/examples/ctor/Cargo.toml @@ -21,4 +21,4 @@ gear-wasm-builder.workspace = true debug = ["gstd/debug"] default = ["std"] std = [] -ethexe = ["gstd/ethexe", "gtest/ethexe"] +ethexe = ["gstd/ethexe"] diff --git a/examples/panic-payload/Cargo.toml b/examples/panic-payload/Cargo.toml index dcb43b89481..9373b6cb214 100644 --- a/examples/panic-payload/Cargo.toml +++ b/examples/panic-payload/Cargo.toml @@ -22,4 +22,4 @@ gear-wasm-builder.workspace = true debug = ["gstd/debug"] default = ["std"] std = [] -ethexe = ["gstd/ethexe", "gtest/ethexe"] +ethexe = ["gstd/ethexe"] diff --git a/gtest/Cargo.toml b/gtest/Cargo.toml index 3b72145b4c5..88cec179e11 100644 --- a/gtest/Cargo.toml +++ b/gtest/Cargo.toml @@ -48,7 +48,3 @@ demo-futures-unordered.workspace = true demo-constructor = { workspace = true, features = ["std"] } demo-delayed-sender.workspace = true gear-core = { workspace = true, features = ["mock"] } - -[features] -## Disables unsupported syscalls and their calls for executing on ethexe. -ethexe = ["gprimitives/ethexe", "gsys/ethexe"] diff --git a/gtest/src/lib.rs b/gtest/src/lib.rs index 6abf2be0b86..01caf9c1e81 100644 --- a/gtest/src/lib.rs +++ b/gtest/src/lib.rs @@ -521,8 +521,6 @@ pub(crate) use constants::*; /// Module containing constants of Gear protocol. pub mod constants { - use gear_core::code::SyscallKind; - /* Constant types */ use gear_common::GasMultiplier; @@ -536,16 +534,6 @@ pub mod constants { /// Numeric type representing blocks in Gear protocol. pub type BlockNumber = u32; - /* Syscall-related constants */ - - /// Syscall kind for executing syscalls in Gear protocol (Vara). - #[cfg(not(feature = "ethexe"))] - pub(crate) const SYSCALL_KIND: SyscallKind = SyscallKind::Vara; - - /// Syscall kind for executing syscalls in Gear protocol (Vara.ETH). - #[cfg(feature = "ethexe")] - pub(crate) const SYSCALL_KIND: SyscallKind = SyscallKind::Eth; - /* Gas logic related constants */ /// Gas allowance for executing user dispatch and set of generated diff --git a/gtest/src/manager/block_exec.rs b/gtest/src/manager/block_exec.rs index 56c733a1945..5627dbd948e 100644 --- a/gtest/src/manager/block_exec.rs +++ b/gtest/src/manager/block_exec.rs @@ -18,7 +18,7 @@ use super::*; use crate::{ - SYSCALL_KIND, WasmProgram, + WasmProgram, builtins::{self, BLS12_381_ID, BlsOpsGasCostsImpl, ETH_BRIDGE_ID}, state::{ blocks, @@ -33,7 +33,7 @@ use core_processor::{ ContextCharged, ForProgram, ProcessExecutionContext, SystemReservationContext, }; use gear_core::{ - code::{InstrumentedCodeAndMetadata, MAX_WASM_PAGES_AMOUNT}, + code::{InstrumentedCodeAndMetadata, MAX_WASM_PAGES_AMOUNT, SyscallKind}, gas::GasCounter, limited::LimitedStr, message::{ContextOutcomeDrain, DispatchKind, MessageContext, ReplyPacket, StoredDispatch}, @@ -630,7 +630,7 @@ impl ExtManager { metadata: code_metadata, }, balance, - SYSCALL_KIND, + SyscallKind::Vara, ), ( blocks::current_epoch_random(), diff --git a/gtest/src/manager/memory.rs b/gtest/src/manager/memory.rs index b12494a0789..6f9fd0dcadb 100644 --- a/gtest/src/manager/memory.rs +++ b/gtest/src/manager/memory.rs @@ -17,7 +17,8 @@ // along with this program. If not, see . use super::*; -use crate::{SYSCALL_KIND, state::programs::GTestProgram}; +use crate::state::programs::GTestProgram; +use gear_core::code::SyscallKind; impl ExtManager { /// Call non-void meta function from actor stored in manager. @@ -70,7 +71,7 @@ impl ExtManager { payload, MAX_USER_GAS_LIMIT, self.blocks_manager.get(), - SYSCALL_KIND, + SyscallKind::Vara, ) .map_err(TestError::ReadStateError) } diff --git a/gtest/src/program.rs b/gtest/src/program.rs index 0d29c0bcd27..b09c80ba7fa 100644 --- a/gtest/src/program.rs +++ b/gtest/src/program.rs @@ -17,7 +17,7 @@ // along with this program. If not, see . use crate::{ - MAX_USER_GAS_LIMIT, Result, SYSCALL_KIND, Value, default_users_list, + MAX_USER_GAS_LIMIT, Result, Value, default_users_list, error::usage_panic, manager::{CUSTOM_WASM_PROGRAM_CODE_ID, ExtManager}, state::programs::{GTestProgram, PLACEHOLDER_MESSAGE_ID, ProgramsStorageManager}, @@ -25,7 +25,7 @@ use crate::{ }; use gear_common::Origin; use gear_core::{ - code::{Code, CodeAndId, InstrumentedCodeAndMetadata}, + code::{Code, CodeAndId, InstrumentedCodeAndMetadata, SyscallKind}, gas_metering::Schedule, ids::{ActorId, CodeId, MessageId, prelude::*}, message::{Dispatch, DispatchKind, Message}, @@ -276,7 +276,7 @@ impl ProgramBuilder { schedule.limits.data_segments_amount.into(), schedule.limits.type_section_len.into(), schedule.limits.parameters.into(), - SYSCALL_KIND, + SyscallKind::Vara, ) .expect("Failed to create Program from provided code"); From 34777a4b513e80b20762195a221854c5b47ebbe6 Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Wed, 6 May 2026 17:57:34 +0300 Subject: [PATCH 10/10] fix tests --- ethexe/processor/src/tests.rs | 28 ---------------------------- utils/wasm-instrument/src/tests.rs | 5 ++++- 2 files changed, 4 insertions(+), 29 deletions(-) diff --git a/ethexe/processor/src/tests.rs b/ethexe/processor/src/tests.rs index d8ecf631cda..deb9797a4e7 100644 --- a/ethexe/processor/src/tests.rs +++ b/ethexe/processor/src/tests.rs @@ -1436,34 +1436,6 @@ async fn insufficient_executable_balance_still_charged() { assert!(exec_balance_after < INSUFFICIENT_EXECUTABLE_BALANCE); } -#[tokio::test] -async fn call_gr_wait_is_forbidden() { - init_logger(); - - let wat = r#" - (module - (import "env" "memory" (memory 0)) - (import "env" "gr_wait" (func $wait)) - (export "init" (func $init)) - (func $init call $wait) - ) - "#; - - let transitions = simple_init_test(wat_to_wasm(wat).1).await; - let reply_code = transitions.current_messages()[0] - .1 - .reply_details - .expect("must be reply") - .to_reply_code(); - assert_eq!( - reply_code, - ReplyCode::Error(ErrorReplyReason::Execution( - SimpleExecutionError::BackendError - )), - "Forbidden syscall should return backend error" - ); -} - #[tokio::test] async fn call_wake_with_delay_is_unsupported() { init_logger(); diff --git a/utils/wasm-instrument/src/tests.rs b/utils/wasm-instrument/src/tests.rs index 7e199f1a011..096abe3dd4b 100644 --- a/utils/wasm-instrument/src/tests.rs +++ b/utils/wasm-instrument/src/tests.rs @@ -575,10 +575,12 @@ fn check_syscall_err_ptr_position() { fn ethexe_syscall_availability_matches_gsys_cfg_gates() { let unavailable = [ SyscallName::CreateProgramWGas, + SyscallName::CreateProgram, SyscallName::ReplyDeposit, SyscallName::SignalCode, - SyscallName::SignalFrom, + SyscallName::Random, SyscallName::ReplyCommitWGas, + SyscallName::SignalFrom, SyscallName::ReplyInputWGas, SyscallName::ReplyWGas, SyscallName::ReservationReplyCommit, @@ -591,6 +593,7 @@ fn ethexe_syscall_availability_matches_gsys_cfg_gates() { SyscallName::SendWGas, SyscallName::SystemReserveGas, SyscallName::UnreserveGas, + SyscallName::Wait, ]; for syscall in SyscallName::instrumentable(SyscallKind::Vara) {