From 4fa944bbefe118b04da05dbe16b4c0add74990b5 Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Thu, 21 Dec 2023 17:50:24 +0300 Subject: [PATCH 01/33] feat(wasm-gen): avoid infinite wait-wake for loose syscalls --- utils/wasm-gen/src/config.rs | 11 ++++ utils/wasm-gen/src/config/syscalls.rs | 14 +++++ utils/wasm-gen/src/generator/syscalls.rs | 8 +++ .../src/generator/syscalls/invocator.rs | 53 +++++++++++++++++++ 4 files changed, 86 insertions(+) diff --git a/utils/wasm-gen/src/config.rs b/utils/wasm-gen/src/config.rs index 7042322963b..907458d91b2 100644 --- a/utils/wasm-gen/src/config.rs +++ b/utils/wasm-gen/src/config.rs @@ -135,6 +135,11 @@ impl ConfigsBundle for (GearWasmGeneratorConfig, SelectableParams) { pub struct StandardGearWasmConfigsBundle { /// Externalities to be logged. pub log_info: Option, + /// Frequency of wait syscalls. + /// + /// For example, if this parameter is 4, wait syscalls will be invoked + /// with probability 1/4. + pub waiting_frequency: Option, /// Set of existing addresses, which will be used as message destinations. /// /// If is `None`, then `gr_source` result will be used as a message destination. @@ -164,6 +169,7 @@ impl Default for StandardGearWasmConfigsBundle { fn default() -> Self { Self { log_info: Some("StandardGearWasmConfigsBundle".into()), + waiting_frequency: Some(4), existing_addresses: None, remove_recursion: false, critical_gas_limit: Some(1_000_000), @@ -180,6 +186,7 @@ impl> ConfigsBundle for StandardGearWasmConfigsBundle { fn into_parts(self) -> (GearWasmGeneratorConfig, SelectableParams) { let StandardGearWasmConfigsBundle { log_info, + waiting_frequency, existing_addresses, remove_recursion, critical_gas_limit, @@ -196,6 +203,10 @@ impl> ConfigsBundle for StandardGearWasmConfigsBundle { if let Some(log_info) = log_info { syscalls_config_builder = syscalls_config_builder.with_log_info(log_info); } + if let Some(waiting_frequency) = waiting_frequency { + syscalls_config_builder = + syscalls_config_builder.with_waiting_frequency(waiting_frequency); + } if let Some(addresses) = existing_addresses { syscalls_config_builder = syscalls_config_builder.with_addresses_msg_dest(addresses); } else { diff --git a/utils/wasm-gen/src/config/syscalls.rs b/utils/wasm-gen/src/config/syscalls.rs index 531a0889cec..d181b0a5644 100644 --- a/utils/wasm-gen/src/config/syscalls.rs +++ b/utils/wasm-gen/src/config/syscalls.rs @@ -49,6 +49,7 @@ impl SyscallsConfigBuilder { syscall_destination: SyscallDestination::default(), error_processing_config: ErrorProcessingConfig::None, log_info: None, + waiting_frequency: None, }) } @@ -105,6 +106,13 @@ impl SyscallsConfigBuilder { self } + /// Set frequency of wait syscalls. + pub fn with_waiting_frequency(mut self, waiting_frequency: u32) -> Self { + self.0.waiting_frequency = Some(waiting_frequency); + + self + } + /// Setup fallible syscalls error processing options. pub fn set_error_processing_config(mut self, config: ErrorProcessingConfig) -> Self { self.0.error_processing_config = config; @@ -127,6 +135,7 @@ pub struct SyscallsConfig { syscall_destination: SyscallDestination, error_processing_config: ErrorProcessingConfig, log_info: Option, + waiting_frequency: Option, } impl SyscallsConfig { @@ -163,6 +172,11 @@ impl SyscallsConfig { pub fn error_processing_config(&self) -> &ErrorProcessingConfig { &self.error_processing_config } + + /// Get frequency of wait syscalls. + pub fn waiting_frequency(&self) -> Option { + self.waiting_frequency + } } /// Syscall destination choice. diff --git a/utils/wasm-gen/src/generator/syscalls.rs b/utils/wasm-gen/src/generator/syscalls.rs index 8a29acd61cc..fa444ffc54b 100644 --- a/utils/wasm-gen/src/generator/syscalls.rs +++ b/utils/wasm-gen/src/generator/syscalls.rs @@ -235,6 +235,14 @@ impl InvocableSyscall { && !matches!(self, InvocableSyscall::Loose(SyscallName::Exit)) } + /// Returns `true` for wait syscalls. + fn is_wait_syscall(&self) -> bool { + use InvocableSyscall::*; + use SyscallName::*; + + matches!(self, Loose(Wait | WaitFor | WaitUpTo)) + } + /// Checks whether syscall is error-prone either by returning error indicating value /// or by providing error pointer as a syscall param. /// diff --git a/utils/wasm-gen/src/generator/syscalls/invocator.rs b/utils/wasm-gen/src/generator/syscalls/invocator.rs index 6f94384477e..77566dd41a9 100644 --- a/utils/wasm-gen/src/generator/syscalls/invocator.rs +++ b/utils/wasm-gen/src/generator/syscalls/invocator.rs @@ -342,6 +342,17 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> { ); self.build_call_with_destination(invocable, call_indexes_handle, argument_index) + } else if let Some(wait_frequency) = self + .config + .waiting_frequency() + .filter(|_| invocable.is_wait_syscall()) + { + log::trace!( + " -- Building call instructions for a `{}` wait syscall", + invocable.to_str() + ); + + self.build_call_for_wait_syscall(invocable, call_indexes_handle, wait_frequency) } else { log::trace!( " -- Building call for a common syscall `{}`", @@ -434,6 +445,48 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> { Ok(original_instructions) } + fn build_call_for_wait_syscall( + &mut self, + invocable: InvocableSyscall, + call_indexes_handle: CallIndexesHandle, + wait_frequency: u32, + ) -> Result> { + let mem_size_pages = self + .module + .initial_mem_size() + // To instantiate this generator, we must instantiate SyscallImportsGenerator, which can be + // instantiated only with memory import generation proof. + .expect("generator is instantiated with a memory import generation proof"); + let mem_size = Into::::into(mem_size_pages).memory_size(); + + let upper_limit = mem_size.saturating_sub(1) as i32; + let wait_called_ptr = upper_limit.saturating_sub(50); + + let mut original_instructions = self.build_call(invocable, call_indexes_handle)?; + let mut instructions = Vec::with_capacity(13 + original_instructions.len()); + + instructions.extend_from_slice(&[ + Instruction::I32Const(wait_called_ptr), + Instruction::I32Load(2, 0), + Instruction::I32Const(wait_frequency as i32), + Instruction::I32RemU, + Instruction::I32Eqz, + Instruction::If(BlockType::NoResult), + ]); + instructions.append(&mut original_instructions); + instructions.extend_from_slice(&[ + Instruction::End, + Instruction::I32Const(wait_called_ptr), + Instruction::I32Const(wait_called_ptr), + Instruction::I32Load(2, 0), + Instruction::I32Const(1), + Instruction::I32Add, + Instruction::I32Store(2, 0), + ]); + + Ok(instructions) + } + fn build_call( &mut self, invocable: InvocableSyscall, From 56db883d7b743cef447ee3f2567f96858d174395 Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Thu, 28 Dec 2023 14:52:08 +0300 Subject: [PATCH 02/33] compare with i32.const 1 --- utils/wasm-gen/src/generator/syscalls/invocator.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/utils/wasm-gen/src/generator/syscalls/invocator.rs b/utils/wasm-gen/src/generator/syscalls/invocator.rs index 77566dd41a9..cc28782e0ea 100644 --- a/utils/wasm-gen/src/generator/syscalls/invocator.rs +++ b/utils/wasm-gen/src/generator/syscalls/invocator.rs @@ -470,7 +470,8 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> { Instruction::I32Load(2, 0), Instruction::I32Const(wait_frequency as i32), Instruction::I32RemU, - Instruction::I32Eqz, + Instruction::I32Const(1), + Instruction::I32Eq, Instruction::If(BlockType::NoResult), ]); instructions.append(&mut original_instructions); From 957d2293d617afee917c3de787e0d36461c518a5 Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Sun, 7 Jan 2024 21:37:16 +0300 Subject: [PATCH 03/33] fix tests --- .../src/generator/syscalls/invocator.rs | 60 ++++++++++--------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/utils/wasm-gen/src/generator/syscalls/invocator.rs b/utils/wasm-gen/src/generator/syscalls/invocator.rs index b11ec13ce93..b737be31632 100644 --- a/utils/wasm-gen/src/generator/syscalls/invocator.rs +++ b/utils/wasm-gen/src/generator/syscalls/invocator.rs @@ -314,19 +314,44 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> { .flat_map(ParamInstructions::into_inner) .collect::>(); - let original_call = Instruction::Call(call_indexes_handle as u32); + instructions.push(Instruction::Call(call_indexes_handle as u32)); + + let process_error = self + .config + .error_processing_config() + .error_should_be_processed(invocable); + + let mut result_processing = match signature { + SyscallSignature::Infallible(_) => { + // It's guaranteed here that infallible has no errors to process + // as it has not mut err pointers or error indicating values returned. + Vec::new() + } + signature @ (SyscallSignature::Fallible(_) | SyscallSignature::System(_)) => { + // It's guaranteed by definition that these variants return an error either by returning + // error indicating value or by having err mut pointer in params. + if process_error { + Self::build_error_processing(signature, param_instructions) + } else { + Self::build_error_processing_ignored(signature) + } + } + }; + instructions.append(&mut result_processing); if let Some(wait_frequency) = self .config .waiting_frequency() .filter(|_| invocable.is_wait_syscall()) { + let mut new_instructions = Vec::with_capacity(instructions.len()); + let mem_size = self.memory_size_in_bytes(); let upper_limit = mem_size.saturating_sub(1) as i32; let wait_called_ptr = upper_limit.saturating_sub(50); - instructions.extend_from_slice(&[ + new_instructions.extend_from_slice(&[ Instruction::I32Const(wait_called_ptr), Instruction::I32Load(2, 0), Instruction::I32Const(wait_frequency as i32), @@ -334,7 +359,9 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> { Instruction::I32Const(1), Instruction::I32Eq, Instruction::If(BlockType::NoResult), - original_call, + ]); + new_instructions.append(&mut instructions); + new_instructions.extend_from_slice(&[ Instruction::End, Instruction::I32Const(wait_called_ptr), Instruction::I32Const(wait_called_ptr), @@ -343,32 +370,9 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> { Instruction::I32Add, Instruction::I32Store(2, 0), ]); - } else { - instructions.push(original_call); - } - - let process_error = self - .config - .error_processing_config() - .error_should_be_processed(invocable); - let mut result_processing = match signature { - SyscallSignature::Infallible(_) => { - // It's guaranteed here that infallible has no errors to process - // as it has not mut err pointers or error indicating values returned. - Vec::new() - } - signature @ (SyscallSignature::Fallible(_) | SyscallSignature::System(_)) => { - // It's guaranteed by definition that these variants return an error either by returning - // error indicating value or by having err mut pointer in params. - if process_error { - Self::build_error_processing(signature, param_instructions) - } else { - Self::build_error_processing_ignored(signature) - } - } - }; - instructions.append(&mut result_processing); + instructions = new_instructions; + } log::trace!( "Random data after building `{}` syscall invoke instructions - {}", From 62c24184f1659dcfda78a7f6bca88dd8fc2acb03 Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Sun, 7 Jan 2024 21:48:04 +0300 Subject: [PATCH 04/33] [si-skip] more efficient memory allocation --- .../src/generator/syscalls/invocator.rs | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/utils/wasm-gen/src/generator/syscalls/invocator.rs b/utils/wasm-gen/src/generator/syscalls/invocator.rs index b737be31632..8ae36296b75 100644 --- a/utils/wasm-gen/src/generator/syscalls/invocator.rs +++ b/utils/wasm-gen/src/generator/syscalls/invocator.rs @@ -344,24 +344,27 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> { .waiting_frequency() .filter(|_| invocable.is_wait_syscall()) { - let mut new_instructions = Vec::with_capacity(instructions.len()); - let mem_size = self.memory_size_in_bytes(); let upper_limit = mem_size.saturating_sub(1) as i32; let wait_called_ptr = upper_limit.saturating_sub(50); - new_instructions.extend_from_slice(&[ - Instruction::I32Const(wait_called_ptr), - Instruction::I32Load(2, 0), - Instruction::I32Const(wait_frequency as i32), - Instruction::I32RemU, - Instruction::I32Const(1), - Instruction::I32Eq, - Instruction::If(BlockType::NoResult), - ]); - new_instructions.append(&mut instructions); - new_instructions.extend_from_slice(&[ + // add instructions before calling wait syscall + instructions.splice( + 0..0, + [ + Instruction::I32Const(wait_called_ptr), + Instruction::I32Load(2, 0), + Instruction::I32Const(wait_frequency as i32), + Instruction::I32RemU, + Instruction::I32Const(1), + Instruction::I32Eq, + Instruction::If(BlockType::NoResult), + ], + ); + + // add instructions after calling wait syscall + instructions.extend_from_slice(&[ Instruction::End, Instruction::I32Const(wait_called_ptr), Instruction::I32Const(wait_called_ptr), @@ -370,8 +373,6 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> { Instruction::I32Add, Instruction::I32Store(2, 0), ]); - - instructions = new_instructions; } log::trace!( From b708f2e737cfa1ef2d4ea506abfce334eeb6c342 Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Tue, 16 Jan 2024 23:31:01 +0300 Subject: [PATCH 05/33] use % == 0, add extra check for init_called --- utils/wasm-gen/src/generator/entry_points.rs | 29 +++++++++++++++++-- .../src/generator/syscalls/invocator.rs | 11 +++++-- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/utils/wasm-gen/src/generator/entry_points.rs b/utils/wasm-gen/src/generator/entry_points.rs index 94c8dfb287e..224bd18ebcb 100644 --- a/utils/wasm-gen/src/generator/entry_points.rs +++ b/utils/wasm-gen/src/generator/entry_points.rs @@ -20,13 +20,15 @@ use crate::{ generator::{CallIndexes, FrozenGearWasmGenerator, GearWasmGenerator, ModuleWithCallIndexes}, - EntryPointsSet, WasmModule, + wasm::{PageCount as WasmPageCount, WasmModule}, + EntryPointsSet, }; use arbitrary::{Result, Unstructured}; use gear_wasm_instrument::parity_wasm::{ builder, elements::{FunctionType, Instruction, Instructions, Type, ValueType}, }; +use std::mem; /// Gear wasm entry points generator. /// @@ -164,8 +166,31 @@ impl<'a, 'b> EntryPointsGenerator<'a, 'b> { (module, func_type) }); - let export_body_instructions = + let mut export_body_instructions = self.generate_export_body(export_body_call_idx, export_body_call_func_type)?; + + // after initializing the program, we will write about this in a special pointer + if name == "init" { + if let Some(memory_size_pages) = self.module.initial_mem_size() { + let mem_size = Into::::into(memory_size_pages).memory_size(); + + let upper_limit = mem_size.saturating_sub(1) as i32; + let wait_called_ptr = upper_limit.saturating_sub(50); + let init_called_ptr = wait_called_ptr + mem::size_of::() as i32; + + let end_instruction = export_body_instructions.pop(); + export_body_instructions.extend_from_slice(&[ + // *init_called_ptr = true + Instruction::I32Const(init_called_ptr), + Instruction::I32Const(1), + Instruction::I32Store8(0, 0), + ]); + if let Some(end_instruction) = end_instruction { + export_body_instructions.push(end_instruction); + } + } + } + self.module.with(|module| { let module = builder::from_module(module) .function() diff --git a/utils/wasm-gen/src/generator/syscalls/invocator.rs b/utils/wasm-gen/src/generator/syscalls/invocator.rs index f316b8d513b..7dda86ace60 100644 --- a/utils/wasm-gen/src/generator/syscalls/invocator.rs +++ b/utils/wasm-gen/src/generator/syscalls/invocator.rs @@ -338,17 +338,22 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> { let upper_limit = mem_size.saturating_sub(1) as i32; let wait_called_ptr = upper_limit.saturating_sub(50); + let init_called_ptr = wait_called_ptr + mem::size_of::() as i32; // add instructions before calling wait syscall instructions.splice( 0..0, [ + Instruction::I32Const(init_called_ptr), + Instruction::I32Load8U(0, 0), + // if *init_called_ptr { .. } + Instruction::If(BlockType::NoResult), Instruction::I32Const(wait_called_ptr), Instruction::I32Load(2, 0), Instruction::I32Const(wait_frequency as i32), Instruction::I32RemU, - Instruction::I32Const(1), - Instruction::I32Eq, + Instruction::I32Eqz, + // if *wait_called_ptr % wait_frequency == 0 { orig_wait_syscall(); } Instruction::If(BlockType::NoResult), ], ); @@ -356,12 +361,14 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> { // add instructions after calling wait syscall instructions.extend_from_slice(&[ Instruction::End, + // *wait_called_ptr += 1 Instruction::I32Const(wait_called_ptr), Instruction::I32Const(wait_called_ptr), Instruction::I32Load(2, 0), Instruction::I32Const(1), Instruction::I32Add, Instruction::I32Store(2, 0), + Instruction::End, ]); } From d5cc5902a8b3b3b210b33e8061f073be2ab4130a Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Thu, 18 Jan 2024 17:33:26 +0300 Subject: [PATCH 06/33] resolve some discussions --- utils/wasm-gen/src/generator/entry_points.rs | 46 +++++++++---------- .../src/generator/syscalls/imports.rs | 4 +- .../src/generator/syscalls/invocator.rs | 14 +++--- 3 files changed, 31 insertions(+), 33 deletions(-) diff --git a/utils/wasm-gen/src/generator/entry_points.rs b/utils/wasm-gen/src/generator/entry_points.rs index 224bd18ebcb..b1ea04af690 100644 --- a/utils/wasm-gen/src/generator/entry_points.rs +++ b/utils/wasm-gen/src/generator/entry_points.rs @@ -166,30 +166,8 @@ impl<'a, 'b> EntryPointsGenerator<'a, 'b> { (module, func_type) }); - let mut export_body_instructions = - self.generate_export_body(export_body_call_idx, export_body_call_func_type)?; - - // after initializing the program, we will write about this in a special pointer - if name == "init" { - if let Some(memory_size_pages) = self.module.initial_mem_size() { - let mem_size = Into::::into(memory_size_pages).memory_size(); - - let upper_limit = mem_size.saturating_sub(1) as i32; - let wait_called_ptr = upper_limit.saturating_sub(50); - let init_called_ptr = wait_called_ptr + mem::size_of::() as i32; - - let end_instruction = export_body_instructions.pop(); - export_body_instructions.extend_from_slice(&[ - // *init_called_ptr = true - Instruction::I32Const(init_called_ptr), - Instruction::I32Const(1), - Instruction::I32Store8(0, 0), - ]); - if let Some(end_instruction) = end_instruction { - export_body_instructions.push(end_instruction); - } - } - } + let export_body_instructions = + self.generate_export_body(name, export_body_call_idx, export_body_call_func_type)?; self.module.with(|module| { let module = builder::from_module(module) @@ -219,6 +197,7 @@ impl<'a, 'b> EntryPointsGenerator<'a, 'b> { /// Generates body of the export function. fn generate_export_body( &mut self, + name: &str, export_body_call_idx: usize, export_body_call_func_type: FunctionType, ) -> Result> { @@ -236,6 +215,25 @@ impl<'a, 'b> EntryPointsGenerator<'a, 'b> { } res.push(Instruction::Call(export_body_call_idx as u32)); res.extend(results.iter().map(|_| Instruction::Drop)); + + // after initializing the program, we will write about this in a special pointer + if name == "init" { + if let Some(memory_size_pages) = self.module.initial_mem_size() { + let mem_size = Into::::into(memory_size_pages).memory_size(); + + let upper_limit = mem_size.saturating_sub(1) as i32; + let wait_called_ptr = upper_limit.saturating_sub(50); + let init_called_ptr = wait_called_ptr + mem::size_of::() as i32; + + res.extend_from_slice(&[ + // *init_called_ptr = true + Instruction::I32Const(init_called_ptr), + Instruction::I32Const(1), + Instruction::I32Store8(0, 0), + ]); + } + } + res.push(Instruction::End); Ok(res) diff --git a/utils/wasm-gen/src/generator/syscalls/imports.rs b/utils/wasm-gen/src/generator/syscalls/imports.rs index 35b503eeb38..84a0f3f3c1e 100644 --- a/utils/wasm-gen/src/generator/syscalls/imports.rs +++ b/utils/wasm-gen/src/generator/syscalls/imports.rs @@ -799,12 +799,12 @@ impl<'a, 'b> SyscallsImportsGenerator<'a, 'b> { /// Reserves enough memory build precise syscall. fn reserve_memory(&self) -> i32 { - self.memory_size_in_bytes() + self.memory_size_bytes() .saturating_sub(Self::PRECISE_SYSCALL_MEMORY_SIZE) as i32 } /// Returns the size of the memory in bytes that can be used to build precise syscall. - fn memory_size_in_bytes(&self) -> u32 { + fn memory_size_bytes(&self) -> u32 { let initial_mem_size: WasmPageCount = self .module .initial_mem_size() diff --git a/utils/wasm-gen/src/generator/syscalls/invocator.rs b/utils/wasm-gen/src/generator/syscalls/invocator.rs index 7dda86ace60..35c8c23c269 100644 --- a/utils/wasm-gen/src/generator/syscalls/invocator.rs +++ b/utils/wasm-gen/src/generator/syscalls/invocator.rs @@ -143,6 +143,11 @@ impl<'a, 'b> From> for SyscallsInvocator< } impl<'a, 'b> SyscallsInvocator<'a, 'b> { + /// Returns the size of the memory in bytes. + fn memory_size_bytes(&self) -> u32 { + Into::::into(self.memory_size_pages()).memory_size() + } + /// Returns the size of the memory in pages. fn memory_size_pages(&self) -> u32 { self.module @@ -152,11 +157,6 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> { .expect("generator is instantiated with a memory import generation proof") } - /// Returns the size of the memory in bytes. - fn memory_size_in_bytes(&self) -> u32 { - Into::::into(self.memory_size_pages()).memory_size() - } - /// Insert syscalls invokes. /// /// The method builds instructions, which describe how each syscall is called, and then @@ -334,7 +334,7 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> { .waiting_frequency() .filter(|_| invocable.is_wait_syscall()) { - let mem_size = self.memory_size_in_bytes(); + let mem_size = self.memory_size_bytes(); let upper_limit = mem_size.saturating_sub(1) as i32; let wait_called_ptr = upper_limit.saturating_sub(50); @@ -391,7 +391,7 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> { ); let mem_size_pages = self.memory_size_pages(); - let mem_size = self.memory_size_in_bytes(); + let mem_size = self.memory_size_bytes(); let mut ret = Vec::with_capacity(params.len()); let mut memory_array_definition: Option<(i32, Option)> = None; From 06c9f614f7535024e4fca2a3af72c3a6c63b7ca4 Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Thu, 18 Jan 2024 18:47:06 +0300 Subject: [PATCH 07/33] fix bug with MutSizedBufferStart --- utils/wasm-gen/src/generator/syscalls/invocator.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/utils/wasm-gen/src/generator/syscalls/invocator.rs b/utils/wasm-gen/src/generator/syscalls/invocator.rs index 35c8c23c269..fac95b7b9b4 100644 --- a/utils/wasm-gen/src/generator/syscalls/invocator.rs +++ b/utils/wasm-gen/src/generator/syscalls/invocator.rs @@ -94,11 +94,14 @@ pub(crate) fn process_syscall_params( Length if length_param_indexes.contains(¶m_idx) => { // Due to match guard `RegularParamType::Length` can be processed in two ways: // 1. The function will return `ProcessedSyscallParams::MemoryArraySize` - // if this parameter is associated with Ptr::SizedBufferStart { .. }`. + // if this parameter is associated with Ptr::SizedBufferStart { .. }` + // or `Ptr::MutSizedBufferStart`. // 2. Otherwise, `ProcessedSyscallParams::Value` will be returned from the function. ProcessedSyscallParams::MemoryArrayLength } - Pointer(Ptr::SizedBufferStart { .. }) => ProcessedSyscallParams::MemoryArrayPtr, + Pointer(Ptr::SizedBufferStart { .. } | Ptr::MutSizedBufferStart { .. }) => { + ProcessedSyscallParams::MemoryArrayPtr + } // It's guaranteed that fallible syscall has error pointer as a last param. Pointer(ptr) => ProcessedSyscallParams::MemoryPtrValue { allowed_values: params_config.get_ptr_rule(ptr), From 5dbbbd010551bb1e28b39ff45813dc3a2cc12564 Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Thu, 18 Jan 2024 20:25:24 +0300 Subject: [PATCH 08/33] reserve 256 bytes on the last page --- utils/wasm-gen/src/generator/entry_points.rs | 3 +-- utils/wasm-gen/src/generator/syscalls/imports.rs | 9 +++++---- utils/wasm-gen/src/generator/syscalls/invocator.rs | 14 +++++++++----- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/utils/wasm-gen/src/generator/entry_points.rs b/utils/wasm-gen/src/generator/entry_points.rs index b1ea04af690..c931a1061a9 100644 --- a/utils/wasm-gen/src/generator/entry_points.rs +++ b/utils/wasm-gen/src/generator/entry_points.rs @@ -221,8 +221,7 @@ impl<'a, 'b> EntryPointsGenerator<'a, 'b> { if let Some(memory_size_pages) = self.module.initial_mem_size() { let mem_size = Into::::into(memory_size_pages).memory_size(); - let upper_limit = mem_size.saturating_sub(1) as i32; - let wait_called_ptr = upper_limit.saturating_sub(50); + let wait_called_ptr = mem_size.saturating_sub(50) as i32; let init_called_ptr = wait_called_ptr + mem::size_of::() as i32; res.extend_from_slice(&[ diff --git a/utils/wasm-gen/src/generator/syscalls/imports.rs b/utils/wasm-gen/src/generator/syscalls/imports.rs index 84a0f3f3c1e..185eb0bd297 100644 --- a/utils/wasm-gen/src/generator/syscalls/imports.rs +++ b/utils/wasm-gen/src/generator/syscalls/imports.rs @@ -21,7 +21,7 @@ use crate::{ generator::{ CallIndexes, CallIndexesHandle, FrozenGearWasmGenerator, GearEntryPointGenerationProof, - GearWasmGenerator, MemoryImportGenerationProof, ModuleWithCallIndexes, + GearWasmGenerator, MemoryImportGenerationProof, ModuleWithCallIndexes, SyscallsInvocator, }, wasm::{PageCount as WasmPageCount, WasmModule}, InvocableSyscall, SyscallInjectionType, SyscallsConfig, @@ -325,8 +325,8 @@ impl<'a, 'b> SyscallsImportsGenerator<'a, 'b> { } impl<'a, 'b> SyscallsImportsGenerator<'a, 'b> { - /// The amount of memory used to create a precise syscall. - const PRECISE_SYSCALL_MEMORY_SIZE: u32 = 100; + /// The amount of reserved memory used to create a precise syscall. + const PRECISE_SYSCALL_RESERVED_MEMORY_SIZE: u32 = 128; /// Generates a function which calls "properly" the `gr_reservation_send`. fn generate_send_from_reservation( @@ -800,7 +800,8 @@ impl<'a, 'b> SyscallsImportsGenerator<'a, 'b> { /// Reserves enough memory build precise syscall. fn reserve_memory(&self) -> i32 { self.memory_size_bytes() - .saturating_sub(Self::PRECISE_SYSCALL_MEMORY_SIZE) as i32 + .saturating_sub(SyscallsInvocator::RESERVED_MEMORY_SIZE) + .saturating_sub(Self::PRECISE_SYSCALL_RESERVED_MEMORY_SIZE) as i32 } /// Returns the size of the memory in bytes that can be used to build precise syscall. diff --git a/utils/wasm-gen/src/generator/syscalls/invocator.rs b/utils/wasm-gen/src/generator/syscalls/invocator.rs index fac95b7b9b4..4e433f22ee7 100644 --- a/utils/wasm-gen/src/generator/syscalls/invocator.rs +++ b/utils/wasm-gen/src/generator/syscalls/invocator.rs @@ -146,6 +146,9 @@ impl<'a, 'b> From> for SyscallsInvocator< } impl<'a, 'b> SyscallsInvocator<'a, 'b> { + /// The amount of reserved memory. + pub const RESERVED_MEMORY_SIZE: u32 = 256; + /// Returns the size of the memory in bytes. fn memory_size_bytes(&self) -> u32 { Into::::into(self.memory_size_pages()).memory_size() @@ -339,8 +342,7 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> { { let mem_size = self.memory_size_bytes(); - let upper_limit = mem_size.saturating_sub(1) as i32; - let wait_called_ptr = upper_limit.saturating_sub(50); + let wait_called_ptr = mem_size.saturating_sub(50) as i32; let init_called_ptr = wait_called_ptr + mem::size_of::() as i32; // add instructions before calling wait syscall @@ -441,7 +443,7 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> { } ProcessedSyscallParams::MemoryArrayLength => { let length; - let upper_limit = mem_size.saturating_sub(1) as i32; + let upper_limit = mem_size.saturating_sub(Self::RESERVED_MEMORY_SIZE) as i32; (memory_array_definition, length) = if let Some((offset, _)) = memory_array_definition @@ -460,7 +462,7 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> { } ProcessedSyscallParams::MemoryArrayPtr => { let offset; - let upper_limit = mem_size.saturating_sub(1) as i32; + let upper_limit = mem_size.saturating_sub(Self::RESERVED_MEMORY_SIZE) as i32; (memory_array_definition, offset) = if let Some((offset, _)) = memory_array_definition { @@ -476,7 +478,9 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> { } ProcessedSyscallParams::MemoryPtrValue { allowed_values } => { // Subtract a bit more so entities from `gsys` fit. - let upper_limit = mem_size.saturating_sub(100); + let upper_limit = mem_size + .saturating_sub(Self::RESERVED_MEMORY_SIZE) + .saturating_sub(128); let offset = self.unstructured.int_in_range(0..=upper_limit)? as i32; let param_instructions = if let Some(allowed_values) = allowed_values { From 196bb79f8361e076890816857f83f0a2c4911124 Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Sat, 20 Jan 2024 15:51:28 +0300 Subject: [PATCH 09/33] add reserved_memory_size to wasm-smith --- Cargo.lock | 6 +++--- Cargo.toml | 2 +- utils/wasm-gen/src/config/module.rs | 2 ++ 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3bf0d1cee5f..d340a83985d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13467,7 +13467,7 @@ checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "wasm-encoder" version = "0.35.0" -source = "git+https://github.com/gear-tech/wasm-tools.git?branch=gear-stable#b5ee21ec07edc43b7e03edc3b9138bf78b3fd332" +source = "git+https://github.com/gear-tech/wasm-tools.git?branch=av/reserved_memory#265ee58d0129e4151a7da5c3ef3ed432e8562f09" dependencies = [ "leb128", ] @@ -13552,7 +13552,7 @@ dependencies = [ [[package]] name = "wasm-smith" version = "0.12.21" -source = "git+https://github.com/gear-tech/wasm-tools.git?branch=gear-stable#b5ee21ec07edc43b7e03edc3b9138bf78b3fd332" +source = "git+https://github.com/gear-tech/wasm-tools.git?branch=av/reserved_memory#265ee58d0129e4151a7da5c3ef3ed432e8562f09" dependencies = [ "arbitrary", "flagset", @@ -13976,7 +13976,7 @@ dependencies = [ [[package]] name = "wasmparser" version = "0.115.0" -source = "git+https://github.com/gear-tech/wasm-tools.git?branch=gear-stable#b5ee21ec07edc43b7e03edc3b9138bf78b3fd332" +source = "git+https://github.com/gear-tech/wasm-tools.git?branch=av/reserved_memory#265ee58d0129e4151a7da5c3ef3ed432e8562f09" dependencies = [ "indexmap 2.1.0", "semver 1.0.18", diff --git a/Cargo.toml b/Cargo.toml index ab808732da9..a5be8e9e315 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -237,7 +237,7 @@ runtime-primitives = { package = "gear-runtime-primitives", path = "runtime/prim service = { package = "gear-service", path = "node/service", default-features = false } testing = { package = "gear-node-testing", path = "node/testing" } vara-runtime = { path = "runtime/vara", default-features = false } -wasm-smith = { version = "0.12.21", git = "https://github.com/gear-tech/wasm-tools.git", branch = "gear-stable" } +wasm-smith = { version = "0.12.21", git = "https://github.com/gear-tech/wasm-tools.git", branch = "av/reserved_memory" } # Common executors between `sandbox-host` and `calc-stack-height` sandbox-wasmer = { package = "wasmer", version = "2.2", features = ["singlepass"] } diff --git a/utils/wasm-gen/src/config/module.rs b/utils/wasm-gen/src/config/module.rs index 69afe09c70a..0b4a7634cfc 100644 --- a/utils/wasm-gen/src/config/module.rs +++ b/utils/wasm-gen/src/config/module.rs @@ -25,6 +25,7 @@ use std::num::NonZeroUsize; +use crate::generator::SyscallsInvocator; use arbitrary::{Arbitrary, Result, Unstructured}; pub use wasm_smith::InstructionKind; use wasm_smith::{InstructionKind::*, InstructionKinds, SwarmConfig}; @@ -169,6 +170,7 @@ impl From<(SelectableParams, ArbitraryParams)> for WasmModuleConfig { min_uleb_size, multi_value_enabled, reference_types_enabled, + reserved_memory_size: Some(SyscallsInvocator::RESERVED_MEMORY_SIZE as u64), tail_call_enabled, relaxed_simd_enabled, saturating_float_to_int_enabled, From c116cae31b381e86bafdf1f6d07bbcfe345f834d Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Sat, 20 Jan 2024 16:14:14 +0300 Subject: [PATCH 10/33] inject_critical_gas_limit: write to const ptr instead of last memory page --- utils/wasm-gen/src/utils.rs | 33 +++++++-------------------------- 1 file changed, 7 insertions(+), 26 deletions(-) diff --git a/utils/wasm-gen/src/utils.rs b/utils/wasm-gen/src/utils.rs index 30a8aaefd36..fe72a0db3a1 100644 --- a/utils/wasm-gen/src/utils.rs +++ b/utils/wasm-gen/src/utils.rs @@ -16,7 +16,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use crate::wasm::PageCount as WasmPageCount; use gear_utils::NonEmpty; use gear_wasm_instrument::{ parity_wasm::{ @@ -285,27 +284,6 @@ pub fn inject_stack_limiter(module: Module) -> Module { /// } /// ``` pub fn inject_critical_gas_limit(module: Module, critical_gas_limit: u64) -> Module { - // get initial memory size of program - let Some(mem_size) = module - .import_section() - .and_then(|section| { - section - .entries() - .iter() - .find_map(|entry| match entry.external() { - External::Memory(mem_ty) => Some(mem_ty.limits().initial()), - _ => None, - }) - }) - .map(Into::::into) - .map(|page_count| page_count.memory_size()) - else { - return module; - }; - - // store available gas pointer on the last memory page - let gas_ptr = mem_size - mem::size_of::() as u32; - // add gr_gas_available import if needed let maybe_gr_gas_available_index = module.import_section().and_then(|section| { section @@ -368,14 +346,17 @@ pub fn inject_critical_gas_limit(module: Module, critical_gas_limit: u64) -> Mod let Type::Function(signature) = signature; let results = signature.results(); + // store available gas pointer on the first memory page + const GAS_PTR: i32 = 1024; + // create the body of the gas limiter: let mut body = Vec::with_capacity(results.len() + 9); body.extend_from_slice(&[ - // gr_gas_available(gas_ptr) - Instruction::I32Const(gas_ptr as i32), + // gr_gas_available(GAS_PTR) + Instruction::I32Const(GAS_PTR), Instruction::Call(gr_gas_available_index), - // gas_available = *gas_ptr - Instruction::I32Const(gas_ptr as i32), + // gas_available = *GAS_PTR + Instruction::I32Const(GAS_PTR), Instruction::I64Load(3, 0), Instruction::I64Const(critical_gas_limit as i64), // if gas_available <= critical_gas_limit { return result; } From 805fa95b0bb72a0efba37a115abcb38d853964d3 Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Sun, 21 Jan 2024 16:32:13 +0300 Subject: [PATCH 11/33] share memory layout between syscalls and instructions --- utils/wasm-gen/src/generator/entry_points.rs | 8 ++--- .../src/generator/syscalls/invocator.rs | 31 ++++++++++++++++--- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/utils/wasm-gen/src/generator/entry_points.rs b/utils/wasm-gen/src/generator/entry_points.rs index c931a1061a9..deee35d0788 100644 --- a/utils/wasm-gen/src/generator/entry_points.rs +++ b/utils/wasm-gen/src/generator/entry_points.rs @@ -21,7 +21,7 @@ use crate::{ generator::{CallIndexes, FrozenGearWasmGenerator, GearWasmGenerator, ModuleWithCallIndexes}, wasm::{PageCount as WasmPageCount, WasmModule}, - EntryPointsSet, + EntryPointsSet, MemoryLayout, }; use arbitrary::{Result, Unstructured}; use gear_wasm_instrument::parity_wasm::{ @@ -220,9 +220,9 @@ impl<'a, 'b> EntryPointsGenerator<'a, 'b> { if name == "init" { if let Some(memory_size_pages) = self.module.initial_mem_size() { let mem_size = Into::::into(memory_size_pages).memory_size(); - - let wait_called_ptr = mem_size.saturating_sub(50) as i32; - let init_called_ptr = wait_called_ptr + mem::size_of::() as i32; + let MemoryLayout { + init_called_ptr, .. + } = MemoryLayout::from(mem_size); res.extend_from_slice(&[ // *init_called_ptr = true diff --git a/utils/wasm-gen/src/generator/syscalls/invocator.rs b/utils/wasm-gen/src/generator/syscalls/invocator.rs index 4e433f22ee7..8c95b6e9ad9 100644 --- a/utils/wasm-gen/src/generator/syscalls/invocator.rs +++ b/utils/wasm-gen/src/generator/syscalls/invocator.rs @@ -340,10 +340,11 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> { .waiting_frequency() .filter(|_| invocable.is_wait_syscall()) { - let mem_size = self.memory_size_bytes(); - - let wait_called_ptr = mem_size.saturating_sub(50) as i32; - let init_called_ptr = wait_called_ptr + mem::size_of::() as i32; + let MemoryLayout { + init_called_ptr, + wait_called_ptr, + .. + } = MemoryLayout::from(self.memory_size_bytes()); // add instructions before calling wait syscall instructions.splice( @@ -797,6 +798,28 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> { } } +/// Represents memory layout that can be safely used between syscalls and instructions. +pub struct MemoryLayout { + pub init_called_ptr: i32, + pub wait_called_ptr: i32, + pub remaining_memory_ptr: i32, +} + +impl From for MemoryLayout { + fn from(mem_size: u32) -> Self { + let init_called_ptr = + mem_size.saturating_sub(SyscallsInvocator::RESERVED_MEMORY_SIZE) as i32; + let wait_called_ptr = init_called_ptr + mem::size_of::() as i32; + let remaining_memory_ptr = wait_called_ptr + mem::size_of::() as i32; + + Self { + init_called_ptr, + wait_called_ptr, + remaining_memory_ptr, + } + } +} + /// Disabled syscalls invocator. /// /// This type signals that syscalls imports generation and syscalls invocation From bac5ab14544431e286a46a312d0acd4d7c36fa26 Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Sun, 21 Jan 2024 16:37:52 +0300 Subject: [PATCH 12/33] fix clippy --- utils/wasm-gen/src/generator/entry_points.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/utils/wasm-gen/src/generator/entry_points.rs b/utils/wasm-gen/src/generator/entry_points.rs index deee35d0788..99eb6f89ca0 100644 --- a/utils/wasm-gen/src/generator/entry_points.rs +++ b/utils/wasm-gen/src/generator/entry_points.rs @@ -28,7 +28,6 @@ use gear_wasm_instrument::parity_wasm::{ builder, elements::{FunctionType, Instruction, Instructions, Type, ValueType}, }; -use std::mem; /// Gear wasm entry points generator. /// From 2a2e61ee8bb368237de50a30545a8aa2d72ea7c2 Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Sun, 21 Jan 2024 17:39:32 +0300 Subject: [PATCH 13/33] add runtime assert when reserved memory exceeded --- utils/wasm-gen/src/config/module.rs | 4 +-- .../src/generator/syscalls/imports.rs | 6 ++-- .../src/generator/syscalls/invocator.rs | 28 +++++++++++++------ 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/utils/wasm-gen/src/config/module.rs b/utils/wasm-gen/src/config/module.rs index 0b4a7634cfc..a4c0a46bca3 100644 --- a/utils/wasm-gen/src/config/module.rs +++ b/utils/wasm-gen/src/config/module.rs @@ -25,7 +25,7 @@ use std::num::NonZeroUsize; -use crate::generator::SyscallsInvocator; +use crate::MemoryLayout; use arbitrary::{Arbitrary, Result, Unstructured}; pub use wasm_smith::InstructionKind; use wasm_smith::{InstructionKind::*, InstructionKinds, SwarmConfig}; @@ -170,7 +170,7 @@ impl From<(SelectableParams, ArbitraryParams)> for WasmModuleConfig { min_uleb_size, multi_value_enabled, reference_types_enabled, - reserved_memory_size: Some(SyscallsInvocator::RESERVED_MEMORY_SIZE as u64), + reserved_memory_size: Some(MemoryLayout::RESERVED_MEMORY_SIZE as u64), tail_call_enabled, relaxed_simd_enabled, saturating_float_to_int_enabled, diff --git a/utils/wasm-gen/src/generator/syscalls/imports.rs b/utils/wasm-gen/src/generator/syscalls/imports.rs index 185eb0bd297..7a7713e40d6 100644 --- a/utils/wasm-gen/src/generator/syscalls/imports.rs +++ b/utils/wasm-gen/src/generator/syscalls/imports.rs @@ -21,10 +21,10 @@ use crate::{ generator::{ CallIndexes, CallIndexesHandle, FrozenGearWasmGenerator, GearEntryPointGenerationProof, - GearWasmGenerator, MemoryImportGenerationProof, ModuleWithCallIndexes, SyscallsInvocator, + GearWasmGenerator, MemoryImportGenerationProof, ModuleWithCallIndexes, }, wasm::{PageCount as WasmPageCount, WasmModule}, - InvocableSyscall, SyscallInjectionType, SyscallsConfig, + InvocableSyscall, MemoryLayout, SyscallInjectionType, SyscallsConfig, }; use arbitrary::{Error as ArbitraryError, Result, Unstructured}; use gear_wasm_instrument::{ @@ -800,7 +800,7 @@ impl<'a, 'b> SyscallsImportsGenerator<'a, 'b> { /// Reserves enough memory build precise syscall. fn reserve_memory(&self) -> i32 { self.memory_size_bytes() - .saturating_sub(SyscallsInvocator::RESERVED_MEMORY_SIZE) + .saturating_sub(MemoryLayout::RESERVED_MEMORY_SIZE) .saturating_sub(Self::PRECISE_SYSCALL_RESERVED_MEMORY_SIZE) as i32 } diff --git a/utils/wasm-gen/src/generator/syscalls/invocator.rs b/utils/wasm-gen/src/generator/syscalls/invocator.rs index 8c95b6e9ad9..4fc82c609e1 100644 --- a/utils/wasm-gen/src/generator/syscalls/invocator.rs +++ b/utils/wasm-gen/src/generator/syscalls/invocator.rs @@ -146,9 +146,6 @@ impl<'a, 'b> From> for SyscallsInvocator< } impl<'a, 'b> SyscallsInvocator<'a, 'b> { - /// The amount of reserved memory. - pub const RESERVED_MEMORY_SIZE: u32 = 256; - /// Returns the size of the memory in bytes. fn memory_size_bytes(&self) -> u32 { Into::::into(self.memory_size_pages()).memory_size() @@ -444,7 +441,8 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> { } ProcessedSyscallParams::MemoryArrayLength => { let length; - let upper_limit = mem_size.saturating_sub(Self::RESERVED_MEMORY_SIZE) as i32; + let upper_limit = + mem_size.saturating_sub(MemoryLayout::RESERVED_MEMORY_SIZE) as i32; (memory_array_definition, length) = if let Some((offset, _)) = memory_array_definition @@ -463,7 +461,8 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> { } ProcessedSyscallParams::MemoryArrayPtr => { let offset; - let upper_limit = mem_size.saturating_sub(Self::RESERVED_MEMORY_SIZE) as i32; + let upper_limit = + mem_size.saturating_sub(MemoryLayout::RESERVED_MEMORY_SIZE) as i32; (memory_array_definition, offset) = if let Some((offset, _)) = memory_array_definition { @@ -480,7 +479,7 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> { ProcessedSyscallParams::MemoryPtrValue { allowed_values } => { // Subtract a bit more so entities from `gsys` fit. let upper_limit = mem_size - .saturating_sub(Self::RESERVED_MEMORY_SIZE) + .saturating_sub(MemoryLayout::RESERVED_MEMORY_SIZE) .saturating_sub(128); let offset = self.unstructured.int_in_range(0..=upper_limit)? as i32; @@ -802,19 +801,32 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> { pub struct MemoryLayout { pub init_called_ptr: i32, pub wait_called_ptr: i32, + pub remaining_memory_len: u32, pub remaining_memory_ptr: i32, } +impl MemoryLayout { + /// The amount of reserved memory. + pub const RESERVED_MEMORY_SIZE: u32 = 256; +} + impl From for MemoryLayout { fn from(mem_size: u32) -> Self { - let init_called_ptr = - mem_size.saturating_sub(SyscallsInvocator::RESERVED_MEMORY_SIZE) as i32; + let start_memory_ptr = mem_size.saturating_sub(Self::RESERVED_MEMORY_SIZE) as i32; + let init_called_ptr = start_memory_ptr; let wait_called_ptr = init_called_ptr + mem::size_of::() as i32; let remaining_memory_ptr = wait_called_ptr + mem::size_of::() as i32; + let remaining_memory_len = (remaining_memory_ptr - start_memory_ptr) as u32; + + assert!( + remaining_memory_len <= Self::RESERVED_MEMORY_SIZE, + "reserved memory exceeded" + ); Self { init_called_ptr, wait_called_ptr, + remaining_memory_len, remaining_memory_ptr, } } From 86917384df9e17f7e8344b7793bf7494001059ff Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Tue, 23 Jan 2024 18:57:51 +0300 Subject: [PATCH 14/33] rename waiting_frequency to waiting_probability --- utils/wasm-gen/src/config.rs | 12 ++++++------ utils/wasm-gen/src/config/syscalls.rs | 16 ++++++++-------- .../wasm-gen/src/generator/syscalls/invocator.rs | 8 ++++---- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/utils/wasm-gen/src/config.rs b/utils/wasm-gen/src/config.rs index bfa3fca808e..ae3c67755c0 100644 --- a/utils/wasm-gen/src/config.rs +++ b/utils/wasm-gen/src/config.rs @@ -131,11 +131,11 @@ impl ConfigsBundle for (GearWasmGeneratorConfig, SelectableParams) { pub struct StandardGearWasmConfigsBundle { /// Externalities to be logged. pub log_info: Option, - /// Frequency of wait syscalls. + /// Probability of wait syscalls. /// /// For example, if this parameter is 4, wait syscalls will be invoked /// with probability 1/4. - pub waiting_frequency: Option, + pub waiting_probability: Option, /// Flag which signals whether recursions must be removed. pub remove_recursion: bool, /// If the limit is set to `Some(_)`, programs will try to stop execution @@ -161,7 +161,7 @@ impl Default for StandardGearWasmConfigsBundle { fn default() -> Self { Self { log_info: Some("StandardGearWasmConfigsBundle".into()), - waiting_frequency: Some(4), + waiting_probability: Some(4), remove_recursion: false, critical_gas_limit: Some(1_000_000), injection_types: SyscallsInjectionTypes::all_once(), @@ -177,7 +177,7 @@ impl ConfigsBundle for StandardGearWasmConfigsBundle { fn into_parts(self) -> (GearWasmGeneratorConfig, SelectableParams) { let StandardGearWasmConfigsBundle { log_info, - waiting_frequency, + waiting_probability, remove_recursion, critical_gas_limit, injection_types, @@ -193,9 +193,9 @@ impl ConfigsBundle for StandardGearWasmConfigsBundle { if let Some(log_info) = log_info { syscalls_config_builder = syscalls_config_builder.with_log_info(log_info); } - if let Some(waiting_frequency) = waiting_frequency { + if let Some(waiting_probability) = waiting_probability { syscalls_config_builder = - syscalls_config_builder.with_waiting_frequency(waiting_frequency); + syscalls_config_builder.with_waiting_probability(waiting_probability); } syscalls_config_builder = syscalls_config_builder.with_params_config(params_config); diff --git a/utils/wasm-gen/src/config/syscalls.rs b/utils/wasm-gen/src/config/syscalls.rs index 0bd882225ae..10385a5727a 100644 --- a/utils/wasm-gen/src/config/syscalls.rs +++ b/utils/wasm-gen/src/config/syscalls.rs @@ -46,7 +46,7 @@ impl SyscallsConfigBuilder { precise_syscalls_config: PreciseSyscallsConfig::default(), error_processing_config: ErrorProcessingConfig::None, log_info: None, - waiting_frequency: None, + waiting_probability: None, }) } @@ -94,9 +94,9 @@ impl SyscallsConfigBuilder { self } - /// Set frequency of wait syscalls. - pub fn with_waiting_frequency(mut self, waiting_frequency: u32) -> Self { - self.0.waiting_frequency = Some(waiting_frequency); + /// Set probability of wait syscalls. + pub fn with_waiting_probability(mut self, waiting_probability: u32) -> Self { + self.0.waiting_probability = Some(waiting_probability); self } @@ -122,7 +122,7 @@ pub struct SyscallsConfig { precise_syscalls_config: PreciseSyscallsConfig, error_processing_config: ErrorProcessingConfig, log_info: Option, - waiting_frequency: Option, + waiting_probability: Option, } impl SyscallsConfig { @@ -153,8 +153,8 @@ impl SyscallsConfig { &self.error_processing_config } - /// Get frequency of wait syscalls. - pub fn waiting_frequency(&self) -> Option { - self.waiting_frequency + /// Get probability of wait syscalls. + pub fn waiting_probability(&self) -> Option { + self.waiting_probability } } diff --git a/utils/wasm-gen/src/generator/syscalls/invocator.rs b/utils/wasm-gen/src/generator/syscalls/invocator.rs index 4fc82c609e1..b846c506278 100644 --- a/utils/wasm-gen/src/generator/syscalls/invocator.rs +++ b/utils/wasm-gen/src/generator/syscalls/invocator.rs @@ -332,9 +332,9 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> { }; instructions.append(&mut result_processing); - if let Some(wait_frequency) = self + if let Some(waiting_probability) = self .config - .waiting_frequency() + .waiting_probability() .filter(|_| invocable.is_wait_syscall()) { let MemoryLayout { @@ -353,10 +353,10 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> { Instruction::If(BlockType::NoResult), Instruction::I32Const(wait_called_ptr), Instruction::I32Load(2, 0), - Instruction::I32Const(wait_frequency as i32), + Instruction::I32Const(waiting_probability as i32), Instruction::I32RemU, Instruction::I32Eqz, - // if *wait_called_ptr % wait_frequency == 0 { orig_wait_syscall(); } + // if *wait_called_ptr % waiting_probability == 0 { orig_wait_syscall(); } Instruction::If(BlockType::NoResult), ], ); From 27e53ddb72b290f6c4184587864fff8cfae72447 Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Wed, 24 Jan 2024 15:50:38 +0300 Subject: [PATCH 15/33] add simple test to check avoid wait in init() --- utils/wasm-gen/src/tests.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/utils/wasm-gen/src/tests.rs b/utils/wasm-gen/src/tests.rs index fd4b2c933ee..ef627f3807d 100644 --- a/utils/wasm-gen/src/tests.rs +++ b/utils/wasm-gen/src/tests.rs @@ -171,6 +171,28 @@ fn remove_multiple_recursions() { println!("wat = {wat}"); } +#[test] +fn test_avoid_waits_works() { + let mut rng = SmallRng::seed_from_u64(123); + let mut buf = vec![0; UNSTRUCTURED_SIZE]; + rng.fill_bytes(&mut buf); + let mut unstructured = Unstructured::new(&buf); + + let mut injection_types = SyscallsInjectionTypes::all_never(); + injection_types.set(InvocableSyscall::Loose(SyscallName::Wait), 1, 1); + let syscalls_config = SyscallsConfigBuilder::new(injection_types) + .with_waiting_probability(4) + .build(); + + let backend_report = + execute_wasm_with_custom_configs(&mut unstructured, syscalls_config, None, 1024, false, 0); + + assert_eq!( + backend_report.termination_reason, + TerminationReason::Actor(ActorTerminationReason::Success) + ); +} + #[test] fn test_source_as_address_param() { let mut rng = SmallRng::seed_from_u64(123); From 62afff2ae569676416c4c7afd261f96123a4ddd8 Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Sun, 28 Jan 2024 19:29:56 +0300 Subject: [PATCH 16/33] hardcode memory_offset_choices --- utils/wasm-gen/src/config/module.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/utils/wasm-gen/src/config/module.rs b/utils/wasm-gen/src/config/module.rs index a4c0a46bca3..b033193688f 100644 --- a/utils/wasm-gen/src/config/module.rs +++ b/utils/wasm-gen/src/config/module.rs @@ -239,7 +239,6 @@ impl Arbitrary<'_> for ArbitraryParams { max_type_size, max_values, memory_max_size_required, - memory_offset_choices, min_element_segments, min_elements, min_globals, @@ -269,7 +268,7 @@ impl Arbitrary<'_> for ArbitraryParams { max_type_size, max_values, memory_max_size_required, - memory_offset_choices, + memory_offset_choices: (75, 25, 0), min_element_segments, min_elements, min_globals, From 10eb2543eb4eb6cca573375dd53991eb530f2750 Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Sun, 28 Jan 2024 19:32:42 +0300 Subject: [PATCH 17/33] update dep --- Cargo.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d5ebfedca47..4ca64563e75 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13467,7 +13467,7 @@ checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "wasm-encoder" version = "0.35.0" -source = "git+https://github.com/gear-tech/wasm-tools.git?branch=av/reserved_memory#265ee58d0129e4151a7da5c3ef3ed432e8562f09" +source = "git+https://github.com/gear-tech/wasm-tools.git?branch=av/reserved_memory#2e26beabcc734b71cae998c7ff4164a5338fde52" dependencies = [ "leb128", ] @@ -13552,7 +13552,7 @@ dependencies = [ [[package]] name = "wasm-smith" version = "0.12.21" -source = "git+https://github.com/gear-tech/wasm-tools.git?branch=av/reserved_memory#265ee58d0129e4151a7da5c3ef3ed432e8562f09" +source = "git+https://github.com/gear-tech/wasm-tools.git?branch=av/reserved_memory#2e26beabcc734b71cae998c7ff4164a5338fde52" dependencies = [ "arbitrary", "flagset", @@ -13976,7 +13976,7 @@ dependencies = [ [[package]] name = "wasmparser" version = "0.115.0" -source = "git+https://github.com/gear-tech/wasm-tools.git?branch=av/reserved_memory#265ee58d0129e4151a7da5c3ef3ed432e8562f09" +source = "git+https://github.com/gear-tech/wasm-tools.git?branch=av/reserved_memory#2e26beabcc734b71cae998c7ff4164a5338fde52" dependencies = [ "indexmap 2.1.0", "semver 1.0.18", From a74c7d126ad76cbf2c0422833ecfb6a3854c8f86 Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Sun, 28 Jan 2024 22:35:25 +0300 Subject: [PATCH 18/33] update dep to gear-stable --- Cargo.lock | 6 +++--- Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4ca64563e75..56b0d205428 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13467,7 +13467,7 @@ checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "wasm-encoder" version = "0.35.0" -source = "git+https://github.com/gear-tech/wasm-tools.git?branch=av/reserved_memory#2e26beabcc734b71cae998c7ff4164a5338fde52" +source = "git+https://github.com/gear-tech/wasm-tools.git?branch=gear-stable#ffe9abee63ad640c051d50515cedee7f67f31884" dependencies = [ "leb128", ] @@ -13552,7 +13552,7 @@ dependencies = [ [[package]] name = "wasm-smith" version = "0.12.21" -source = "git+https://github.com/gear-tech/wasm-tools.git?branch=av/reserved_memory#2e26beabcc734b71cae998c7ff4164a5338fde52" +source = "git+https://github.com/gear-tech/wasm-tools.git?branch=gear-stable#ffe9abee63ad640c051d50515cedee7f67f31884" dependencies = [ "arbitrary", "flagset", @@ -13976,7 +13976,7 @@ dependencies = [ [[package]] name = "wasmparser" version = "0.115.0" -source = "git+https://github.com/gear-tech/wasm-tools.git?branch=av/reserved_memory#2e26beabcc734b71cae998c7ff4164a5338fde52" +source = "git+https://github.com/gear-tech/wasm-tools.git?branch=gear-stable#ffe9abee63ad640c051d50515cedee7f67f31884" dependencies = [ "indexmap 2.1.0", "semver 1.0.18", diff --git a/Cargo.toml b/Cargo.toml index 922e0fccd75..14c5a713f05 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -237,7 +237,7 @@ runtime-primitives = { package = "gear-runtime-primitives", path = "runtime/prim service = { package = "gear-service", path = "node/service", default-features = false } testing = { package = "gear-node-testing", path = "node/testing" } vara-runtime = { path = "runtime/vara", default-features = false } -wasm-smith = { version = "0.12.21", git = "https://github.com/gear-tech/wasm-tools.git", branch = "av/reserved_memory" } +wasm-smith = { version = "0.12.21", git = "https://github.com/gear-tech/wasm-tools.git", branch = "gear-stable" } # Common executors between `sandbox-host` and `calc-stack-height` sandbox-wasmer = { package = "wasmer", version = "2.2", features = ["singlepass"] } From 0c140859a9577894046c51195297dc18c9d0e3a6 Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Sun, 28 Jan 2024 22:43:26 +0300 Subject: [PATCH 19/33] replace if let with .expect --- utils/wasm-gen/src/generator/entry_points.rs | 30 +++++++++++--------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/utils/wasm-gen/src/generator/entry_points.rs b/utils/wasm-gen/src/generator/entry_points.rs index 99eb6f89ca0..7a1b8046a0b 100644 --- a/utils/wasm-gen/src/generator/entry_points.rs +++ b/utils/wasm-gen/src/generator/entry_points.rs @@ -217,19 +217,23 @@ impl<'a, 'b> EntryPointsGenerator<'a, 'b> { // after initializing the program, we will write about this in a special pointer if name == "init" { - if let Some(memory_size_pages) = self.module.initial_mem_size() { - let mem_size = Into::::into(memory_size_pages).memory_size(); - let MemoryLayout { - init_called_ptr, .. - } = MemoryLayout::from(mem_size); - - res.extend_from_slice(&[ - // *init_called_ptr = true - Instruction::I32Const(init_called_ptr), - Instruction::I32Const(1), - Instruction::I32Store8(0, 0), - ]); - } + let memory_size_pages = self + .module + .initial_mem_size() + .expect("generator is instantiated with a mem import generation proof"); + + let mem_size = Into::::into(memory_size_pages).memory_size(); + + let MemoryLayout { + init_called_ptr, .. + } = MemoryLayout::from(mem_size); + + res.extend_from_slice(&[ + // *init_called_ptr = true + Instruction::I32Const(init_called_ptr), + Instruction::I32Const(1), + Instruction::I32Store8(0, 0), + ]); } res.push(Instruction::End); From 6fbeb3fdbfe9c3adaa372c961dbd89ca664fa5f1 Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Sun, 28 Jan 2024 22:45:37 +0300 Subject: [PATCH 20/33] move memory_size_{bytes, pages} under callers --- .../src/generator/syscalls/invocator.rs | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/utils/wasm-gen/src/generator/syscalls/invocator.rs b/utils/wasm-gen/src/generator/syscalls/invocator.rs index b846c506278..b3b23b8bf29 100644 --- a/utils/wasm-gen/src/generator/syscalls/invocator.rs +++ b/utils/wasm-gen/src/generator/syscalls/invocator.rs @@ -146,20 +146,6 @@ impl<'a, 'b> From> for SyscallsInvocator< } impl<'a, 'b> SyscallsInvocator<'a, 'b> { - /// Returns the size of the memory in bytes. - fn memory_size_bytes(&self) -> u32 { - Into::::into(self.memory_size_pages()).memory_size() - } - - /// Returns the size of the memory in pages. - fn memory_size_pages(&self) -> u32 { - self.module - .initial_mem_size() - // To instantiate this generator, we must instantiate SyscallImportsGenerator, which can be - // instantiated only with memory import generation proof. - .expect("generator is instantiated with a memory import generation proof") - } - /// Insert syscalls invokes. /// /// The method builds instructions, which describe how each syscall is called, and then @@ -795,6 +781,20 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> { (module, ()) }) } + + /// Returns the size of the memory in bytes. + fn memory_size_bytes(&self) -> u32 { + Into::::into(self.memory_size_pages()).memory_size() + } + + /// Returns the size of the memory in pages. + fn memory_size_pages(&self) -> u32 { + self.module + .initial_mem_size() + // To instantiate this generator, we must instantiate SyscallImportsGenerator, which can be + // instantiated only with memory import generation proof. + .expect("generator is instantiated with a memory import generation proof") + } } /// Represents memory layout that can be safely used between syscalls and instructions. From 29c5eddbb622761a48fd0750e3386e37b9330b54 Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Sun, 28 Jan 2024 22:58:09 +0300 Subject: [PATCH 21/33] extract code new method limit_infinite_waits --- .../src/generator/syscalls/invocator.rs | 77 ++++++++++--------- 1 file changed, 41 insertions(+), 36 deletions(-) diff --git a/utils/wasm-gen/src/generator/syscalls/invocator.rs b/utils/wasm-gen/src/generator/syscalls/invocator.rs index b3b23b8bf29..affe9f2c29a 100644 --- a/utils/wasm-gen/src/generator/syscalls/invocator.rs +++ b/utils/wasm-gen/src/generator/syscalls/invocator.rs @@ -323,42 +323,7 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> { .waiting_probability() .filter(|_| invocable.is_wait_syscall()) { - let MemoryLayout { - init_called_ptr, - wait_called_ptr, - .. - } = MemoryLayout::from(self.memory_size_bytes()); - - // add instructions before calling wait syscall - instructions.splice( - 0..0, - [ - Instruction::I32Const(init_called_ptr), - Instruction::I32Load8U(0, 0), - // if *init_called_ptr { .. } - Instruction::If(BlockType::NoResult), - Instruction::I32Const(wait_called_ptr), - Instruction::I32Load(2, 0), - Instruction::I32Const(waiting_probability as i32), - Instruction::I32RemU, - Instruction::I32Eqz, - // if *wait_called_ptr % waiting_probability == 0 { orig_wait_syscall(); } - Instruction::If(BlockType::NoResult), - ], - ); - - // add instructions after calling wait syscall - instructions.extend_from_slice(&[ - Instruction::End, - // *wait_called_ptr += 1 - Instruction::I32Const(wait_called_ptr), - Instruction::I32Const(wait_called_ptr), - Instruction::I32Load(2, 0), - Instruction::I32Const(1), - Instruction::I32Add, - Instruction::I32Store(2, 0), - Instruction::End, - ]); + self.limit_infinite_waits(&mut instructions, waiting_probability); } log::trace!( @@ -706,6 +671,46 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> { } } + /// Patches instructions of wait-syscalls to prevent deadlocks. + fn limit_infinite_waits(&self, instructions: &mut Vec, waiting_probability: u32) { + let MemoryLayout { + init_called_ptr, + wait_called_ptr, + .. + } = MemoryLayout::from(self.memory_size_bytes()); + + // add instructions before calling wait syscall + instructions.splice( + 0..0, + [ + Instruction::I32Const(init_called_ptr), + Instruction::I32Load8U(0, 0), + // if *init_called_ptr { .. } + Instruction::If(BlockType::NoResult), + Instruction::I32Const(wait_called_ptr), + Instruction::I32Load(2, 0), + Instruction::I32Const(waiting_probability as i32), + Instruction::I32RemU, + Instruction::I32Eqz, + // if *wait_called_ptr % waiting_probability == 0 { orig_wait_syscall(); } + Instruction::If(BlockType::NoResult), + ], + ); + + // add instructions after calling wait syscall + instructions.extend_from_slice(&[ + Instruction::End, + // *wait_called_ptr += 1 + Instruction::I32Const(wait_called_ptr), + Instruction::I32Const(wait_called_ptr), + Instruction::I32Load(2, 0), + Instruction::I32Const(1), + Instruction::I32Add, + Instruction::I32Store(2, 0), + Instruction::End, + ]); + } + fn resolves_calls_indexes(&mut self) { log::trace!("Resolving calls indexes"); From 28193ca7ed52085152258c883e598dcc0b46ffe0 Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Sun, 28 Jan 2024 23:02:23 +0300 Subject: [PATCH 22/33] move some stuff to const params --- utils/wasm-gen/src/config/module.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/utils/wasm-gen/src/config/module.rs b/utils/wasm-gen/src/config/module.rs index b033193688f..4c2856ed7d4 100644 --- a/utils/wasm-gen/src/config/module.rs +++ b/utils/wasm-gen/src/config/module.rs @@ -82,6 +82,8 @@ impl From<(SelectableParams, ArbitraryParams)> for WasmModuleConfig { min_data_segments, max_types, min_types, + memory_offset_choices, + reserved_memory_size, } = ConstantParams::default(); let SelectableParams { @@ -110,7 +112,6 @@ impl From<(SelectableParams, ArbitraryParams)> for WasmModuleConfig { max_type_size, max_values, memory_max_size_required, - memory_offset_choices, min_element_segments, min_elements, min_globals, @@ -170,7 +171,7 @@ impl From<(SelectableParams, ArbitraryParams)> for WasmModuleConfig { min_uleb_size, multi_value_enabled, reference_types_enabled, - reserved_memory_size: Some(MemoryLayout::RESERVED_MEMORY_SIZE as u64), + reserved_memory_size, tail_call_enabled, relaxed_simd_enabled, saturating_float_to_int_enabled, @@ -207,7 +208,6 @@ pub struct ArbitraryParams { max_type_size: u32, max_values: usize, memory_max_size_required: bool, - memory_offset_choices: (u32, u32, u32), min_element_segments: usize, min_elements: usize, min_globals: usize, @@ -268,7 +268,6 @@ impl Arbitrary<'_> for ArbitraryParams { max_type_size, max_values, memory_max_size_required, - memory_offset_choices: (75, 25, 0), min_element_segments, min_elements, min_globals, @@ -313,6 +312,8 @@ pub struct ConstantParams { float_enabled: bool, memory_grow_enabled: bool, min_types: usize, + memory_offset_choices: (u32, u32, u32), + reserved_memory_size: Option, } impl Default for ConstantParams { @@ -344,6 +345,8 @@ impl Default for ConstantParams { min_data_segments: 0, max_types: 100, min_types: 5, + memory_offset_choices: (75, 25, 0), + reserved_memory_size: Some(MemoryLayout::RESERVED_MEMORY_SIZE as u64), } } } From 7ec0f1586d6645e9d6e15fced4a1b788ac2fce10 Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Sun, 28 Jan 2024 23:07:54 +0300 Subject: [PATCH 23/33] add new memory_layout module --- .../src/generator/syscalls/invocator.rs | 39 +------------ utils/wasm-gen/src/lib.rs | 3 + utils/wasm-gen/src/memory_layout.rs | 56 +++++++++++++++++++ 3 files changed, 61 insertions(+), 37 deletions(-) create mode 100644 utils/wasm-gen/src/memory_layout.rs diff --git a/utils/wasm-gen/src/generator/syscalls/invocator.rs b/utils/wasm-gen/src/generator/syscalls/invocator.rs index affe9f2c29a..190b6a983fa 100644 --- a/utils/wasm-gen/src/generator/syscalls/invocator.rs +++ b/utils/wasm-gen/src/generator/syscalls/invocator.rs @@ -25,8 +25,8 @@ use crate::{ }, utils::{self, WasmWords}, wasm::{PageCount as WasmPageCount, WasmModule}, - ActorKind, InvocableSyscall, PtrParamAllowedValues, RegularParamAllowedValues, SyscallsConfig, - SyscallsParamsConfig, + ActorKind, InvocableSyscall, MemoryLayout, PtrParamAllowedValues, RegularParamAllowedValues, + SyscallsConfig, SyscallsParamsConfig, }; use arbitrary::{Result, Unstructured}; use gear_wasm_instrument::{ @@ -802,41 +802,6 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> { } } -/// Represents memory layout that can be safely used between syscalls and instructions. -pub struct MemoryLayout { - pub init_called_ptr: i32, - pub wait_called_ptr: i32, - pub remaining_memory_len: u32, - pub remaining_memory_ptr: i32, -} - -impl MemoryLayout { - /// The amount of reserved memory. - pub const RESERVED_MEMORY_SIZE: u32 = 256; -} - -impl From for MemoryLayout { - fn from(mem_size: u32) -> Self { - let start_memory_ptr = mem_size.saturating_sub(Self::RESERVED_MEMORY_SIZE) as i32; - let init_called_ptr = start_memory_ptr; - let wait_called_ptr = init_called_ptr + mem::size_of::() as i32; - let remaining_memory_ptr = wait_called_ptr + mem::size_of::() as i32; - let remaining_memory_len = (remaining_memory_ptr - start_memory_ptr) as u32; - - assert!( - remaining_memory_len <= Self::RESERVED_MEMORY_SIZE, - "reserved memory exceeded" - ); - - Self { - init_called_ptr, - wait_called_ptr, - remaining_memory_len, - remaining_memory_ptr, - } - } -} - /// Disabled syscalls invocator. /// /// This type signals that syscalls imports generation and syscalls invocation diff --git a/utils/wasm-gen/src/lib.rs b/utils/wasm-gen/src/lib.rs index e535b26c5a7..23ead6ffa22 100644 --- a/utils/wasm-gen/src/lib.rs +++ b/utils/wasm-gen/src/lib.rs @@ -30,6 +30,8 @@ pub mod wasm_gen_arbitrary { } pub mod config; pub mod generator; +pub mod memory_layout; + #[cfg(test)] mod tests; mod utils; @@ -38,6 +40,7 @@ mod wasm; pub use config::*; pub use gear_wasm_instrument::syscalls::SyscallName; pub use generator::*; +pub use memory_layout::*; pub use wasm::WasmModule; pub use wasm_gen_arbitrary::*; diff --git a/utils/wasm-gen/src/memory_layout.rs b/utils/wasm-gen/src/memory_layout.rs new file mode 100644 index 00000000000..67e2926362b --- /dev/null +++ b/utils/wasm-gen/src/memory_layout.rs @@ -0,0 +1,56 @@ +// This file is part of Gear. + +// Copyright (C) 2021-2024 Gear Technologies Inc. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! TODO. + +use std::mem; + +/// Represents memory layout that can be safely used between syscalls and instructions. +pub struct MemoryLayout { + pub init_called_ptr: i32, + pub wait_called_ptr: i32, + pub remaining_memory_len: u32, + pub remaining_memory_ptr: i32, +} + +impl MemoryLayout { + /// The amount of reserved memory. + pub const RESERVED_MEMORY_SIZE: u32 = 256; +} + +impl From for MemoryLayout { + fn from(mem_size: u32) -> Self { + let start_memory_ptr = mem_size.saturating_sub(Self::RESERVED_MEMORY_SIZE) as i32; + let init_called_ptr = start_memory_ptr; + let wait_called_ptr = init_called_ptr + mem::size_of::() as i32; + let remaining_memory_ptr = wait_called_ptr + mem::size_of::() as i32; + let remaining_memory_len = (remaining_memory_ptr - start_memory_ptr) as u32; + + assert!( + remaining_memory_len <= Self::RESERVED_MEMORY_SIZE, + "reserved memory exceeded" + ); + + Self { + init_called_ptr, + wait_called_ptr, + remaining_memory_len, + remaining_memory_ptr, + } + } +} From 4c4478d36646d3a2b4134c86ea6344f69dab7572 Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Sun, 28 Jan 2024 23:10:21 +0300 Subject: [PATCH 24/33] pass mem_import_gen_proof to the entry point generator for better type-level guarantees --- utils/wasm-gen/src/generator.rs | 19 ++++++++++++++----- utils/wasm-gen/src/generator/entry_points.rs | 14 +++++++++++--- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/utils/wasm-gen/src/generator.rs b/utils/wasm-gen/src/generator.rs index 4bfda9c3cf3..3fcff1d7029 100644 --- a/utils/wasm-gen/src/generator.rs +++ b/utils/wasm-gen/src/generator.rs @@ -124,8 +124,9 @@ impl<'a, 'b> GearWasmGenerator<'a, 'b> { let (disabled_mem_gen, frozen_gear_wasm_gen, mem_imports_gen_proof) = self.generate_memory_export(); - let (disabled_ep_gen, frozen_gear_wasm_gen, ep_gen_proof) = - Self::from((disabled_mem_gen, frozen_gear_wasm_gen)).generate_entry_points()?; + let (disabled_ep_gen, frozen_gear_wasm_gen, ep_gen_proof, mem_imports_gen_proof) = + Self::from((disabled_mem_gen, frozen_gear_wasm_gen)) + .generate_entry_points(mem_imports_gen_proof)?; let (disabled_syscalls_invocator, frozen_gear_wasm_gen) = Self::from((disabled_ep_gen, frozen_gear_wasm_gen)) @@ -173,16 +174,24 @@ impl<'a, 'b> GearWasmGenerator<'a, 'b> { /// Generate gear wasm gentry points using entry points generator. pub fn generate_entry_points( self, + mem_import_gen_proof: MemoryImportGenerationProof, ) -> Result<( DisabledEntryPointsGenerator<'a, 'b>, FrozenGearWasmGenerator<'a, 'b>, GearEntryPointGenerationProof, + MemoryImportGenerationProof, )> { let (ep_gen, frozen_gear_wasm_gen): (EntryPointsGenerator, FrozenGearWasmGenerator) = self.into(); - let (disabled_ep_gen, ep_gen_proof) = ep_gen.generate_entry_points()?; - - Ok((disabled_ep_gen, frozen_gear_wasm_gen, ep_gen_proof)) + let (disabled_ep_gen, ep_gen_proof, mem_import_gen_proof) = + ep_gen.generate_entry_points(mem_import_gen_proof)?; + + Ok(( + disabled_ep_gen, + frozen_gear_wasm_gen, + ep_gen_proof, + mem_import_gen_proof, + )) } /// Generate syscalls using syscalls module generators. diff --git a/utils/wasm-gen/src/generator/entry_points.rs b/utils/wasm-gen/src/generator/entry_points.rs index 7a1b8046a0b..8a64541f1fd 100644 --- a/utils/wasm-gen/src/generator/entry_points.rs +++ b/utils/wasm-gen/src/generator/entry_points.rs @@ -19,7 +19,10 @@ //! Gear wasm entry points generator module. use crate::{ - generator::{CallIndexes, FrozenGearWasmGenerator, GearWasmGenerator, ModuleWithCallIndexes}, + generator::{ + CallIndexes, FrozenGearWasmGenerator, GearWasmGenerator, MemoryImportGenerationProof, + ModuleWithCallIndexes, + }, wasm::{PageCount as WasmPageCount, WasmModule}, EntryPointsSet, MemoryLayout, }; @@ -100,9 +103,11 @@ impl<'a, 'b> EntryPointsGenerator<'a, 'b> { /// Returns disabled entry points generator and a proof that all entry points from config were generated. pub fn generate_entry_points( mut self, + mem_import_gen_proof: MemoryImportGenerationProof, ) -> Result<( DisabledEntryPointsGenerator<'a, 'b>, GearEntryPointGenerationProof, + MemoryImportGenerationProof, )> { log::trace!("Generating gear entry points"); @@ -118,7 +123,11 @@ impl<'a, 'b> EntryPointsGenerator<'a, 'b> { self.generate_export("handle_reply")?; } - Ok((self.disable(), GearEntryPointGenerationProof(()))) + Ok(( + self.disable(), + GearEntryPointGenerationProof(()), + mem_import_gen_proof, + )) } /// Generates an export function with a `name`. @@ -221,7 +230,6 @@ impl<'a, 'b> EntryPointsGenerator<'a, 'b> { .module .initial_mem_size() .expect("generator is instantiated with a mem import generation proof"); - let mem_size = Into::::into(memory_size_pages).memory_size(); let MemoryLayout { From 7bc1ecb465b6b94478550710801dfd193e30ae2b Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Sun, 28 Jan 2024 23:55:57 +0300 Subject: [PATCH 25/33] [skip-ci] add docs for memory layout --- utils/wasm-gen/src/memory_layout.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/utils/wasm-gen/src/memory_layout.rs b/utils/wasm-gen/src/memory_layout.rs index 67e2926362b..d6445f33ce7 100644 --- a/utils/wasm-gen/src/memory_layout.rs +++ b/utils/wasm-gen/src/memory_layout.rs @@ -16,11 +16,18 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -//! TODO. +//! The last memory page in program generated by `wasm-gen` is reserved for +//! internal use. Currently, we take [`MemoryLayout::RESERVED_MEMORY_SIZE`] +//! bytes from the last memory page and also prohibit modification of this +//! memory at the `wasm-smith` and `wasm-gen` level. +//! +//! If you want to store some data in memory and then access it in the program, +//! consider adding a new pointer to [`MemoryLayout`] structure. use std::mem; -/// Represents memory layout that can be safely used between syscalls and instructions. +/// Represents memory layout that can be safely used between syscalls and +/// instructions. pub struct MemoryLayout { pub init_called_ptr: i32, pub wait_called_ptr: i32, From c2f26f937bcbcb4e1c56051ff93832b1e8fdb4e8 Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Thu, 1 Feb 2024 14:38:37 +0300 Subject: [PATCH 26/33] use NonZeroU32 --- utils/wasm-gen/src/config.rs | 6 ++++-- utils/wasm-gen/src/config/syscalls.rs | 7 ++++--- utils/wasm-gen/src/generator/syscalls/invocator.rs | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/utils/wasm-gen/src/config.rs b/utils/wasm-gen/src/config.rs index ae3c67755c0..a4ed9e43b3a 100644 --- a/utils/wasm-gen/src/config.rs +++ b/utils/wasm-gen/src/config.rs @@ -93,6 +93,8 @@ //! There's a pre-defined one - [`StandardGearWasmConfigsBundle`], usage of which will result //! in generation of valid (always) gear-wasm module. +use std::num::NonZeroU32; + mod generator; mod module; mod syscalls; @@ -135,7 +137,7 @@ pub struct StandardGearWasmConfigsBundle { /// /// For example, if this parameter is 4, wait syscalls will be invoked /// with probability 1/4. - pub waiting_probability: Option, + pub waiting_probability: Option, /// Flag which signals whether recursions must be removed. pub remove_recursion: bool, /// If the limit is set to `Some(_)`, programs will try to stop execution @@ -161,7 +163,7 @@ impl Default for StandardGearWasmConfigsBundle { fn default() -> Self { Self { log_info: Some("StandardGearWasmConfigsBundle".into()), - waiting_probability: Some(4), + waiting_probability: NonZeroU32::new(4), remove_recursion: false, critical_gas_limit: Some(1_000_000), injection_types: SyscallsInjectionTypes::all_once(), diff --git a/utils/wasm-gen/src/config/syscalls.rs b/utils/wasm-gen/src/config/syscalls.rs index 10385a5727a..e120917099e 100644 --- a/utils/wasm-gen/src/config/syscalls.rs +++ b/utils/wasm-gen/src/config/syscalls.rs @@ -25,6 +25,7 @@ mod precise; mod process_errors; use gear_wasm_instrument::syscalls::SyscallName; +use std::num::NonZeroU32; pub use injection::*; pub use param::*; @@ -95,7 +96,7 @@ impl SyscallsConfigBuilder { } /// Set probability of wait syscalls. - pub fn with_waiting_probability(mut self, waiting_probability: u32) -> Self { + pub fn with_waiting_probability(mut self, waiting_probability: NonZeroU32) -> Self { self.0.waiting_probability = Some(waiting_probability); self @@ -122,7 +123,7 @@ pub struct SyscallsConfig { precise_syscalls_config: PreciseSyscallsConfig, error_processing_config: ErrorProcessingConfig, log_info: Option, - waiting_probability: Option, + waiting_probability: Option, } impl SyscallsConfig { @@ -154,7 +155,7 @@ impl SyscallsConfig { } /// Get probability of wait syscalls. - pub fn waiting_probability(&self) -> Option { + pub fn waiting_probability(&self) -> Option { self.waiting_probability } } diff --git a/utils/wasm-gen/src/generator/syscalls/invocator.rs b/utils/wasm-gen/src/generator/syscalls/invocator.rs index 190b6a983fa..367d8801c39 100644 --- a/utils/wasm-gen/src/generator/syscalls/invocator.rs +++ b/utils/wasm-gen/src/generator/syscalls/invocator.rs @@ -323,7 +323,7 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> { .waiting_probability() .filter(|_| invocable.is_wait_syscall()) { - self.limit_infinite_waits(&mut instructions, waiting_probability); + self.limit_infinite_waits(&mut instructions, waiting_probability.get()); } log::trace!( From 5f3c29e5b9e1f7af0c50641f7dc850d3a06aba1b Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Thu, 1 Feb 2024 15:24:04 +0300 Subject: [PATCH 27/33] fix tests --- utils/wasm-gen/src/tests.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/wasm-gen/src/tests.rs b/utils/wasm-gen/src/tests.rs index ef627f3807d..5a657481066 100644 --- a/utils/wasm-gen/src/tests.rs +++ b/utils/wasm-gen/src/tests.rs @@ -40,7 +40,7 @@ use gear_wasm_instrument::{ }; use proptest::prelude::*; use rand::{rngs::SmallRng, RngCore, SeedableRng}; -use std::num::NonZeroUsize; +use std::num::{NonZeroU32, NonZeroUsize}; const UNSTRUCTURED_SIZE: usize = 1_000_000; @@ -181,7 +181,7 @@ fn test_avoid_waits_works() { let mut injection_types = SyscallsInjectionTypes::all_never(); injection_types.set(InvocableSyscall::Loose(SyscallName::Wait), 1, 1); let syscalls_config = SyscallsConfigBuilder::new(injection_types) - .with_waiting_probability(4) + .with_waiting_probability(NonZeroU32::new(4).unwrap()) .build(); let backend_report = From 7c47b8d95537aa2cbe2e7122bafdfd3166f760ff Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Thu, 1 Feb 2024 15:27:29 +0300 Subject: [PATCH 28/33] move memory layout to wasm module --- utils/wasm-gen/src/lib.rs | 4 +- utils/wasm-gen/src/memory_layout.rs | 63 ----------------------------- utils/wasm-gen/src/wasm.rs | 44 ++++++++++++++++++++ 3 files changed, 45 insertions(+), 66 deletions(-) delete mode 100644 utils/wasm-gen/src/memory_layout.rs diff --git a/utils/wasm-gen/src/lib.rs b/utils/wasm-gen/src/lib.rs index 23ead6ffa22..c9cce715653 100644 --- a/utils/wasm-gen/src/lib.rs +++ b/utils/wasm-gen/src/lib.rs @@ -30,7 +30,6 @@ pub mod wasm_gen_arbitrary { } pub mod config; pub mod generator; -pub mod memory_layout; #[cfg(test)] mod tests; @@ -40,8 +39,7 @@ mod wasm; pub use config::*; pub use gear_wasm_instrument::syscalls::SyscallName; pub use generator::*; -pub use memory_layout::*; -pub use wasm::WasmModule; +pub use wasm::{MemoryLayout, WasmModule}; pub use wasm_gen_arbitrary::*; use gear_wasm_instrument::parity_wasm::{self, elements::Module}; diff --git a/utils/wasm-gen/src/memory_layout.rs b/utils/wasm-gen/src/memory_layout.rs deleted file mode 100644 index d6445f33ce7..00000000000 --- a/utils/wasm-gen/src/memory_layout.rs +++ /dev/null @@ -1,63 +0,0 @@ -// This file is part of Gear. - -// Copyright (C) 2021-2024 Gear Technologies Inc. -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -//! The last memory page in program generated by `wasm-gen` is reserved for -//! internal use. Currently, we take [`MemoryLayout::RESERVED_MEMORY_SIZE`] -//! bytes from the last memory page and also prohibit modification of this -//! memory at the `wasm-smith` and `wasm-gen` level. -//! -//! If you want to store some data in memory and then access it in the program, -//! consider adding a new pointer to [`MemoryLayout`] structure. - -use std::mem; - -/// Represents memory layout that can be safely used between syscalls and -/// instructions. -pub struct MemoryLayout { - pub init_called_ptr: i32, - pub wait_called_ptr: i32, - pub remaining_memory_len: u32, - pub remaining_memory_ptr: i32, -} - -impl MemoryLayout { - /// The amount of reserved memory. - pub const RESERVED_MEMORY_SIZE: u32 = 256; -} - -impl From for MemoryLayout { - fn from(mem_size: u32) -> Self { - let start_memory_ptr = mem_size.saturating_sub(Self::RESERVED_MEMORY_SIZE) as i32; - let init_called_ptr = start_memory_ptr; - let wait_called_ptr = init_called_ptr + mem::size_of::() as i32; - let remaining_memory_ptr = wait_called_ptr + mem::size_of::() as i32; - let remaining_memory_len = (remaining_memory_ptr - start_memory_ptr) as u32; - - assert!( - remaining_memory_len <= Self::RESERVED_MEMORY_SIZE, - "reserved memory exceeded" - ); - - Self { - init_called_ptr, - wait_called_ptr, - remaining_memory_len, - remaining_memory_ptr, - } - } -} diff --git a/utils/wasm-gen/src/wasm.rs b/utils/wasm-gen/src/wasm.rs index e35c4d0d7bf..7487e189209 100644 --- a/utils/wasm-gen/src/wasm.rs +++ b/utils/wasm-gen/src/wasm.rs @@ -196,3 +196,47 @@ impl PageCount { self.0 * WASM_PAGE_SIZE as u32 } } + +/// Represents memory layout that can be safely used between syscalls and +/// instructions. +/// +/// The last memory page in program generated by `wasm-gen` is reserved for +/// internal use. Currently, we take [`MemoryLayout::RESERVED_MEMORY_SIZE`] +/// bytes from the last memory page and also prohibit modification of this +/// memory at the `wasm-smith` and `wasm-gen` level. +/// +/// If you want to store some data in memory and then access it in the program, +/// consider adding a new pointer to this structure. +pub struct MemoryLayout { + pub init_called_ptr: i32, + pub wait_called_ptr: i32, + pub remaining_memory_len: u32, + pub remaining_memory_ptr: i32, +} + +impl MemoryLayout { + /// The amount of reserved memory. + pub const RESERVED_MEMORY_SIZE: u32 = 256; +} + +impl From for MemoryLayout { + fn from(mem_size: u32) -> Self { + let start_memory_ptr = mem_size.saturating_sub(Self::RESERVED_MEMORY_SIZE) as i32; + let init_called_ptr = start_memory_ptr; + let wait_called_ptr = init_called_ptr + mem::size_of::() as i32; + let remaining_memory_ptr = wait_called_ptr + mem::size_of::() as i32; + let remaining_memory_len = (remaining_memory_ptr - start_memory_ptr) as u32; + + assert!( + remaining_memory_len <= Self::RESERVED_MEMORY_SIZE, + "reserved memory exceeded" + ); + + Self { + init_called_ptr, + wait_called_ptr, + remaining_memory_len, + remaining_memory_ptr, + } + } +} From fc444a6dbff9fd3937a7b9c2b37c25764e77a5db Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Mon, 5 Feb 2024 15:49:54 +0300 Subject: [PATCH 29/33] add GearWasmGeneratorWithMemory newtype --- utils/wasm-gen/src/generator.rs | 7 ++++-- utils/wasm-gen/src/generator/entry_points.rs | 23 +++++++++++++++++--- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/utils/wasm-gen/src/generator.rs b/utils/wasm-gen/src/generator.rs index 3fcff1d7029..929c4e48093 100644 --- a/utils/wasm-gen/src/generator.rs +++ b/utils/wasm-gen/src/generator.rs @@ -181,8 +181,11 @@ impl<'a, 'b> GearWasmGenerator<'a, 'b> { GearEntryPointGenerationProof, MemoryImportGenerationProof, )> { - let (ep_gen, frozen_gear_wasm_gen): (EntryPointsGenerator, FrozenGearWasmGenerator) = - self.into(); + let (ep_gen, frozen_gear_wasm_gen, mem_import_gen_proof): ( + EntryPointsGenerator, + FrozenGearWasmGenerator, + MemoryImportGenerationProof, + ) = GearWasmGeneratorWithMemory::from((self, mem_import_gen_proof)).into(); let (disabled_ep_gen, ep_gen_proof, mem_import_gen_proof) = ep_gen.generate_entry_points(mem_import_gen_proof)?; diff --git a/utils/wasm-gen/src/generator/entry_points.rs b/utils/wasm-gen/src/generator/entry_points.rs index 8a64541f1fd..4846c948cad 100644 --- a/utils/wasm-gen/src/generator/entry_points.rs +++ b/utils/wasm-gen/src/generator/entry_points.rs @@ -42,13 +42,30 @@ pub struct EntryPointsGenerator<'a, 'b> { call_indexes: CallIndexes, } -impl<'a, 'b> From> +pub struct GearWasmGeneratorWithMemory<'a, 'b>( + GearWasmGenerator<'a, 'b>, + MemoryImportGenerationProof, +); + +impl<'a, 'b> From<(GearWasmGenerator<'a, 'b>, MemoryImportGenerationProof)> + for GearWasmGeneratorWithMemory<'a, 'b> +{ + fn from( + (generator, mem_import_gen_proof): (GearWasmGenerator<'a, 'b>, MemoryImportGenerationProof), + ) -> Self { + Self(generator, mem_import_gen_proof) + } +} + +impl<'a, 'b> From> for ( EntryPointsGenerator<'a, 'b>, FrozenGearWasmGenerator<'a, 'b>, + MemoryImportGenerationProof, ) { - fn from(generator: GearWasmGenerator<'a, 'b>) -> Self { + fn from(generator_with_memory: GearWasmGeneratorWithMemory<'a, 'b>) -> Self { + let GearWasmGeneratorWithMemory(generator, mem_import_gen_proof) = generator_with_memory; let ep_generator = EntryPointsGenerator { unstructured: generator.unstructured, module: generator.module, @@ -61,7 +78,7 @@ impl<'a, 'b> From> unstructured: None, }; - (ep_generator, frozen) + (ep_generator, frozen, mem_import_gen_proof) } } From fa20ca27e57923ec1bde089aca64a306ebeb1b27 Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Mon, 5 Feb 2024 16:18:09 +0300 Subject: [PATCH 30/33] rename newtype to EntryPointsGeneratorInstantiator --- utils/wasm-gen/src/generator.rs | 4 +++- utils/wasm-gen/src/generator/entry_points.rs | 22 ++++++++++---------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/utils/wasm-gen/src/generator.rs b/utils/wasm-gen/src/generator.rs index 0b1a23bfc78..58c7bbca723 100644 --- a/utils/wasm-gen/src/generator.rs +++ b/utils/wasm-gen/src/generator.rs @@ -179,11 +179,13 @@ impl<'a, 'b> GearWasmGenerator<'a, 'b> { GearEntryPointGenerationProof, MemoryImportGenerationProof, )> { + let entry_points_gen_instantiator = + EntryPointsGeneratorInstantiator::from((self, mem_import_gen_proof)); let (ep_gen, frozen_gear_wasm_gen, mem_import_gen_proof): ( EntryPointsGenerator, FrozenGearWasmGenerator, MemoryImportGenerationProof, - ) = GearWasmGeneratorWithMemory::from((self, mem_import_gen_proof)).into(); + ) = entry_points_gen_instantiator.into(); let (disabled_ep_gen, ep_gen_proof, mem_import_gen_proof) = ep_gen.generate_entry_points(mem_import_gen_proof)?; diff --git a/utils/wasm-gen/src/generator/entry_points.rs b/utils/wasm-gen/src/generator/entry_points.rs index 4846c948cad..d3cd0e7dda6 100644 --- a/utils/wasm-gen/src/generator/entry_points.rs +++ b/utils/wasm-gen/src/generator/entry_points.rs @@ -42,30 +42,30 @@ pub struct EntryPointsGenerator<'a, 'b> { call_indexes: CallIndexes, } -pub struct GearWasmGeneratorWithMemory<'a, 'b>( - GearWasmGenerator<'a, 'b>, - MemoryImportGenerationProof, +/// Entry points generator instantiator. +/// +/// Serves as a new type in order to create the generator from gear wasm generator and memory import proof. +pub struct EntryPointsGeneratorInstantiator<'a, 'b>( + (GearWasmGenerator<'a, 'b>, MemoryImportGenerationProof), ); impl<'a, 'b> From<(GearWasmGenerator<'a, 'b>, MemoryImportGenerationProof)> - for GearWasmGeneratorWithMemory<'a, 'b> + for EntryPointsGeneratorInstantiator<'a, 'b> { - fn from( - (generator, mem_import_gen_proof): (GearWasmGenerator<'a, 'b>, MemoryImportGenerationProof), - ) -> Self { - Self(generator, mem_import_gen_proof) + fn from(inner: (GearWasmGenerator<'a, 'b>, MemoryImportGenerationProof)) -> Self { + Self(inner) } } -impl<'a, 'b> From> +impl<'a, 'b> From> for ( EntryPointsGenerator<'a, 'b>, FrozenGearWasmGenerator<'a, 'b>, MemoryImportGenerationProof, ) { - fn from(generator_with_memory: GearWasmGeneratorWithMemory<'a, 'b>) -> Self { - let GearWasmGeneratorWithMemory(generator, mem_import_gen_proof) = generator_with_memory; + fn from(instantiator: EntryPointsGeneratorInstantiator<'a, 'b>) -> Self { + let EntryPointsGeneratorInstantiator((generator, mem_import_gen_proof)) = instantiator; let ep_generator = EntryPointsGenerator { unstructured: generator.unstructured, module: generator.module, From fcaeac64f59beba979961dd2cc032303286f8c89 Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Wed, 7 Feb 2024 17:33:32 +0300 Subject: [PATCH 31/33] remove mem_imports_gen_proof from SyscallsImportsGeneratorInstantiator --- utils/wasm-gen/src/generator.rs | 14 +++--------- .../src/generator/syscalls/imports.rs | 22 ++++--------------- 2 files changed, 7 insertions(+), 29 deletions(-) diff --git a/utils/wasm-gen/src/generator.rs b/utils/wasm-gen/src/generator.rs index 58c7bbca723..a242bd60143 100644 --- a/utils/wasm-gen/src/generator.rs +++ b/utils/wasm-gen/src/generator.rs @@ -124,13 +124,12 @@ impl<'a, 'b> GearWasmGenerator<'a, 'b> { let (disabled_mem_gen, frozen_gear_wasm_gen, mem_imports_gen_proof) = self.generate_memory_export(); - let (disabled_ep_gen, frozen_gear_wasm_gen, ep_gen_proof, mem_imports_gen_proof) = + let (disabled_ep_gen, frozen_gear_wasm_gen, ep_gen_proof) = Self::from((disabled_mem_gen, frozen_gear_wasm_gen)) .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(mem_imports_gen_proof, ep_gen_proof)?; + Self::from((disabled_ep_gen, frozen_gear_wasm_gen)).generate_syscalls(ep_gen_proof)?; let config = frozen_gear_wasm_gen.melt(); let module = ModuleWithCallIndexes::from(disabled_syscalls_invocator) @@ -177,7 +176,6 @@ impl<'a, 'b> GearWasmGenerator<'a, 'b> { DisabledEntryPointsGenerator<'a, 'b>, FrozenGearWasmGenerator<'a, 'b>, GearEntryPointGenerationProof, - MemoryImportGenerationProof, )> { let entry_points_gen_instantiator = EntryPointsGeneratorInstantiator::from((self, mem_import_gen_proof)); @@ -189,18 +187,12 @@ impl<'a, 'b> GearWasmGenerator<'a, 'b> { let (disabled_ep_gen, ep_gen_proof, mem_import_gen_proof) = ep_gen.generate_entry_points(mem_import_gen_proof)?; - Ok(( - disabled_ep_gen, - frozen_gear_wasm_gen, - ep_gen_proof, - mem_import_gen_proof, - )) + Ok((disabled_ep_gen, frozen_gear_wasm_gen, ep_gen_proof)) } /// Generate syscalls using syscalls module generators. pub fn generate_syscalls( self, - mem_import_gen_proof: MemoryImportGenerationProof, ep_gen_proof: GearEntryPointGenerationProof, ) -> Result<(DisabledSyscallsInvocator, FrozenGearWasmGenerator<'a, 'b>)> { let syscalls_imports_gen_instantiator = diff --git a/utils/wasm-gen/src/generator/syscalls/imports.rs b/utils/wasm-gen/src/generator/syscalls/imports.rs index 7a7713e40d6..3e0a7b1007e 100644 --- a/utils/wasm-gen/src/generator/syscalls/imports.rs +++ b/utils/wasm-gen/src/generator/syscalls/imports.rs @@ -71,20 +71,10 @@ pub enum PreciseSyscallError { Arbitrary(#[from] ArbitraryError), } -impl<'a, 'b> - From<( - GearWasmGenerator<'a, 'b>, - MemoryImportGenerationProof, - GearEntryPointGenerationProof, - )> for SyscallsImportsGeneratorInstantiator<'a, 'b> +impl<'a, 'b> From<(GearWasmGenerator<'a, 'b>, GearEntryPointGenerationProof)> + for SyscallsImportsGeneratorInstantiator<'a, 'b> { - fn from( - inner: ( - GearWasmGenerator<'a, 'b>, - MemoryImportGenerationProof, - GearEntryPointGenerationProof, - ), - ) -> Self { + fn from(inner: (GearWasmGenerator<'a, 'b>, GearEntryPointGenerationProof)) -> Self { Self(inner) } } @@ -96,11 +86,7 @@ impl<'a, 'b> From> ) { fn from(instantiator: SyscallsImportsGeneratorInstantiator<'a, 'b>) -> Self { - let SyscallsImportsGeneratorInstantiator(( - generator, - _mem_import_gen_proof, - _gen_ep_gen_proof, - )) = instantiator; + let SyscallsImportsGeneratorInstantiator((generator, _gen_ep_gen_proof)) = instantiator; let syscall_gen = SyscallsImportsGenerator { unstructured: generator.unstructured, call_indexes: generator.call_indexes, From 9addce95ca305cf44cac28a1f450dd8558919d81 Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Wed, 7 Feb 2024 17:42:38 +0300 Subject: [PATCH 32/33] fix --- utils/wasm-gen/src/generator.rs | 12 ++++-------- utils/wasm-gen/src/generator/entry_points.rs | 13 +++---------- utils/wasm-gen/src/generator/syscalls/imports.rs | 6 +----- 3 files changed, 8 insertions(+), 23 deletions(-) diff --git a/utils/wasm-gen/src/generator.rs b/utils/wasm-gen/src/generator.rs index a242bd60143..08a0efa45ba 100644 --- a/utils/wasm-gen/src/generator.rs +++ b/utils/wasm-gen/src/generator.rs @@ -179,13 +179,9 @@ impl<'a, 'b> GearWasmGenerator<'a, 'b> { )> { let entry_points_gen_instantiator = EntryPointsGeneratorInstantiator::from((self, mem_import_gen_proof)); - let (ep_gen, frozen_gear_wasm_gen, mem_import_gen_proof): ( - EntryPointsGenerator, - FrozenGearWasmGenerator, - MemoryImportGenerationProof, - ) = entry_points_gen_instantiator.into(); - let (disabled_ep_gen, ep_gen_proof, mem_import_gen_proof) = - ep_gen.generate_entry_points(mem_import_gen_proof)?; + let (ep_gen, frozen_gear_wasm_gen): (EntryPointsGenerator, FrozenGearWasmGenerator) = + entry_points_gen_instantiator.into(); + let (disabled_ep_gen, ep_gen_proof) = ep_gen.generate_entry_points()?; Ok((disabled_ep_gen, frozen_gear_wasm_gen, ep_gen_proof)) } @@ -196,7 +192,7 @@ impl<'a, 'b> GearWasmGenerator<'a, 'b> { ep_gen_proof: GearEntryPointGenerationProof, ) -> Result<(DisabledSyscallsInvocator, FrozenGearWasmGenerator<'a, 'b>)> { let syscalls_imports_gen_instantiator = - SyscallsImportsGeneratorInstantiator::from((self, mem_import_gen_proof, ep_gen_proof)); + 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()?; diff --git a/utils/wasm-gen/src/generator/entry_points.rs b/utils/wasm-gen/src/generator/entry_points.rs index d3cd0e7dda6..1df7dfae639 100644 --- a/utils/wasm-gen/src/generator/entry_points.rs +++ b/utils/wasm-gen/src/generator/entry_points.rs @@ -61,11 +61,10 @@ impl<'a, 'b> From> for ( EntryPointsGenerator<'a, 'b>, FrozenGearWasmGenerator<'a, 'b>, - MemoryImportGenerationProof, ) { fn from(instantiator: EntryPointsGeneratorInstantiator<'a, 'b>) -> Self { - let EntryPointsGeneratorInstantiator((generator, mem_import_gen_proof)) = instantiator; + let EntryPointsGeneratorInstantiator((generator, _mem_import_gen_proof)) = instantiator; let ep_generator = EntryPointsGenerator { unstructured: generator.unstructured, module: generator.module, @@ -78,7 +77,7 @@ impl<'a, 'b> From> unstructured: None, }; - (ep_generator, frozen, mem_import_gen_proof) + (ep_generator, frozen) } } @@ -120,11 +119,9 @@ impl<'a, 'b> EntryPointsGenerator<'a, 'b> { /// Returns disabled entry points generator and a proof that all entry points from config were generated. pub fn generate_entry_points( mut self, - mem_import_gen_proof: MemoryImportGenerationProof, ) -> Result<( DisabledEntryPointsGenerator<'a, 'b>, GearEntryPointGenerationProof, - MemoryImportGenerationProof, )> { log::trace!("Generating gear entry points"); @@ -140,11 +137,7 @@ impl<'a, 'b> EntryPointsGenerator<'a, 'b> { self.generate_export("handle_reply")?; } - Ok(( - self.disable(), - GearEntryPointGenerationProof(()), - mem_import_gen_proof, - )) + Ok((self.disable(), GearEntryPointGenerationProof(()))) } /// Generates an export function with a `name`. diff --git a/utils/wasm-gen/src/generator/syscalls/imports.rs b/utils/wasm-gen/src/generator/syscalls/imports.rs index 3e0a7b1007e..75466fcc2c4 100644 --- a/utils/wasm-gen/src/generator/syscalls/imports.rs +++ b/utils/wasm-gen/src/generator/syscalls/imports.rs @@ -50,11 +50,7 @@ pub struct SyscallsImportsGenerator<'a, 'b> { /// /// Serves as a new type in order to create the generator from gear wasm generator and proofs. pub struct SyscallsImportsGeneratorInstantiator<'a, 'b>( - ( - GearWasmGenerator<'a, 'b>, - MemoryImportGenerationProof, - GearEntryPointGenerationProof, - ), + (GearWasmGenerator<'a, 'b>, GearEntryPointGenerationProof), ); /// The set of syscalls that need to be imported to create precise syscall. From 0217157acf115b865db9ef22bdfe566a9038647b Mon Sep 17 00:00:00 2001 From: StackOverflowExcept1on <109800286+StackOverflowExcept1on@users.noreply.github.com> Date: Wed, 7 Feb 2024 17:49:22 +0300 Subject: [PATCH 33/33] [skip-ci] fix docs --- utils/wasm-gen/src/generator.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/utils/wasm-gen/src/generator.rs b/utils/wasm-gen/src/generator.rs index 08a0efa45ba..1f0024adc33 100644 --- a/utils/wasm-gen/src/generator.rs +++ b/utils/wasm-gen/src/generator.rs @@ -33,21 +33,14 @@ //! //! # First generators nesting level //! GearWasmGenerator--->MemoryGenerator--->DisabledMemoryGenerator--->ModuleWithCallIndexes--->WasmModule -//! GearWasmGenerator--->EntryPointsGenerator--->DisabledEntryPointsGenerator--->ModuleWithCallIndexes--->WasmModule //! //! # Second generators nesting level //! GearWasmGenerator--->MemoryGenerator--(DisabledMemoryGenerator, FrozenGearWasmGenerator)---\ //! |--->GearWasmGenerator--->EntryPointsGenerator--->DisabledEntryPointsGenerator--->ModuleWithCallIndexes---> //! -//! GearWasmGenerator--->EntryPointsGenerator--(DisabledEntryPointsGenerator, FrozenGearWasmGenerator)---\ -//! |--->GearWasmGenerator--->MemoryGenerator--->DisabledMemoryGenerator--->ModuleWithCallIndexes--->WasmModule -//! //! # Third generators nesting level //! GearWasmGenerator--->MemoryGenerator--(DisabledMemoryGenerator, FrozenGearWasmGenerator)---\ //! |--->GearWasmGenerator--->EntryPointsGenerator--->DisabledEntryPointsGenerator--(MemoryImportGenerationProof, GearEntryPointGenerationProof)-->(syscalls-module-state-machine) -//! -//! GearWasmGenerator--->EntryPointsGenerator--(DisabledEntryPointsGenerator, FrozenGearWasmGenerator)---\ -//! |--->GearWasmGenerator--->MemoryGenerator--->DisabledMemoryGenerator--(MemoryImportGenerationProof, GearEntryPointGenerationProof)-->(syscalls-module-state-machine) //! ``` //! //! State machine named `(syscalls-module-state-machine)` can be started only with having proof of work from `MemoryGenerator` and `EntryPointsGenerator`.