diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index a3f7fdde5f1..347e63342a6 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -61,6 +61,9 @@ jobs: - name: "Check: Compiling gstd on stable" run: cargo +stable check -p gstd + - name: "Check: crates-io packages" + run: cargo run --release -p crates-io check + fuzzer: runs-on: [kuberunner, github-runner-01] env: diff --git a/.github/workflows/crates-io.yml b/.github/workflows/crates-io.yml index 130f2c24041..b668ff89674 100644 --- a/.github/workflows/crates-io.yml +++ b/.github/workflows/crates-io.yml @@ -11,8 +11,6 @@ on: description: "Workspace version to publish" required: true type: string - pull_request: - branches: [master] env: CARGO_INCREMENTAL: 0 @@ -33,8 +31,9 @@ jobs: uses: dsherret/rust-toolchain-file@v1 - name: "Check packages" + if: ${{ !inputs.publish }} run: cargo run --release -p crates-io check - name: "Publish packages" - if: ${{ github.event_name == 'workflow_dispatch' && inputs.publish }} + if: ${{ inputs.publish }} run: cargo run --release -p crates-io publish -v ${{ inputs.version }} diff --git a/Cargo.lock b/Cargo.lock index 215884fa711..14f45870739 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1234,6 +1234,26 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aca749d3d3f5b87a0d6100509879f9cf486ab510803a4a4e1001da1ff61c2bd6" +[[package]] +name = "const_format" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a214c7af3d04997541b18d432afaff4c455e79e2029079647e72fc2bd27673" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + [[package]] name = "constant_time_eq" version = "0.1.5" @@ -4678,7 +4698,9 @@ dependencies = [ name = "gstd" version = "1.0.5" dependencies = [ + "arrayvec 0.7.4", "bs58 0.5.0", + "const_format", "document-features", "futures", "galloc", diff --git a/Cargo.toml b/Cargo.toml index c0ee5953723..e224ac058ed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -185,7 +185,7 @@ gcli = { path = "gcli" } gclient = { path = "gclient" } gsdk = { path = "gsdk" } gsdk-codegen = { path = "gsdk/codegen" } -gstd = { path = "gstd", features = [ "nightly" ] } +gstd = { path = "gstd", features = ["nightly"] } gstd-codegen = { path = "gstd/codegen" } gsys = { path = "gsys" } gtest = { path = "gtest" } diff --git a/core-backend/src/env.rs b/core-backend/src/env.rs index fa5861e31b1..05a4ae6cc4f 100644 --- a/core-backend/src/env.rs +++ b/core-backend/src/env.rs @@ -201,7 +201,6 @@ where builder.add_func(GasAvailable, wrap_syscall!(gas_available)); builder.add_func(Leave, wrap_syscall!(leave)); builder.add_func(MessageId, wrap_syscall!(message_id)); - builder.add_func(PayProgramRent, wrap_syscall!(pay_program_rent)); builder.add_func(ProgramId, wrap_syscall!(program_id)); builder.add_func(Random, wrap_syscall!(random)); builder.add_func(Read, wrap_syscall!(read)); diff --git a/core-backend/src/error.rs b/core-backend/src/error.rs index b4fd2e926b7..137f6dc4cd0 100644 --- a/core-backend/src/error.rs +++ b/core-backend/src/error.rs @@ -225,7 +225,7 @@ pub enum TrapExplanation { ProgramAllocOutOfBounds, #[display(fmt = "Syscall unrecoverable error: {_0}")] UnrecoverableExt(UnrecoverableExtError), - #[display(fmt = "{_0}")] + #[display(fmt = "Panic occurred: {_0}")] Panic(LimitedStr<'static>), #[display(fmt = "Stack limit exceeded")] StackLimitExceeded, diff --git a/core-backend/src/funcs.rs b/core-backend/src/funcs.rs index ea0cc7f175e..5f52049629b 100644 --- a/core-backend/src/funcs.rs +++ b/core-backend/src/funcs.rs @@ -48,9 +48,9 @@ use gear_sandbox::{default_executor::Caller, ReturnValue, Value}; use gear_sandbox_env::{HostError, WasmReturnValue}; use gear_wasm_instrument::SystemBreakCode; use gsys::{ - BlockNumberWithHash, ErrorBytes, ErrorWithBlockNumberAndValue, ErrorWithGas, ErrorWithHandle, - ErrorWithHash, ErrorWithReplyCode, ErrorWithSignalCode, ErrorWithTwoHashes, Gas, Hash, - HashWithValue, TwoHashesWithValue, + BlockNumberWithHash, ErrorBytes, ErrorWithGas, ErrorWithHandle, ErrorWithHash, + ErrorWithReplyCode, ErrorWithSignalCode, ErrorWithTwoHashes, Gas, Hash, HashWithValue, + TwoHashesWithValue, }; const PTR_SPECIAL: u32 = u32::MAX; @@ -1132,24 +1132,6 @@ where }) } - pub fn pay_program_rent(rent_pid_ptr: u32) -> impl Syscall { - FallibleSyscall::new::( - RuntimeCosts::PayProgramRent, - move |ctx: &mut CallerWrap| { - let read_rent_pid = ctx.manager.register_read_as(rent_pid_ptr); - - let HashWithValue { - hash: program_id, - value: rent, - } = ctx.read_as(read_rent_pid)?; - - ctx.ext_mut() - .pay_program_rent(program_id.into(), rent) - .map_err(Into::into) - }, - ) - } - pub fn source(source_ptr: u32) -> impl Syscall { InfallibleSyscall::new(RuntimeCosts::Source, move |ctx: &mut CallerWrap| { let source = ctx.ext_mut().source()?; diff --git a/core-backend/src/mock.rs b/core-backend/src/mock.rs index 138ee7d843a..a0a725b8a9e 100644 --- a/core-backend/src/mock.rs +++ b/core-backend/src/mock.rs @@ -185,13 +185,6 @@ impl Externalities for MockExt { fn message_id(&self) -> Result { Ok(0.into()) } - fn pay_program_rent( - &mut self, - _program_id: ProgramId, - _rent: u128, - ) -> Result<(u128, u32), Self::UnrecoverableError> { - Ok((0, 0)) - } fn program_id(&self) -> Result { Ok(0.into()) } diff --git a/core-errors/src/lib.rs b/core-errors/src/lib.rs index d8c974ccc5d..69f4dd70aa1 100644 --- a/core-errors/src/lib.rs +++ b/core-errors/src/lib.rs @@ -188,18 +188,6 @@ pub enum ReservationError { ReservationBelowMailboxThreshold = 504, } -/// Program rent error. -#[derive( - Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, Sequence, derive_more::Display, -)] -#[non_exhaustive] -#[repr(u32)] -pub enum ProgramRentError { - /// The error occurs when program's paid block count is maximum. - #[display(fmt = "Rent block count limit has been reached")] - MaximumBlockCountPaid = 600, -} - /// An error occurred in API. #[derive( Debug, @@ -232,10 +220,6 @@ pub enum ExtError { #[display(fmt = "Reservation error: {_0}")] Reservation(ReservationError), - /// Program rent error. - #[display(fmt = "Program rent error: {_0}")] - ProgramRent(ProgramRentError), - /// There is a new error variant old program don't support. Unsupported, } @@ -248,7 +232,6 @@ impl ExtError { ExtError::Memory(err) => err as u32, ExtError::Message(err) => err as u32, ExtError::Reservation(err) => err as u32, - ExtError::ProgramRent(err) => err as u32, ExtError::Unsupported => u32::MAX, } } @@ -287,9 +270,8 @@ impl ExtError { 503 => Some(ReservationError::ZeroReservationAmount.into()), 504 => Some(ReservationError::ReservationBelowMailboxThreshold.into()), // - 600 => Some(ProgramRentError::MaximumBlockCountPaid.into()), - // 0xffff /* SyscallUsage */ | + 600 /* ProgramRent(ProgramRentError::MaximumBlockCountPaid) */ | u32::MAX => Some(ExtError::Unsupported), _ => None, } @@ -360,7 +342,10 @@ mod tests { /// if we accidentally re-use such codes #[test] fn error_codes_forbidden() { - let codes = [0xffff /* SyscallUsage */]; + let codes = [ + 0xffff, /* SyscallUsage */ + 600, /* ProgramRent(ProgramRentError::MaximumBlockCountPaid) */ + ]; // check forbidden code is `Unsupported` variant now for code in codes { diff --git a/core-processor/src/ext.rs b/core-processor/src/ext.rs index 84337f4bdbb..276c0de340d 100644 --- a/core-processor/src/ext.rs +++ b/core-processor/src/ext.rs @@ -54,7 +54,7 @@ use gear_core_backend::{ }; use gear_core_errors::{ ExecutionError as FallibleExecutionError, ExtError as FallibleExtErrorCore, MessageError, - ProgramRentError, ReplyCode, ReservationError, SignalCode, + ReplyCode, ReservationError, SignalCode, }; use gear_lazy_pages_common::{GlobalsAccessConfig, LazyPagesWeights, ProcessAccessError, Status}; use gear_wasm_instrument::syscalls::SyscallName; @@ -255,12 +255,6 @@ impl From for FallibleExtError { } } -impl From for FallibleExtError { - fn from(err: ProgramRentError) -> Self { - Self::Core(FallibleExtErrorCore::ProgramRent(err)) - } -} - impl From for FallibleExtError { fn from(err: ReservationError) -> Self { Self::Core(FallibleExtErrorCore::Reservation(err)) @@ -991,14 +985,6 @@ impl Externalities for Ext { Ok(self.context.message_context.current().id()) } - fn pay_program_rent( - &mut self, - _program_id: ProgramId, - rent: u128, - ) -> Result<(u128, u32), Self::FallibleError> { - Ok((rent, 0)) - } - fn program_id(&self) -> Result { Ok(self.context.program_id) } diff --git a/core/src/costs.rs b/core/src/costs.rs index fcd5d9887d9..47b38be2a47 100644 --- a/core/src/costs.rs +++ b/core/src/costs.rs @@ -118,9 +118,6 @@ pub struct HostFnWeights { /// Weight of calling `gr_message_id`. pub gr_message_id: u64, - /// Weight of calling `gr_pay_program_rent`. - pub gr_pay_program_rent: u64, - /// Weight of calling `gr_program_id`. pub gr_program_id: u64, @@ -346,8 +343,6 @@ pub enum RuntimeCosts { GasAvailable, /// Weight of calling `gr_message_id`. MsgId, - /// Weight of calling `gr_pay_program_rent`. - PayProgramRent, /// Weight of calling `gr_program_id`. ProgramId, /// Weight of calling `gr_source`. @@ -484,7 +479,6 @@ impl RuntimeCosts { SystemReserveGas => s.gr_system_reserve_gas, GasAvailable => s.gr_gas_available, MsgId => s.gr_message_id, - PayProgramRent => s.gr_pay_program_rent, ProgramId => s.gr_program_id, Source => s.gr_source, Value => s.gr_value, diff --git a/core/src/env.rs b/core/src/env.rs index 4cfdd7c22bc..e147fa8ae3e 100644 --- a/core/src/env.rs +++ b/core/src/env.rs @@ -304,13 +304,6 @@ pub trait Externalities { /// Get the id of the message currently being handled. fn message_id(&self) -> Result; - /// Pay rent for the specified program. - fn pay_program_rent( - &mut self, - program_id: ProgramId, - rent: u128, - ) -> Result<(u128, u32), Self::FallibleError>; - /// Get the id of program itself fn program_id(&self) -> Result; diff --git a/examples/syscalls/src/lib.rs b/examples/syscalls/src/lib.rs index 9577560ea96..216fec67c9b 100644 --- a/examples/syscalls/src/lib.rs +++ b/examples/syscalls/src/lib.rs @@ -48,8 +48,6 @@ pub enum Kind { Size(u32), // Expected(message id) MessageId(MessageId), - // Params(program id, rent) - PayProgramRent(ActorId, u128, Option<(u128, u32)>), // Expected(program id) ProgramId(ActorId), // Expected(message sender) @@ -103,7 +101,5 @@ pub enum Kind { ReplyDeposit(u64), } -pub const PAY_PROGRAM_RENT_EXPECT: &str = "Unable to pay rent"; - #[cfg(not(feature = "wasm-wrapper"))] mod wasm; diff --git a/examples/syscalls/src/wasm.rs b/examples/syscalls/src/wasm.rs index 79d24a48a7a..eaf979d61ad 100644 --- a/examples/syscalls/src/wasm.rs +++ b/examples/syscalls/src/wasm.rs @@ -160,15 +160,6 @@ fn process(syscall_kind: Kind) { let actual_mid: [u8; 32] = msg::id().into(); assert_eq!(expected_mid, actual_mid, "Kind::MessageId: mid test failed"); } - #[allow(deprecated)] - Kind::PayProgramRent(program_id, rent, expected) => { - let (unused_value, paid_block_count) = exec::pay_program_rent(program_id.into(), rent) - .expect(super::PAY_PROGRAM_RENT_EXPECT); - if let Some((expected_unused_value, expected_paid_block_count)) = expected { - assert_eq!(unused_value, expected_unused_value); - assert_eq!(paid_block_count, expected_paid_block_count); - } - } Kind::ProgramId(expected_pid) => { let actual_pid: [u8; 32] = exec::program_id().into(); assert_eq!(expected_pid, actual_pid, "Kind::ProgramId: pid test failed"); diff --git a/examples/waiter/tests/utils/mod.rs b/examples/waiter/tests/utils/mod.rs index 108f36fa700..ba695ea6505 100644 --- a/examples/waiter/tests/utils/mod.rs +++ b/examples/waiter/tests/utils/mod.rs @@ -13,10 +13,6 @@ pub fn assert_panicked(result: &RunResult, panic_msg: &str) { ))) )); let payload = String::from_utf8(result.log()[0].payload().into()) - .expect("Unable to decode panic message") - .split(',') - .map(String::from) - .next() - .expect("Unable to split panic message"); - assert_eq!(payload, format!("'{}'", panic_msg)); + .expect("Unable to decode panic message"); + assert!(payload.contains(&format!("panicked with '{panic_msg}'"))); } diff --git a/gcli/src/meta/executor.rs b/gcli/src/meta/executor.rs index f5453a8ba8c..60394cf559b 100644 --- a/gcli/src/meta/executor.rs +++ b/gcli/src/meta/executor.rs @@ -142,7 +142,6 @@ mod env { "gr_leave" => func!(store), "gr_message_id" => func!(store, i32), "gr_system_break" => func!(store, u32), - "gr_pay_program_rent" => func!(store, i32, i32), "gr_program_id" => func!(store, i32), "gr_random" => func!(store, i32, i32), "gr_reply_code" => func!(store, i32), diff --git a/gcore/src/exec.rs b/gcore/src/exec.rs index eb7166d7360..c781a795d7a 100644 --- a/gcore/src/exec.rs +++ b/gcore/src/exec.rs @@ -26,10 +26,7 @@ use crate::{ ActorId, MessageId, ReservationId, }; use core::mem::MaybeUninit; -use gsys::{ - BlockNumberWithHash, EnvVars, ErrorWithBlockNumberAndValue, ErrorWithGas, ErrorWithHash, - HashWithValue, -}; +use gsys::{BlockNumberWithHash, EnvVars, ErrorWithGas, ErrorWithHash}; /// Get current version of environment variables. pub fn env_vars() -> EnvVars { @@ -405,36 +402,6 @@ pub fn program_id() -> ActorId { program_id } -/// Pay specified rent for the program. The result contains the remainder of -/// rent value and the count of paid blocks. -/// -/// # Examples -/// -/// ```ignore -/// use gcore::exec; -/// -/// #[no_mangle] -/// extern "C" fn handle() { -/// let (unused_value, paid_block_count) = -/// exec::pay_program_rent(exec::program_id(), 1_000_000).expect("Unable to pay rent"); -/// } -/// ``` -#[allow(warnings)] -#[deprecated = "Rent program logic is deprecated. The function is now a no-op and will be removed soon."] -pub fn pay_program_rent(program_id: ActorId, value: u128) -> Result<(u128, u32)> { - let rent_pid = HashWithValue { - hash: program_id.0, - value, - }; - - let mut res: ErrorWithBlockNumberAndValue = Default::default(); - - unsafe { gsys::gr_pay_program_rent(&rent_pid, res.as_mut_ptr()) } - - SyscallError(res.error_code).into_result()?; - Ok((res.value, res.bn)) -} - /// Get the random seed, along with the block number from which it is /// determinable by chain observers. /// diff --git a/gsdk/src/metadata/generated.rs b/gsdk/src/metadata/generated.rs index bb1a4f6e462..51c73b4575d 100644 --- a/gsdk/src/metadata/generated.rs +++ b/gsdk/src/metadata/generated.rs @@ -2318,7 +2318,6 @@ pub mod runtime_types { pub gr_system_reserve_gas: runtime_types::sp_weights::weight_v2::Weight, pub gr_gas_available: runtime_types::sp_weights::weight_v2::Weight, pub gr_message_id: runtime_types::sp_weights::weight_v2::Weight, - pub gr_pay_program_rent: runtime_types::sp_weights::weight_v2::Weight, pub gr_program_id: runtime_types::sp_weights::weight_v2::Weight, pub gr_source: runtime_types::sp_weights::weight_v2::Weight, pub gr_value: runtime_types::sp_weights::weight_v2::Weight, diff --git a/gstd/Cargo.toml b/gstd/Cargo.toml index 1c7fdf490fe..be7b500a68b 100644 --- a/gstd/Cargo.toml +++ b/gstd/Cargo.toml @@ -3,6 +3,8 @@ name = "gstd" description = "Gear programs standard library" keywords = ["gear", "std", "no-std", "wasm", "smart-contracts"] categories = ["api-bindings"] +# Stable version of Rust >=1.73 is required due to new format of panic message. +rust-version = "1.73" version.workspace = true edition.workspace = true authors.workspace = true @@ -11,6 +13,8 @@ homepage.workspace = true repository.workspace = true [dependencies] +arrayvec = { version = "0.7.4", default-features = false, optional = true } +const_format = { version = "0.2.32", optional = true } document-features = { version = "0.2.8", optional = true } galloc.workspace = true gcore = { workspace = true, features = ["codec"] } @@ -27,18 +31,45 @@ futures = { workspace = true, features = ["alloc"] } [features] #! ## Default features -default = ["panic-handler"] -## When enabled, a panic handler is provided by this crate. -panic-handler = [] +default = ["panic-message"] + +#! ## Panic handler profiles +#! We currently use the following format for panic messages from Rust code: +#! `panicked with '{message}'[ at '{location}']`. Also `Panic occurred: ` +#! will be added to the beginning of the panic message by our core-backend. +#! +#! So the final panic message looks like this: +#! `Panic occurred: panicked with '{message}'[ at '{location}']`. +#! +#! You can configure which panic handler profile you need +#! by specifying one of the following functions: + +## When enabled, a minimal panic handler is provided by this crate. +## Instead of a panic message, `` is displayed. +panic-handler = ["const_format"] +## When enabled, a panic handler will also display a panic message. +panic-message = ["panic-handler", "arrayvec"] +## When enabled, a panic handler will also display a panic message and location. +## This function is not recommended for use in production environment +## because it displays the code path. +panic-location = ["panic-message"] #! ## Nightly features +#! +#! The `panic-message` and `panic-location` features gets additional +#! optimizations when using the nightly compiler. +#! +#! For example, if you don't use the `panic-location` feature, the compiler +#! will remove all locations such as `/home/username/dapp/src/lib.rs:1:2` +#! from the binary. The size of smart contract will be reduced and +#! `/home/username/...` information will not be included in the binary. ## Enables all features below. ## These features depend on unstable Rust API and require nightly toolchain. -nightly = ["panic-messages", "oom-handler"] -## When enabled, additional context information is available from -## panic messages in debug mode. Relies on [`panic_info_message`][rust-66745]. -panic-messages = [] +nightly = ["panic-info-message", "oom-handler"] +## When enabled, a panic handler will use a more efficient implementation. +## Relies on [`panic_info_message`][rust-66745]. +panic-info-message = [] ## When enabled, an OOM error handler is provided. ## Relies on [`alloc_error_handler`][rust-51540], oom-handler = [] diff --git a/gstd/src/common/handlers.rs b/gstd/src/common/handlers.rs index 071bb35947c..04b0bf0463a 100644 --- a/gstd/src/common/handlers.rs +++ b/gstd/src/common/handlers.rs @@ -25,50 +25,205 @@ //! debug and non-debug mode, for programs built in `wasm32` architecture. //! For `debug` mode it provides more extensive logging. +#[cfg(target_arch = "wasm32")] #[cfg(feature = "oom-handler")] #[alloc_error_handler] pub fn oom(_: core::alloc::Layout) -> ! { crate::ext::oom_panic() } - +/// We currently support 3 panic handler profiles: +/// - `panic-handler`: it displays `panicked with ''` +/// - `panic-message`: it displays `panicked with '{message}'` +/// - `panic-location`: it displays `panicked with '{message}' at '{location}'` +/// +/// How we get the panic message in different versions of Rust: +/// - In nightly Rust, we use `#![feature(panic_info_message)]` and the +/// [`write!`] macro. +/// - In stable Rust, we need to modify the default panic handler message +/// format. +/// +/// Default panic handler message format (according to ): +/// `panicked at {location}:\n{message}` +/// +/// We parse the output of `impl Display for PanicInfo<'_>` and +/// then convert it to custom format: +/// `panicked with '{message}'[ at '{location}']`. +#[cfg(target_arch = "wasm32")] #[cfg(feature = "panic-handler")] mod panic_handler { use crate::ext; use core::panic::PanicInfo; - #[cfg(not(feature = "debug"))] + mod constants { + /// This prefix is used before the panic message. + pub const PANIC_PREFIX: &str = "panicked with "; + /// This panic message is used in the minimal panic handler and when + /// internal errors occur. + #[cfg(any(feature = "panic-info-message", not(feature = "panic-message")))] + pub const UNKNOWN_REASON: &str = ""; + + /// This prefix is used by `impl Display for PanicInfo<'_>`. + #[cfg(all(not(feature = "panic-info-message"), feature = "panic-message"))] + pub const PANICKED_AT: &str = "panicked at "; + + /// Max amount of bytes allowed to be thrown as string explanation + /// of the error. + #[cfg(feature = "panic-message")] + pub const TRIMMED_MAX_LEN: usize = 1024; //TODO: do not duplicate + // `gear_core::str::TRIMMED_MAX_LEN` + } + + use constants::*; + + /// Minimal panic handler. + #[cfg(not(feature = "panic-message"))] #[panic_handler] pub fn panic(_: &PanicInfo) -> ! { - ext::panic("no info") + const MESSAGE: &str = const_format::formatcp!("{PANIC_PREFIX}'{UNKNOWN_REASON}'"); + + #[cfg(feature = "debug")] + let _ = ext::debug(MESSAGE); + + ext::panic(MESSAGE) } - #[cfg(feature = "debug")] + /// Panic handler for nightly Rust. + #[cfg(all(feature = "panic-info-message", feature = "panic-message"))] #[panic_handler] pub fn panic(panic_info: &PanicInfo) -> ! { - use crate::prelude::format; - #[cfg(not(feature = "panic-messages"))] - let message = None::<&core::fmt::Arguments<'_>>; - #[cfg(feature = "panic-messages")] - let message = panic_info.message(); - - let msg = match (message, panic_info.location()) { - (Some(msg), Some(loc)) => format!( - "'{:?}', {}:{}:{}", - msg, - loc.file(), - loc.line(), - loc.column() - ), - (Some(msg), None) => format!("'{msg:?}'"), - (None, Some(loc)) => { - format!("{}:{}:{}", loc.file(), loc.line(), loc.column()) + use crate::prelude::fmt::Write; + use arrayvec::ArrayString; + + let mut debug_msg = ArrayString::::new(); + let _ = debug_msg.try_push_str(PANIC_PREFIX); + + match (panic_info.message(), panic_info.location()) { + #[cfg(feature = "panic-location")] + (Some(msg), Some(loc)) => { + let _ = write!(&mut debug_msg, "'{msg}' at '{loc}'"); + } + #[cfg(not(feature = "panic-location"))] + (Some(msg), _) => { + let _ = write!(&mut debug_msg, "'{msg}'"); + } + _ => { + let _ = debug_msg.try_push_str(const_format::formatcp!("'{UNKNOWN_REASON}'")); } - _ => ext::panic("no info"), }; - crate::debug!("panic occurred: {msg}"); - ext::panic(&msg) + #[cfg(feature = "debug")] + let _ = ext::debug(&debug_msg); + + ext::panic(&debug_msg) + } + + /// Panic handler for stable Rust. + #[cfg(all(not(feature = "panic-info-message"), feature = "panic-message"))] + #[panic_handler] + pub fn panic(panic_info: &PanicInfo) -> ! { + use crate::prelude::fmt::{self, Write}; + use arrayvec::ArrayString; + + #[derive(Default)] + struct TempBuffer { + overflowed: bool, + buffer: ArrayString, + } + + impl TempBuffer { + #[inline] + fn write_str(&mut self, s: &str) { + if !self.overflowed && self.buffer.write_str(s).is_err() { + self.overflowed = true; + } + } + } + + #[derive(Default)] + struct TempOutput { + found_prefix: bool, + found_delimiter: bool, + #[cfg(feature = "panic-location")] + location: TempBuffer, + message: TempBuffer, + } + + impl fmt::Write for TempOutput { + fn write_str(&mut self, s: &str) -> fmt::Result { + if !self.found_prefix && s.len() == PANICKED_AT.len() { + self.found_prefix = true; + return Ok(()); + } + + if !self.found_delimiter { + if s == ":\n" { + self.found_delimiter = true; + return Ok(()); + } + #[cfg(feature = "panic-location")] + self.location.write_str(s); + } else { + self.message.write_str(s); + } + + Ok(()) + } + } + + let mut output = TempOutput::default(); + let _ = write!(&mut output, "{panic_info}"); + + #[cfg(feature = "panic-location")] + let location = &*output.location.buffer; + let message = &*output.message.buffer; + + let mut debug_msg = ArrayString::::new(); + let _ = debug_msg.try_push_str(PANIC_PREFIX); + + #[cfg(feature = "panic-location")] + for s in ["'", message, "' at '", location, "'"] { + if debug_msg.try_push_str(s).is_err() { + break; + } + } + + #[cfg(not(feature = "panic-location"))] + for s in ["'", message, "'"] { + if debug_msg.try_push_str(s).is_err() { + break; + } + } + + #[cfg(feature = "debug")] + let _ = ext::debug(&debug_msg); + + ext::panic(&debug_msg) + } +} + +#[cfg(test)] +mod tests { + extern crate std; + + use std::{format, panic, prelude::v1::*}; + + /// Here is a test to verify that the default panic handler message + /// format has not changed. + #[test] + fn panic_msg_format_not_changed() { + const MESSAGE: &str = "message"; + + panic::set_hook(Box::new(|panic_info| { + let location = panic_info.location().unwrap(); + assert_eq!( + panic_info.to_string(), + format!("panicked at {location}:\n{MESSAGE}") + ); + })); + + let result = panic::catch_unwind(|| { + panic!("{MESSAGE}"); + }); + assert!(result.is_err()); } } -#[cfg(feature = "panic-handler")] -pub use panic_handler::*; diff --git a/gstd/src/common/mod.rs b/gstd/src/common/mod.rs index a9e065da018..aad7044a550 100644 --- a/gstd/src/common/mod.rs +++ b/gstd/src/common/mod.rs @@ -19,6 +19,5 @@ //! Common modules for each Gear smart contract. pub mod errors; -#[cfg(target_arch = "wasm32")] mod handlers; pub mod primitives; diff --git a/gstd/src/exec/basic.rs b/gstd/src/exec/basic.rs index 517fc7ab4e5..2f1e4d1ac24 100644 --- a/gstd/src/exec/basic.rs +++ b/gstd/src/exec/basic.rs @@ -109,26 +109,6 @@ pub fn wake_delayed(message_id: MessageId, delay: u32) -> Result<()> { gcore::exec::wake_delayed(message_id.into(), delay).map_err(Into::into) } -/// Pay specified rent for the program. The result contains the remainder of -/// rent value and the count of paid blocks. -/// -/// # Examples -/// -/// ```ignore -/// use gstd::exec; -/// -/// #[no_mangle] -/// extern "C" fn handle() { -/// let (_unused_value, paid_block_count) = -/// exec::pay_program_rent(exec::program_id(), 1_000_000).expect("Unable to pay rent"); -/// } -/// ``` -#[allow(warnings)] -#[deprecated = "Rent program logic is deprecated. The function is now a no-op and will be removed soon."] -pub fn pay_program_rent(program_id: ActorId, value: u128) -> Result<(u128, u32)> { - Ok(gcore::exec::pay_program_rent(program_id.into(), value)?) -} - /// Return the identifier of the current program. /// /// # Examples diff --git a/gstd/src/lib.rs b/gstd/src/lib.rs index 74a408879bb..448ff67e71d 100644 --- a/gstd/src/lib.rs +++ b/gstd/src/lib.rs @@ -28,6 +28,10 @@ //! asynchronous programming primitives, arbitrary types encoding/decoding, //! providing convenient instruments for creating programs from programs, etc. //! +//! # Minimum supported Rust version +//! This crate requires **Rust >= 1.73** due to the implementation of the panic +//! handler in the stable version. +//! //! # Crate features #![cfg_attr( feature = "document-features", @@ -129,7 +133,11 @@ #![no_std] #![warn(missing_docs)] #![cfg_attr( - all(target_arch = "wasm32", feature = "panic-messages",), + all( + target_arch = "wasm32", + feature = "panic-info-message", + feature = "panic-message" + ), feature(panic_info_message) )] #![cfg_attr( diff --git a/gsys/src/lib.rs b/gsys/src/lib.rs index 41719242c0f..da60b8fa381 100644 --- a/gsys/src/lib.rs +++ b/gsys/src/lib.rs @@ -274,37 +274,6 @@ where } } -/// Represents type defining concatenated block number and value with error code. 24 bytes. -#[repr(C, packed)] -#[derive(Default, Debug)] -pub struct ErrorWithBlockNumberAndValue { - pub error_code: ErrorCode, - pub bn: BlockNumber, - pub value: Value, -} - -impl ErrorWithBlockNumberAndValue { - pub fn as_mut_ptr(&mut self) -> *mut Self { - self as _ - } -} - -impl From> for ErrorWithBlockNumberAndValue { - fn from(result: Result<(Value, BlockNumber), ErrorCode>) -> Self { - let mut res: Self = Default::default(); - - match result { - Ok((v, bn)) => { - res.value = v; - res.bn = bn; - } - Err(code) => res.error_code = code, - } - - res - } -} - /// Represents type defining concatenated two hashes. 64 bytes. #[repr(C, packed)] #[derive(Default, Debug)] @@ -534,17 +503,6 @@ extern "C" { /// - `message_id`: `const ptr` for message id. pub fn gr_message_id(message_id: *mut Hash); - /// Fallible `gr_pay_program_rent` control syscall. - /// - /// Arguments type: - /// - `rent_pid`: `const ptr` for program id and rent value. - /// - `err_bn_value`: `mut ptr` for concatenated error code, paid block count and unused rent value. - #[deprecated] - pub fn gr_pay_program_rent( - rent_pid: *const HashWithValue, - err_bn_value: *mut ErrorWithBlockNumberAndValue, - ); - /// Infallible `gr_program_id` get syscall. /// /// Arguments type: diff --git a/gtest/src/program.rs b/gtest/src/program.rs index 6ad4507f52a..8989b5f7c49 100644 --- a/gtest/src/program.rs +++ b/gtest/src/program.rs @@ -856,7 +856,9 @@ mod tests { assert!(run_result.main_failed()); let log = run_result.log(); - assert!(log[0].payload().starts_with(b"'Failed to load destination")); + let panic_msg_payload = + String::from_utf8(log[0].payload().into()).expect("Unable to decode panic message"); + assert!(panic_msg_payload.contains("panicked with 'Failed to load destination")); let run_result = prog.send(user_id, String::from("should_be_skipped")); diff --git a/pallets/gear/src/benchmarking/mod.rs b/pallets/gear/src/benchmarking/mod.rs index 54ac27154b8..0ca6b6acb07 100644 --- a/pallets/gear/src/benchmarking/mod.rs +++ b/pallets/gear/src/benchmarking/mod.rs @@ -1400,14 +1400,6 @@ benchmarks! { verify_process(res.unwrap()); } - gr_pay_program_rent { - let r in 0 .. API_BENCHMARK_BATCHES; - let mut res = None; - let exec = Benches::::gr_pay_program_rent(r)?; - }: { - res.replace(run_process(exec)); - } - lazy_pages_signal_read { let p in 0 .. code::max_pages::() as u32; let mut res = None; diff --git a/pallets/gear/src/benchmarking/syscalls.rs b/pallets/gear/src/benchmarking/syscalls.rs index 1feb83a02f4..71de5a4d205 100644 --- a/pallets/gear/src/benchmarking/syscalls.rs +++ b/pallets/gear/src/benchmarking/syscalls.rs @@ -1500,27 +1500,6 @@ where Self::prepare_handle(module, 0) } - pub fn gr_pay_program_rent(r: u32) -> Result, &'static str> { - let pid_value_offset = COMMON_OFFSET; - let res_offset = pid_value_offset + PID_SIZE + VALUE_SIZE; - - let module = ModuleDefinition { - memory: Some(ImportedMemory::new(SMALL_MEM_SIZE)), - imported_functions: vec![SyscallName::PayProgramRent], - handle_body: Some(body::fallible_syscall( - r, - res_offset, - &[ - // block_number & program_id offset - InstrI32Const(pid_value_offset), - ], - )), - ..Default::default() - }; - - Self::prepare_handle(module, 10_000_000) - } - pub fn lazy_pages_signal_read(wasm_pages: WasmPage) -> Result, &'static str> { let instrs = body::read_access_all_pages_instrs(wasm_pages, vec![]); let module = ModuleDefinition { diff --git a/pallets/gear/src/benchmarking/tests/syscalls_integrity.rs b/pallets/gear/src/benchmarking/tests/syscalls_integrity.rs index 78d67c79447..b7e3cd1ca5e 100644 --- a/pallets/gear/src/benchmarking/tests/syscalls_integrity.rs +++ b/pallets/gear/src/benchmarking/tests/syscalls_integrity.rs @@ -268,7 +268,6 @@ where SyscallName::ReservationReply => check_gr_reservation_reply::(), SyscallName::ReservationReplyCommit => check_gr_reservation_reply_commit::(), SyscallName::SystemReserveGas => check_gr_system_reserve_gas::(), - SyscallName::PayProgramRent => { /*no need for tests */ } } }); } diff --git a/pallets/gear/src/lib.rs b/pallets/gear/src/lib.rs index d45f29c14cb..ae0e75c32db 100644 --- a/pallets/gear/src/lib.rs +++ b/pallets/gear/src/lib.rs @@ -483,12 +483,6 @@ pub mod pallet { where T::AccountId: Origin, { - fn on_runtime_upgrade() -> Weight { - log::debug!(target: "gear::runtime", "⚙️ Runtime upgrade"); - - Zero::zero() - } - /// Initialization fn on_initialize(bn: BlockNumberFor) -> Weight { // Incrementing Gear block number diff --git a/pallets/gear/src/schedule.rs b/pallets/gear/src/schedule.rs index cb2d0d0fd00..ff70be4d04f 100644 --- a/pallets/gear/src/schedule.rs +++ b/pallets/gear/src/schedule.rs @@ -366,9 +366,6 @@ pub struct HostFnWeights { /// Weight of calling `gr_message_id`. pub gr_message_id: Weight, - /// Weight of calling `gr_pay_program_rent`. - pub gr_pay_program_rent: Weight, - /// Weight of calling `gr_program_id`. pub gr_program_id: Weight, @@ -871,7 +868,6 @@ impl HostFnWeights { gr_system_reserve_gas: self.gr_system_reserve_gas.ref_time(), gr_gas_available: self.gr_gas_available.ref_time(), gr_message_id: self.gr_message_id.ref_time(), - gr_pay_program_rent: self.gr_pay_program_rent.ref_time(), gr_program_id: self.gr_program_id.ref_time(), gr_source: self.gr_source.ref_time(), gr_value: self.gr_value.ref_time(), @@ -995,7 +991,6 @@ impl Default for HostFnWeights { gr_unreserve_gas: to_weight!(cost!(gr_unreserve_gas)), gr_gas_available: to_weight!(cost_batched!(gr_gas_available)), gr_message_id: to_weight!(cost_batched!(gr_message_id)), - gr_pay_program_rent: to_weight!(cost_batched!(gr_pay_program_rent)), gr_program_id: to_weight!(cost_batched!(gr_program_id)), gr_source: to_weight!(cost_batched!(gr_source)), gr_value: to_weight!(cost_batched!(gr_value)), diff --git a/pallets/gear/src/tests.rs b/pallets/gear/src/tests.rs index b1e899d165a..ae8e9cb51f9 100644 --- a/pallets/gear/src/tests.rs +++ b/pallets/gear/src/tests.rs @@ -366,7 +366,7 @@ fn delayed_reservations_sending_validation() { run_to_next_block(None); let error_text = format!( - "{SENDING_EXPECT}: {:?}", + "panicked with '{SENDING_EXPECT}: {:?}'", GstdError::Core( ExtError::Message(MessageError::InsufficientGasForDelayedSending).into() ) @@ -403,7 +403,7 @@ fn delayed_reservations_sending_validation() { run_for_blocks(wait_for as u64 + 1, None); let error_text = format!( - "{SENDING_EXPECT}: {:?}", + "panicked with '{SENDING_EXPECT}: {:?}'", GstdError::Core( ExtError::Message(MessageError::InsufficientGasForDelayedSending).into() ) @@ -514,7 +514,7 @@ fn default_wait_lock_timeout() { run_to_block(expiration_block, None); let error_text = format!( - "ran into error-reply: {:?}", + "panicked with 'ran into error-reply: {:?}'", GstdError::Timeout( expiration_block.unique_saturated_into(), expiration_block.unique_saturated_into() @@ -7546,7 +7546,7 @@ fn test_create_program_with_value_lt_ed() { assert_total_dequeued(1); let error_text = format!( - "Failed to create program: {:?}", + "panicked with 'Failed to create program: {:?}'", GstdError::Core(ExtError::Message(MessageError::InsufficientValue).into()) ); @@ -7596,7 +7596,7 @@ fn test_create_program_with_exceeding_value() { assert_total_dequeued(1); let error_text = format!( - "Failed to create program: {:?}", + "panicked with 'Failed to create program: {:?}'", GstdError::Core(ExtError::Execution(ExecutionError::NotEnoughValue).into()) ); assert_failed( @@ -7682,7 +7682,7 @@ fn demo_constructor_works() { run_to_next_block(None); - let error_text = "I just panic every time".to_owned(); + let error_text = "panicked with 'I just panic every time'".to_owned(); assert_failed( message_id, @@ -8669,7 +8669,7 @@ fn mx_lock_ownership_exceedance() { let get_lock_ownership_exceeded_trap = |command_msg_id| { ActorExecutionErrorReplyReason::Trap(TrapExplanation::Panic( format!( - "Message 0x{} has exceeded lock ownership time", + "panicked with 'Message 0x{} has exceeded lock ownership time'", hex::encode(command_msg_id) ) .into(), diff --git a/pallets/gear/src/weights.rs b/pallets/gear/src/weights.rs index 82143acc310..6dc17aa0f1a 100644 --- a/pallets/gear/src/weights.rs +++ b/pallets/gear/src/weights.rs @@ -25,7 +25,7 @@ //! EXECUTION: , WASM-EXECUTION: Compiled, CHAIN: Some("vara-dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/gear benchmark pallet --chain=vara-dev --steps=50 --repeat=20 --pallet=pallet_gear --extrinsic=alloc,alloc_in_handle,alloc_per_page,claim_value,create_program,db_read_per_kb,db_write_per_kb,free,gr_block_height,gr_block_timestamp,gr_create_program,gr_create_program_per_kb,gr_create_program_wgas,gr_create_program_wgas_per_kb,gr_debug,gr_debug_per_kb,gr_gas_available,gr_message_id,gr_pay_program_rent,gr_program_id,gr_random,gr_read,gr_read_per_kb,gr_reply_code,gr_reply_deposit,gr_reply_per_kb,gr_reply_push,gr_reply_push_input,gr_reply_push_input_per_kb,gr_reply_push_per_kb,gr_reply_to,gr_reply_wgas_per_kb,gr_reservation_reply_commit_per_kb,gr_reservation_reply_per_kb,gr_reservation_send,gr_reservation_send_commit,gr_reservation_send_per_kb,gr_reserve_gas,gr_send,gr_send_commit,gr_send_commit_wgas,gr_send_init,gr_send_input,gr_send_input_wgas,gr_send_per_kb,gr_send_push,gr_send_push_input,gr_send_push_input_per_kb,gr_send_push_per_kb,gr_send_wgas,gr_send_wgas_per_kb,gr_signal_code,gr_signal_from,gr_size,gr_source,gr_system_reserve_gas,gr_unreserve_gas,gr_value,gr_value_available,gr_wake,initial_allocation,instantiate_module_per_kb,instr_br,instr_br_if,instr_br_table,instr_br_table_per_entry,instr_call,instr_call_const,instr_call_indirect,instr_call_indirect_per_param,instr_call_per_local,instr_global_get,instr_global_set,instr_i32add,instr_i32and,instr_i32clz,instr_i32ctz,instr_i32divs,instr_i32divu,instr_i32eq,instr_i32eqz,instr_i32extend16s,instr_i32extend8s,instr_i32ges,instr_i32geu,instr_i32gts,instr_i32gtu,instr_i32les,instr_i32leu,instr_i32load,instr_i32lts,instr_i32ltu,instr_i32mul,instr_i32ne,instr_i32or,instr_i32popcnt,instr_i32rems,instr_i32remu,instr_i32rotl,instr_i32rotr,instr_i32shl,instr_i32shrs,instr_i32shru,instr_i32store,instr_i32sub,instr_i32wrapi64,instr_i32xor,instr_i64add,instr_i64and,instr_i64clz,instr_i64ctz,instr_i64divs,instr_i64divu,instr_i64eq,instr_i64eqz,instr_i64extend16s,instr_i64extend32s,instr_i64extend8s,instr_i64extendsi32,instr_i64extendui32,instr_i64ges,instr_i64geu,instr_i64gts,instr_i64gtu,instr_i64les,instr_i64leu,instr_i64load,instr_i64lts,instr_i64ltu,instr_i64mul,instr_i64ne,instr_i64or,instr_i64popcnt,instr_i64rems,instr_i64remu,instr_i64rotl,instr_i64rotr,instr_i64shl,instr_i64shrs,instr_i64shru,instr_i64store,instr_i64sub,instr_i64xor,instr_if,instr_local_get,instr_local_set,instr_local_tee,instr_memory_current,instr_select,lazy_pages_host_func_read,lazy_pages_host_func_write,lazy_pages_host_func_write_after_read,lazy_pages_load_page_storage_data,lazy_pages_signal_read,lazy_pages_signal_write,lazy_pages_signal_write_after_read,mem_grow,pay_program_rent,reinstrument_per_kb,resume_session_commit,resume_session_init,resume_session_push,send_message,send_reply,tasks_pause_program,tasks_pause_program_uninited,tasks_remove_from_mailbox,tasks_remove_from_waitlist,tasks_remove_gas_reservation,tasks_remove_resume_session,tasks_send_dispatch,tasks_send_user_message,tasks_send_user_message_to_mailbox,tasks_wake_message,tasks_wake_message_no_wake,upload_code,upload_program --heap-pages=4096 --output=./scripts/benchmarking/weights-output/pallet_gear.rs --template=.maintain/frame-weight-template.hbs +// ./target/production/gear benchmark pallet --chain=vara-dev --steps=50 --repeat=20 --pallet=pallet_gear --extrinsic=alloc,alloc_in_handle,alloc_per_page,claim_value,create_program,db_read_per_kb,db_write_per_kb,free,gr_block_height,gr_block_timestamp,gr_create_program,gr_create_program_per_kb,gr_create_program_wgas,gr_create_program_wgas_per_kb,gr_debug,gr_debug_per_kb,gr_gas_available,gr_message_id,gr_program_id,gr_random,gr_read,gr_read_per_kb,gr_reply_code,gr_reply_deposit,gr_reply_per_kb,gr_reply_push,gr_reply_push_input,gr_reply_push_input_per_kb,gr_reply_push_per_kb,gr_reply_to,gr_reply_wgas_per_kb,gr_reservation_reply_commit_per_kb,gr_reservation_reply_per_kb,gr_reservation_send,gr_reservation_send_commit,gr_reservation_send_per_kb,gr_reserve_gas,gr_send,gr_send_commit,gr_send_commit_wgas,gr_send_init,gr_send_input,gr_send_input_wgas,gr_send_per_kb,gr_send_push,gr_send_push_input,gr_send_push_input_per_kb,gr_send_push_per_kb,gr_send_wgas,gr_send_wgas_per_kb,gr_signal_code,gr_signal_from,gr_size,gr_source,gr_system_reserve_gas,gr_unreserve_gas,gr_value,gr_value_available,gr_wake,initial_allocation,instantiate_module_per_kb,instr_br,instr_br_if,instr_br_table,instr_br_table_per_entry,instr_call,instr_call_const,instr_call_indirect,instr_call_indirect_per_param,instr_call_per_local,instr_global_get,instr_global_set,instr_i32add,instr_i32and,instr_i32clz,instr_i32ctz,instr_i32divs,instr_i32divu,instr_i32eq,instr_i32eqz,instr_i32extend16s,instr_i32extend8s,instr_i32ges,instr_i32geu,instr_i32gts,instr_i32gtu,instr_i32les,instr_i32leu,instr_i32load,instr_i32lts,instr_i32ltu,instr_i32mul,instr_i32ne,instr_i32or,instr_i32popcnt,instr_i32rems,instr_i32remu,instr_i32rotl,instr_i32rotr,instr_i32shl,instr_i32shrs,instr_i32shru,instr_i32store,instr_i32sub,instr_i32wrapi64,instr_i32xor,instr_i64add,instr_i64and,instr_i64clz,instr_i64ctz,instr_i64divs,instr_i64divu,instr_i64eq,instr_i64eqz,instr_i64extend16s,instr_i64extend32s,instr_i64extend8s,instr_i64extendsi32,instr_i64extendui32,instr_i64ges,instr_i64geu,instr_i64gts,instr_i64gtu,instr_i64les,instr_i64leu,instr_i64load,instr_i64lts,instr_i64ltu,instr_i64mul,instr_i64ne,instr_i64or,instr_i64popcnt,instr_i64rems,instr_i64remu,instr_i64rotl,instr_i64rotr,instr_i64shl,instr_i64shrs,instr_i64shru,instr_i64store,instr_i64sub,instr_i64xor,instr_if,instr_local_get,instr_local_set,instr_local_tee,instr_memory_current,instr_select,lazy_pages_host_func_read,lazy_pages_host_func_write,lazy_pages_host_func_write_after_read,lazy_pages_load_page_storage_data,lazy_pages_signal_read,lazy_pages_signal_write,lazy_pages_signal_write_after_read,mem_grow,reinstrument_per_kb,resume_session_commit,resume_session_init,resume_session_push,send_message,send_reply,tasks_pause_program,tasks_pause_program_uninited,tasks_remove_from_mailbox,tasks_remove_from_waitlist,tasks_remove_gas_reservation,tasks_remove_resume_session,tasks_send_dispatch,tasks_send_user_message,tasks_send_user_message_to_mailbox,tasks_wake_message,tasks_wake_message_no_wake,upload_code,upload_program --heap-pages=4096 --output=./scripts/benchmarking/weights-output/pallet_gear.rs --template=.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -117,7 +117,6 @@ pub trait WeightInfo { fn gr_create_program_per_kb(p: u32, s: u32, ) -> Weight; fn gr_create_program_wgas(r: u32, ) -> Weight; fn gr_create_program_wgas_per_kb(p: u32, s: u32, ) -> Weight; - fn gr_pay_program_rent(r: u32, ) -> Weight; fn lazy_pages_signal_read(p: u32, ) -> Weight; fn lazy_pages_signal_write(p: u32, ) -> Weight; fn lazy_pages_signal_write_after_read(p: u32, ) -> Weight; @@ -1069,16 +1068,6 @@ impl WeightInfo for SubstrateWeight { // Standard Error: 133_275 .saturating_add(Weight::from_parts(168_745_496, 0).saturating_mul(s.into())) } - /// The range of component `r` is `[0, 20]`. - fn gr_pay_program_rent(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 99_990_000 picoseconds. - Weight::from_parts(118_439_219, 0) - // Standard Error: 33_092 - .saturating_add(Weight::from_parts(1_902_407, 0).saturating_mul(r.into())) - } /// The range of component `p` is `[0, 512]`. fn lazy_pages_signal_read(p: u32, ) -> Weight { // Proof Size summary in bytes: @@ -2957,16 +2946,6 @@ impl WeightInfo for () { // Standard Error: 133_275 .saturating_add(Weight::from_parts(168_745_496, 0).saturating_mul(s.into())) } - /// The range of component `r` is `[0, 20]`. - fn gr_pay_program_rent(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 99_990_000 picoseconds. - Weight::from_parts(118_439_219, 0) - // Standard Error: 33_092 - .saturating_add(Weight::from_parts(1_902_407, 0).saturating_mul(r.into())) - } /// The range of component `p` is `[0, 512]`. fn lazy_pages_signal_read(p: u32, ) -> Weight { // Proof Size summary in bytes: diff --git a/runtime/vara/src/migrations.rs b/runtime/vara/src/migrations.rs index 69ada7a4857..10fb1fc6d5e 100644 --- a/runtime/vara/src/migrations.rs +++ b/runtime/vara/src/migrations.rs @@ -97,6 +97,6 @@ pub type Migrations = ( pallet_offences::migration::v1::MigrateToV1, // v1040 pallet_im_online::migration::v1::Migration, - // unreleased + // v1050 pallet_gear_program::migrations::MigrateToV3, ); diff --git a/runtime/vara/src/weights/pallet_gear.rs b/runtime/vara/src/weights/pallet_gear.rs index 7e637785eca..46d16d50dc3 100644 --- a/runtime/vara/src/weights/pallet_gear.rs +++ b/runtime/vara/src/weights/pallet_gear.rs @@ -25,7 +25,7 @@ //! EXECUTION: , WASM-EXECUTION: Compiled, CHAIN: Some("vara-dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/gear benchmark pallet --chain=vara-dev --steps=50 --repeat=20 --pallet=pallet_gear --extrinsic=alloc,alloc_in_handle,alloc_per_page,claim_value,create_program,db_read_per_kb,db_write_per_kb,free,gr_block_height,gr_block_timestamp,gr_create_program,gr_create_program_per_kb,gr_create_program_wgas,gr_create_program_wgas_per_kb,gr_debug,gr_debug_per_kb,gr_gas_available,gr_message_id,gr_pay_program_rent,gr_program_id,gr_random,gr_read,gr_read_per_kb,gr_reply_code,gr_reply_deposit,gr_reply_per_kb,gr_reply_push,gr_reply_push_input,gr_reply_push_input_per_kb,gr_reply_push_per_kb,gr_reply_to,gr_reply_wgas_per_kb,gr_reservation_reply_commit_per_kb,gr_reservation_reply_per_kb,gr_reservation_send,gr_reservation_send_commit,gr_reservation_send_per_kb,gr_reserve_gas,gr_send,gr_send_commit,gr_send_commit_wgas,gr_send_init,gr_send_input,gr_send_input_wgas,gr_send_per_kb,gr_send_push,gr_send_push_input,gr_send_push_input_per_kb,gr_send_push_per_kb,gr_send_wgas,gr_send_wgas_per_kb,gr_signal_code,gr_signal_from,gr_size,gr_source,gr_system_reserve_gas,gr_unreserve_gas,gr_value,gr_value_available,gr_wake,initial_allocation,instantiate_module_per_kb,instr_br,instr_br_if,instr_br_table,instr_br_table_per_entry,instr_call,instr_call_const,instr_call_indirect,instr_call_indirect_per_param,instr_call_per_local,instr_global_get,instr_global_set,instr_i32add,instr_i32and,instr_i32clz,instr_i32ctz,instr_i32divs,instr_i32divu,instr_i32eq,instr_i32eqz,instr_i32extend16s,instr_i32extend8s,instr_i32ges,instr_i32geu,instr_i32gts,instr_i32gtu,instr_i32les,instr_i32leu,instr_i32load,instr_i32lts,instr_i32ltu,instr_i32mul,instr_i32ne,instr_i32or,instr_i32popcnt,instr_i32rems,instr_i32remu,instr_i32rotl,instr_i32rotr,instr_i32shl,instr_i32shrs,instr_i32shru,instr_i32store,instr_i32sub,instr_i32wrapi64,instr_i32xor,instr_i64add,instr_i64and,instr_i64clz,instr_i64ctz,instr_i64divs,instr_i64divu,instr_i64eq,instr_i64eqz,instr_i64extend16s,instr_i64extend32s,instr_i64extend8s,instr_i64extendsi32,instr_i64extendui32,instr_i64ges,instr_i64geu,instr_i64gts,instr_i64gtu,instr_i64les,instr_i64leu,instr_i64load,instr_i64lts,instr_i64ltu,instr_i64mul,instr_i64ne,instr_i64or,instr_i64popcnt,instr_i64rems,instr_i64remu,instr_i64rotl,instr_i64rotr,instr_i64shl,instr_i64shrs,instr_i64shru,instr_i64store,instr_i64sub,instr_i64xor,instr_if,instr_local_get,instr_local_set,instr_local_tee,instr_memory_current,instr_select,lazy_pages_host_func_read,lazy_pages_host_func_write,lazy_pages_host_func_write_after_read,lazy_pages_load_page_storage_data,lazy_pages_signal_read,lazy_pages_signal_write,lazy_pages_signal_write_after_read,mem_grow,pay_program_rent,reinstrument_per_kb,resume_session_commit,resume_session_init,resume_session_push,send_message,send_reply,tasks_pause_program,tasks_pause_program_uninited,tasks_remove_from_mailbox,tasks_remove_from_waitlist,tasks_remove_gas_reservation,tasks_remove_resume_session,tasks_send_dispatch,tasks_send_user_message,tasks_send_user_message_to_mailbox,tasks_wake_message,tasks_wake_message_no_wake,upload_code,upload_program --heap-pages=4096 --output=./scripts/benchmarking/weights-output/pallet_gear.rs --template=.maintain/frame-weight-template.hbs +// ./target/production/gear benchmark pallet --chain=vara-dev --steps=50 --repeat=20 --pallet=pallet_gear --extrinsic=alloc,alloc_in_handle,alloc_per_page,claim_value,create_program,db_read_per_kb,db_write_per_kb,free,gr_block_height,gr_block_timestamp,gr_create_program,gr_create_program_per_kb,gr_create_program_wgas,gr_create_program_wgas_per_kb,gr_debug,gr_debug_per_kb,gr_gas_available,gr_message_id,gr_program_id,gr_random,gr_read,gr_read_per_kb,gr_reply_code,gr_reply_deposit,gr_reply_per_kb,gr_reply_push,gr_reply_push_input,gr_reply_push_input_per_kb,gr_reply_push_per_kb,gr_reply_to,gr_reply_wgas_per_kb,gr_reservation_reply_commit_per_kb,gr_reservation_reply_per_kb,gr_reservation_send,gr_reservation_send_commit,gr_reservation_send_per_kb,gr_reserve_gas,gr_send,gr_send_commit,gr_send_commit_wgas,gr_send_init,gr_send_input,gr_send_input_wgas,gr_send_per_kb,gr_send_push,gr_send_push_input,gr_send_push_input_per_kb,gr_send_push_per_kb,gr_send_wgas,gr_send_wgas_per_kb,gr_signal_code,gr_signal_from,gr_size,gr_source,gr_system_reserve_gas,gr_unreserve_gas,gr_value,gr_value_available,gr_wake,initial_allocation,instantiate_module_per_kb,instr_br,instr_br_if,instr_br_table,instr_br_table_per_entry,instr_call,instr_call_const,instr_call_indirect,instr_call_indirect_per_param,instr_call_per_local,instr_global_get,instr_global_set,instr_i32add,instr_i32and,instr_i32clz,instr_i32ctz,instr_i32divs,instr_i32divu,instr_i32eq,instr_i32eqz,instr_i32extend16s,instr_i32extend8s,instr_i32ges,instr_i32geu,instr_i32gts,instr_i32gtu,instr_i32les,instr_i32leu,instr_i32load,instr_i32lts,instr_i32ltu,instr_i32mul,instr_i32ne,instr_i32or,instr_i32popcnt,instr_i32rems,instr_i32remu,instr_i32rotl,instr_i32rotr,instr_i32shl,instr_i32shrs,instr_i32shru,instr_i32store,instr_i32sub,instr_i32wrapi64,instr_i32xor,instr_i64add,instr_i64and,instr_i64clz,instr_i64ctz,instr_i64divs,instr_i64divu,instr_i64eq,instr_i64eqz,instr_i64extend16s,instr_i64extend32s,instr_i64extend8s,instr_i64extendsi32,instr_i64extendui32,instr_i64ges,instr_i64geu,instr_i64gts,instr_i64gtu,instr_i64les,instr_i64leu,instr_i64load,instr_i64lts,instr_i64ltu,instr_i64mul,instr_i64ne,instr_i64or,instr_i64popcnt,instr_i64rems,instr_i64remu,instr_i64rotl,instr_i64rotr,instr_i64shl,instr_i64shrs,instr_i64shru,instr_i64store,instr_i64sub,instr_i64xor,instr_if,instr_local_get,instr_local_set,instr_local_tee,instr_memory_current,instr_select,lazy_pages_host_func_read,lazy_pages_host_func_write,lazy_pages_host_func_write_after_read,lazy_pages_load_page_storage_data,lazy_pages_signal_read,lazy_pages_signal_write,lazy_pages_signal_write_after_read,mem_grow,reinstrument_per_kb,resume_session_commit,resume_session_init,resume_session_push,send_message,send_reply,tasks_pause_program,tasks_pause_program_uninited,tasks_remove_from_mailbox,tasks_remove_from_waitlist,tasks_remove_gas_reservation,tasks_remove_resume_session,tasks_send_dispatch,tasks_send_user_message,tasks_send_user_message_to_mailbox,tasks_wake_message,tasks_wake_message_no_wake,upload_code,upload_program --heap-pages=4096 --output=./scripts/benchmarking/weights-output/pallet_gear.rs --template=.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -117,7 +117,6 @@ pub trait WeightInfo { fn gr_create_program_per_kb(p: u32, s: u32, ) -> Weight; fn gr_create_program_wgas(r: u32, ) -> Weight; fn gr_create_program_wgas_per_kb(p: u32, s: u32, ) -> Weight; - fn gr_pay_program_rent(r: u32, ) -> Weight; fn lazy_pages_signal_read(p: u32, ) -> Weight; fn lazy_pages_signal_write(p: u32, ) -> Weight; fn lazy_pages_signal_write_after_read(p: u32, ) -> Weight; @@ -1069,16 +1068,6 @@ impl pallet_gear::WeightInfo for SubstrateWeight { // Standard Error: 133_275 .saturating_add(Weight::from_parts(168_745_496, 0).saturating_mul(s.into())) } - /// The range of component `r` is `[0, 20]`. - fn gr_pay_program_rent(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 99_990_000 picoseconds. - Weight::from_parts(118_439_219, 0) - // Standard Error: 33_092 - .saturating_add(Weight::from_parts(1_902_407, 0).saturating_mul(r.into())) - } /// The range of component `p` is `[0, 512]`. fn lazy_pages_signal_read(p: u32, ) -> Weight { // Proof Size summary in bytes: @@ -2957,16 +2946,6 @@ impl WeightInfo for () { // Standard Error: 133_275 .saturating_add(Weight::from_parts(168_745_496, 0).saturating_mul(s.into())) } - /// The range of component `r` is `[0, 20]`. - fn gr_pay_program_rent(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 99_990_000 picoseconds. - Weight::from_parts(118_439_219, 0) - // Standard Error: 33_092 - .saturating_add(Weight::from_parts(1_902_407, 0).saturating_mul(r.into())) - } /// The range of component `p` is `[0, 512]`. fn lazy_pages_signal_read(p: u32, ) -> Weight { // Proof Size summary in bytes: diff --git a/utils/regression-analysis/src/main.rs b/utils/regression-analysis/src/main.rs index 3e0bc72514c..0a677ab2abe 100644 --- a/utils/regression-analysis/src/main.rs +++ b/utils/regression-analysis/src/main.rs @@ -313,7 +313,6 @@ fn weights(kind: WeightsKind, input_file: PathBuf, output_file: PathBuf) { free_range_per_page, gr_gas_available, gr_message_id, - gr_pay_program_rent, gr_program_id, gr_source, gr_value, diff --git a/utils/runtime-fuzzer/src/gear_calls.rs b/utils/runtime-fuzzer/src/gear_calls.rs index 7faf31ccdfb..7cefd33d5b6 100644 --- a/utils/runtime-fuzzer/src/gear_calls.rs +++ b/utils/runtime-fuzzer/src/gear_calls.rs @@ -434,8 +434,7 @@ fn config(programs: &[ProgramId], log_info: Option) -> StandardGearWasmC programs .iter() .copied() - .filter(|&pid| pid != ProgramId::default()) - .map(|pid| pid.into()), + .filter_map(|pid| (pid != ProgramId::default()).then_some(pid.into())), ) .map(ActorKind::ExistingAddresses) .unwrap_or(ActorKind::Source); diff --git a/utils/wasm-gen/src/config.rs b/utils/wasm-gen/src/config.rs index a6ad6d7b264..b328717952a 100644 --- a/utils/wasm-gen/src/config.rs +++ b/utils/wasm-gen/src/config.rs @@ -90,7 +90,7 @@ //! [`crate::generate_gear_program_code`] or [`crate::generate_gear_program_module`]) //! you'd need a configs bundle - type which implements [`ConfigsBundle`]. //! -//! There's a pre-defined one - [`ValidGearWasmConfigsBundle`], usage of which will result +//! There's a pre-defined one - [`StandardGearWasmConfigsBundle`], usage of which will result //! in generation of valid (always) gear-wasm module. mod generator; diff --git a/utils/wasm-gen/src/config/syscalls.rs b/utils/wasm-gen/src/config/syscalls.rs index f4d88060490..7a7a4aaf8e6 100644 --- a/utils/wasm-gen/src/config/syscalls.rs +++ b/utils/wasm-gen/src/config/syscalls.rs @@ -139,7 +139,7 @@ impl SyscallsConfig { &self.precise_syscalls_config } - /// Error processing config for fallible syscalls. + /// Get error processing config for fallible syscalls. pub fn error_processing_config(&self) -> &ErrorProcessingConfig { &self.error_processing_config } diff --git a/utils/wasm-gen/src/config/syscalls/param.rs b/utils/wasm-gen/src/config/syscalls/param.rs index b36dfa27e0f..3038e654482 100644 --- a/utils/wasm-gen/src/config/syscalls/param.rs +++ b/utils/wasm-gen/src/config/syscalls/param.rs @@ -231,24 +231,37 @@ impl Default for RegularParamAllowedValues { // TODO #3591 Support other hash types. #[derive(Debug, Clone)] pub enum PtrParamAllowedValues { + /// Possible range of values for `Ptr::Value` pointer type. This pointer + /// type is usually define as a message value param type for "reply" syscalls + /// kind. Value(RangeInclusive), + /// Variant of `Ptr::HashWithValue` pointer type, where hash is actor id. ActorIdWithValue { actor_kind: ActorKind, range: RangeInclusive, }, + /// Variant of `Ptr::Hash` pointer type, where hash is actor id. ActorId(ActorKind), } /// Actor kind, which is actually a syscall destination choice. /// -/// `gr_send*` and `gr_exit` syscalls generated from this crate can be sent -/// to different destination in accordance to the config. -/// It's either to the message source, to some existing known address, -/// or to some random, most probably non-existing, address. +/// `gr_send*`, `gr_exit` and other message sending syscalls generated +/// from this crate can send messages to different destination +/// in accordance to the config. It's either to the message source, +/// to some existing known address, or to some random, most probably +/// non-existing, address. #[derive(Debug, Clone, Default)] pub enum ActorKind { + /// The source of the incoming message will be used as + /// a destination for an outgoing message. Source, + /// Some random address from the collection of existing + /// addresses will be used as a destination for an outgoing + /// message. ExistingAddresses(NonEmpty), + /// Absolutely random address will be generated for + /// an outgoing message destination. #[default] Random, } diff --git a/utils/wasm-gen/src/generator.rs b/utils/wasm-gen/src/generator.rs index 3dcd26509dd..4bfda9c3cf3 100644 --- a/utils/wasm-gen/src/generator.rs +++ b/utils/wasm-gen/src/generator.rs @@ -23,7 +23,7 @@ //! 2. Almost all disabled generators can be converted to [`ModuleWithCallIndexes`], from which the wasm module can be retrieved. //! 3. Every generator has a "main" function, after finishing which a transition to another generator is available (either directly or through disabled //! version of the generator). -//! 4. Almost all are instantiated from the disabled generator worked on the previous generation step (see [`GearWasmGenerator::generate`]). This is how +//! 4. Almost all generators are instantiated from the disabled generator worked on the previous generation step (see [`GearWasmGenerator::generate`]). This is how //! generator form a state-machine. //! //! Transitions paths: @@ -69,15 +69,12 @@ pub use syscalls::*; /// Module and it's call indexes carrier. /// /// # Rationale: -/// Some of generators can be instantiated from "scratch", by just calling -/// "new" (or other instantiator function), which accepts params, that are -/// essential for the generator. `WasmModule` and `CallIndexes` have an implicit -/// relationship: newly added imports and functions can be included to the wasm, -/// but not in the call indexes (if we forgot to do that). Although, adding call indexes -/// is controlled in the generator, some other generator can be instantiated with wasm -/// module and call indexes being unrelated to each other. So this carrier is used to -/// control wasm module and call indexes value flow, so related values will always -/// be delivered together. +/// `WasmModule` and `CallIndexes` have an implicit relationship: newly added imports +/// and functions can be included to the wasm, but not in the call indexes (if we forgot to do that). +/// Although, adding call indexes is controlled in the generator, some other generators +/// can be instantiated with wasm module and call indexes being unrelated to each other. +/// So this carrier is used to control wasm module and call indexes value flow, so related +/// values will always be delivered together. pub struct ModuleWithCallIndexes { module: WasmModule, call_indexes: CallIndexes, @@ -232,9 +229,10 @@ struct CallIndexes { /// /// Separating "pre-defined" functions from newly generated ones is important /// when syscalls invocator inserts calls of generated syscalls. For example, - /// calls must not be inserted in the custom function, which perofrms `gr_reservation_send`, - /// not to pollute it's internal instructions structure which is defined such that - /// semantically correct `gr_reservation_send` call is performed. + /// calls must not be inserted in the custom function which serves as a precise + /// call to `gr_reservation_send` not to pollute it's internal instructions structure + /// which is defined such that semantically correct `gr_reservation_send` call + /// is executed. /// /// Same immutability is actual for gear exports to keep them as simple as possible. custom_funcs: HashSet, @@ -276,6 +274,7 @@ impl CallIndexes { .iter() .filter_map(FunctionIndex::internal_func_idx) .max() + // Config min/max function params are `NonZeroUsize`. .expect("at least 1 func is generated by config definition") as usize }; @@ -321,7 +320,7 @@ impl FunctionIndex { /// Frozen gear wasm generator. /// -/// Instantce of this generator signals, that some gear wasm generator +/// Instance of this generator signals, that some gear wasm generator /// instance was converted to some other generator available in this crate. /// This type serves as an access/ticket for converting some generator back /// to the gear wasm generator. So it mainly controls state machine flow. diff --git a/utils/wasm-gen/src/generator/syscalls.rs b/utils/wasm-gen/src/generator/syscalls.rs index 9f4a1f0e213..4b0417f588d 100644 --- a/utils/wasm-gen/src/generator/syscalls.rs +++ b/utils/wasm-gen/src/generator/syscalls.rs @@ -21,15 +21,18 @@ //! Generators from this module form a state machine: //! ```text //! # Zero syscalls generators nesting level. -//! SyscallsImport--->DisabledSyscallsImport--->ModuleWithCallIndexes--->WasmModule +//! SyscallsImportGenerator--->DisabledSyscallsImportsGenerator--->ModuleWithCallIndexes--->WasmModule //! //! # First syscalls generators nesting level. -//! SyscallsImport--->DisabledSyscallsImport--(SyscallsImportsGenerationProof)-->AdditionalDataInjector---\ +//! SyscallsImportGenerator--->DisabledSyscallsImportsGenerator--(SyscallsImportsGenerationProof)-->AdditionalDataInjector---\ //! |--->DisabledAdditionalDataInjector--->ModuleWithCallIndexes--->WasmModule //! -//! # Third syscalls generators nesting level -//! SyscallsImport--->DisabledSyscallsImport--(SyscallsImportsGenerationProof)-->AdditionalDataInjector---\ -//! |--->DisabledAdditionalDataInjector--(AddressesInjectionOutcome)-->SyscallsInvocator--->DisabledSyscallsInvocator--->ModuleWithCallIndexes--->WasmModule +//! SyscallsImportGenerator--->DisabledSyscallsImportsGenerator--(SyscallsImportsGenerationProof)-->SyscallsInvocator---\ +//! |--->DisabledSyscallsInvocator--->ModuleWithCallIndexes--->WasmModule +//! +//! # Second syscalls generators nesting level +//! SyscallsImportGenerator--->DisabledSyscallsImportsGenerator--(SyscallsImportsGenerationProof)-->AdditionalDataInjector---\ +//! |--->DisabledAdditionalDataInjector-->SyscallsInvocator--->DisabledSyscallsInvocator--->ModuleWithCallIndexes--->WasmModule //! ``` //! Entities in curly brackets are those, which are required for the next transition. //! Also all transitions require previous entity to be disabled. diff --git a/utils/wasm-gen/src/generator/syscalls/additional_data.rs b/utils/wasm-gen/src/generator/syscalls/additional_data.rs index c21a86fa59c..019716f5c1c 100644 --- a/utils/wasm-gen/src/generator/syscalls/additional_data.rs +++ b/utils/wasm-gen/src/generator/syscalls/additional_data.rs @@ -17,6 +17,17 @@ // along with this program. If not, see . //! Additional data injector module. +//! +//! Currently it only injects data to be logged in some available +//! gear entry point (either `init`, `handle` or `handle_reply`). +//! The data is set in the data section, offset for this data is +//! chosen to be after stack end offset. Storing data after stack +//! end is a right thing, as stack end is kind of virtual stack, +//! data of which is stored on wasm pages, but not saved after +//! program execution. However, this data can be re-written by +//! other instructions of the wasm module, so one should not +//! rely on consistency of data from data section for all the wasm +//! executions. use crate::{ generator::{ diff --git a/utils/wasm-gen/src/generator/syscalls/imports.rs b/utils/wasm-gen/src/generator/syscalls/imports.rs index 0d9ab1b09e5..35b503eeb38 100644 --- a/utils/wasm-gen/src/generator/syscalls/imports.rs +++ b/utils/wasm-gen/src/generator/syscalls/imports.rs @@ -159,8 +159,8 @@ impl<'a, 'b> SyscallsImportsGenerator<'a, 'b> { } } - /// Generates syscalls imports and a function, that calls `gr_reservation_send` from config, - /// used to instantiate the generator. + /// Generates syscalls imports and precise syscalls, which are functions that call syscalls which have + /// a precise version of them. For more info on precise syscalls see [`InvocableSyscall`]. /// /// Returns disabled syscalls imports generator and a proof that imports from config were generated. pub fn generate( @@ -413,8 +413,7 @@ impl<'a, 'b> SyscallsImportsGenerator<'a, 'b> { Instruction::End, Instruction::End, ]); - let call_indexes_handle = - self.generate_proper_syscall_invocation(syscall, func_instructions); + let call_indexes_handle = self.generate_proper_syscall_function(syscall, func_instructions); Ok(call_indexes_handle) } @@ -485,8 +484,7 @@ impl<'a, 'b> SyscallsImportsGenerator<'a, 'b> { Instruction::End, Instruction::End, ]); - let call_indexes_handle = - self.generate_proper_syscall_invocation(syscall, func_instructions); + let call_indexes_handle = self.generate_proper_syscall_function(syscall, func_instructions); Ok(call_indexes_handle) } @@ -584,8 +582,7 @@ impl<'a, 'b> SyscallsImportsGenerator<'a, 'b> { Instruction::End, ]); let func_instructions = Instructions::new(elements); - let call_indexes_handle = - self.generate_proper_syscall_invocation(syscall, func_instructions); + let call_indexes_handle = self.generate_proper_syscall_function(syscall, func_instructions); Ok(call_indexes_handle) } @@ -690,12 +687,12 @@ impl<'a, 'b> SyscallsImportsGenerator<'a, 'b> { Instruction::End, ]); let func_instructions = Instructions::new(elements); - let call_indexes_handle = - self.generate_proper_syscall_invocation(syscall, func_instructions); + let call_indexes_handle = self.generate_proper_syscall_function(syscall, func_instructions); Ok(call_indexes_handle) } + /// Generates a function which calls "properly" the `gr_reply_deposit`. fn generate_reply_deposit( &mut self, syscall: SyscallName, @@ -777,8 +774,7 @@ impl<'a, 'b> SyscallsImportsGenerator<'a, 'b> { func_instructions.push(Instruction::End); let func_instructions = Instructions::new(func_instructions); - let call_indexes_handle = - self.generate_proper_syscall_invocation(syscall, func_instructions); + let call_indexes_handle = self.generate_proper_syscall_function(syscall, func_instructions); Ok(call_indexes_handle) } @@ -818,7 +814,7 @@ impl<'a, 'b> SyscallsImportsGenerator<'a, 'b> { } /// Generates a function which calls "properly" the given syscall. - fn generate_proper_syscall_invocation( + fn generate_proper_syscall_function( &mut self, syscall: SyscallName, func_instructions: Instructions, diff --git a/utils/wasm-gen/src/generator/syscalls/invocator.rs b/utils/wasm-gen/src/generator/syscalls/invocator.rs index 36d2b694318..b93ec114fc9 100644 --- a/utils/wasm-gen/src/generator/syscalls/invocator.rs +++ b/utils/wasm-gen/src/generator/syscalls/invocator.rs @@ -122,16 +122,6 @@ pub(crate) fn process_syscall_params( /// Syscalls invocator. /// /// Inserts syscalls invokes randomly into internal functions. -/// -/// This type is instantiated from disable additional data injector and -/// data injection outcome ([`AddressesInjectionOutcome`]). The latter was introduced -/// to give additional guarantees for config and generators consistency. Otherwise, -/// if there wasn't any addresses injection outcome, which signals that there was a try to -/// inject addresses, syscalls invocator could falsely set `gr_send*` and `gr_exit` call's destination param -/// to random value. For example, existing addresses could have been defined in the config, but -/// additional data injector was disabled, before injecting addresses from the config. As a result, -/// invocator would set un-intended by config values as messages destination. To avoid such -/// inconsistency the [`AddressesInjectionOutcome`] gives additional required guarantees. pub struct SyscallsInvocator<'a, 'b> { unstructured: &'b mut Unstructured<'a>, call_indexes: CallIndexes, @@ -750,8 +740,8 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> { /// Disabled syscalls invocator. /// -/// This type signals that syscalls imports generation, additional data injection and -/// syscalls invocation (with further call indexes resolution) is done. +/// This type signals that syscalls imports generation and syscalls invocation +/// (with further call indexes resolution) is done. pub struct DisabledSyscallsInvocator { module: WasmModule, call_indexes: CallIndexes, diff --git a/utils/wasm-gen/src/tests.rs b/utils/wasm-gen/src/tests.rs index 43c82c66216..fd4b2c933ee 100644 --- a/utils/wasm-gen/src/tests.rs +++ b/utils/wasm-gen/src/tests.rs @@ -27,7 +27,6 @@ use gear_core::{ ContextSettings, DispatchKind, IncomingDispatch, IncomingMessage, MessageContext, ReplyPacket, }, - pages::WASM_PAGE_SIZE, }; use gear_core_backend::{ env::{BackendReport, Environment}, @@ -387,10 +386,6 @@ fn error_processing_works_for_fallible_syscalls() { let fallible_syscalls = SyscallName::instrumentable() .into_iter() .filter_map(|syscall| { - if matches!(syscall, SyscallName::PayProgramRent) { - return None; - } - let invocable_syscall = InvocableSyscall::Loose(syscall); invocable_syscall.is_fallible().then_some(invocable_syscall) }); @@ -509,23 +504,11 @@ struct MemoryWrite { } fn get_params_for_syscall_to_fail( - syscall: InvocableSyscall, + _syscall: InvocableSyscall, ) -> (SyscallsParamsConfig, Option) { - let syscall_name = match syscall { - InvocableSyscall::Loose(name) => name, - InvocableSyscall::Precise(name) => name, - }; - let memory_write = match syscall_name { - SyscallName::PayProgramRent => Some(MemoryWrite { - offset: 0, - content: vec![255; WASM_PAGE_SIZE], - }), - _ => None, - }; - ( SyscallsParamsConfig::const_regular_params(i32::MAX as i64), - memory_write, + None, ) } diff --git a/utils/wasm-gen/src/utils.rs b/utils/wasm-gen/src/utils.rs index 3062c4010b0..30a8aaefd36 100644 --- a/utils/wasm-gen/src/utils.rs +++ b/utils/wasm-gen/src/utils.rs @@ -464,6 +464,12 @@ pub fn inject_critical_gas_limit(module: Module, critical_gas_limit: u64) -> Mod module } +/// Bytes data converted into wasm words, i.e. i32 words. +/// +/// This type is mainly used to define values for syscalls +/// params of a pointer type. The value is converted first +/// to bytes and then to wasm words, which are later translated +/// to wasm instructions (see [`translate_ptr_data`]). pub(crate) struct WasmWords(Vec); impl WasmWords { @@ -498,6 +504,14 @@ impl WasmWords { } } +/// Translates ptr data wasm words to instructions that set this data +/// to wasm memory. +/// +/// The `start_offset` is the index in memory where data should start. +/// +/// The `end_offset` is usually the same as `start_offset` when the translated +/// data (words) is desired to be used as a param for the syscall. In this case +/// end offset just points to the start of the param value. pub(crate) fn translate_ptr_data( WasmWords(words): WasmWords, (start_offset, end_offset): (i32, i32), @@ -516,6 +530,7 @@ pub(crate) fn translate_ptr_data( .collect() } +/// Convert `NonEmpty` vector to `Vec`. pub(crate) fn non_empty_to_vec(non_empty: NonEmpty) -> Vec { let (head, mut tail) = non_empty.into(); tail.push(head); diff --git a/utils/wasm-gen/src/wasm.rs b/utils/wasm-gen/src/wasm.rs index 2f2d32e3491..e35c4d0d7bf 100644 --- a/utils/wasm-gen/src/wasm.rs +++ b/utils/wasm-gen/src/wasm.rs @@ -16,6 +16,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +//! Wasm related entities. + use crate::{config::WasmModuleConfig, EntryPointName}; use arbitrary::{Arbitrary, Result, Unstructured}; use core::mem; diff --git a/utils/wasm-instrument/src/syscalls.rs b/utils/wasm-instrument/src/syscalls.rs index 75497fe0063..ff891d7897b 100644 --- a/utils/wasm-instrument/src/syscalls.rs +++ b/utils/wasm-instrument/src/syscalls.rs @@ -105,7 +105,6 @@ pub enum SyscallName { ReserveGas, UnreserveGas, SystemReserveGas, - PayProgramRent, } impl SyscallName { @@ -128,7 +127,6 @@ impl SyscallName { SyscallName::Leave => "gr_leave", SyscallName::MessageId => "gr_message_id", SyscallName::SystemBreak => "gr_system_break", - SyscallName::PayProgramRent => "gr_pay_program_rent", SyscallName::ProgramId => "gr_program_id", SyscallName::Random => "gr_random", SyscallName::Read => "gr_read", @@ -192,7 +190,6 @@ impl SyscallName { Self::BlockTimestamp, Self::Exit, Self::GasAvailable, - Self::PayProgramRent, Self::ProgramId, Self::Leave, Self::ValueAvailable, @@ -269,10 +266,6 @@ impl SyscallName { } Self::Exit => SyscallSignature::gr_infallible([Ptr::Hash(HashType::ActorId).into()]), Self::GasAvailable => SyscallSignature::gr_infallible([Ptr::MutGas.into()]), - Self::PayProgramRent => SyscallSignature::gr_fallible(( - [Ptr::HashWithValue(HashType::ActorId).into()], - ErrPtr::ErrorWithBlockNumberAndValue, - )), Self::ProgramId => { SyscallSignature::gr_infallible([Ptr::MutHash(HashType::ActorId).into()]) } @@ -828,7 +821,6 @@ mod pointers { ErrorWithHandle, ErrorWithHash(HashType), ErrorWithTwoHashes(HashType, HashType), - ErrorWithBlockNumberAndValue, } impl From for ParamType {