Skip to content

Commit

Permalink
feat(wasm-gen): Implement fallible syscalls error processing setup
Browse files Browse the repository at this point in the history
  • Loading branch information
mertwole authored Sep 4, 2023
1 parent 807472a commit 4c3bb97
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 16 deletions.
44 changes: 35 additions & 9 deletions utils/wasm-gen/src/config/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,13 @@ mod param;
use gear_utils::NonEmpty;
use gear_wasm_instrument::syscalls::SysCallName;
use gsys::{Hash, HashWithValue};
use std::ops::RangeInclusive;
use std::{collections::HashSet, ops::RangeInclusive};

pub use amount::*;
pub use param::*;

use crate::InvocableSysCall;

/// Builder for [`SysCallsConfig`].
pub struct SysCallsConfigBuilder(SysCallsConfig);

Expand All @@ -40,7 +42,7 @@ impl SysCallsConfigBuilder {
injection_amounts,
params_config: SysCallsParamsConfig::default(),
sending_message_destination: MessageDestination::default(),
ignore_fallible_syscall_errors: true,
error_processing_config: ErrorProcessingConfig::None,
log_info: None,
})
}
Expand Down Expand Up @@ -84,9 +86,9 @@ impl SysCallsConfigBuilder {
self
}

/// Enable/disable processing of errors returned from fallible syscalls.
pub fn set_ignore_fallible_syscall_errors(mut self, ignore: bool) -> Self {
self.0.ignore_fallible_syscall_errors = ignore;
/// Setup fallible syscalls error processing options.
pub fn set_error_processing_config(mut self, config: ErrorProcessingConfig) -> Self {
self.0.error_processing_config = config;

self
}
Expand All @@ -107,13 +109,37 @@ impl SysCallsConfigBuilder {
}
}

#[derive(Debug, Clone, Default)]
pub enum ErrorProcessingConfig {
/// Process errors on all the fallible syscalls.
All,
/// Process only errors on provided syscalls.
Whitelist(HashSet<InvocableSysCall>),
/// Process errors on all the syscalls excluding provided.
Blacklist(HashSet<InvocableSysCall>),
/// Don't process syscall errors at all.
#[default]
None,
}

impl ErrorProcessingConfig {
pub fn error_should_be_processed(&self, syscall: &InvocableSysCall) -> bool {
match self {
Self::All => true,
Self::Whitelist(wl) => wl.contains(syscall),
Self::Blacklist(bl) => !bl.contains(syscall),
Self::None => false,
}
}
}

/// United config for all entities in sys-calls generator module.
#[derive(Debug, Clone, Default)]
pub struct SysCallsConfig {
injection_amounts: SysCallsInjectionAmounts,
params_config: SysCallsParamsConfig,
sending_message_destination: MessageDestination,
ignore_fallible_syscall_errors: bool,
error_processing_config: ErrorProcessingConfig,
log_info: Option<String>,
}

Expand Down Expand Up @@ -142,9 +168,9 @@ impl SysCallsConfig {
&self.params_config
}

/// Should we ignore error processing of fallible syscalls?
pub fn ignore_fallible_syscall_errors(&self) -> bool {
self.ignore_fallible_syscall_errors
/// Error processing config for fallible syscalls.
pub fn error_processing_config(&self) -> &ErrorProcessingConfig {
&self.error_processing_config
}
}

Expand Down
4 changes: 2 additions & 2 deletions utils/wasm-gen/src/generator/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ use gear_wasm_instrument::syscalls::{ParamType, SysCallName, SysCallSignature};
/// which is pretty hard to predict beforehand with a generator. So this call context
/// is created from scratch - first `gr_reserve_gas` is called and then it's result
/// is used for the further `gr_reservation_send` call. Those are `Precise` sys-calls.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub(crate) enum InvocableSysCall {
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum InvocableSysCall {
Loose(SysCallName),
Precise(SysCallName),
}
Expand Down
22 changes: 18 additions & 4 deletions utils/wasm-gen/src/generator/syscalls/invocator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,14 +208,23 @@ impl<'a, 'b> SysCallsInvocator<'a, 'b> {
self.unstructured.len()
);

let insert_error_processing = self
.config
.error_processing_config()
.error_should_be_processed(&invocable);
let (fallible, mut signature) = (invocable.is_fallible(), invocable.into_signature());

if self.is_not_send_sys_call(invocable) {
log::trace!(
" -- Generating build call for non-send sys-call {}",
invocable.to_str()
);
return self.build_call(signature, fallible, call_indexes_handle);
return self.build_call(
signature,
fallible,
insert_error_processing,
call_indexes_handle,
);
}

log::trace!(
Expand All @@ -226,8 +235,12 @@ impl<'a, 'b> SysCallsInvocator<'a, 'b> {
// The value for the first param is chosen from config.
// It's either the result of `gr_source`, some existing address (set in the data section) or a completely random value.
signature.params.remove(0);
let mut call_without_destination_instrs =
self.build_call(signature, fallible, call_indexes_handle)?;
let mut call_without_destination_instrs = self.build_call(
signature,
fallible,
insert_error_processing,
call_indexes_handle,
)?;

let res = if self.config.sending_message_destination().is_source() {
log::trace!(" -- Message destination is result of `gr_source`");
Expand Down Expand Up @@ -306,6 +319,7 @@ impl<'a, 'b> SysCallsInvocator<'a, 'b> {
&mut self,
signature: SysCallSignature,
fallible: bool,
insert_error_processing: bool,
call_indexes_handle: CallIndexesHandle,
) -> Result<Vec<Instruction>> {
let param_setters = self.build_param_setters(&signature.params)?;
Expand All @@ -317,7 +331,7 @@ impl<'a, 'b> SysCallsInvocator<'a, 'b> {

instructions.push(Instruction::Call(call_indexes_handle as u32));

let mut result_processing = if self.config.ignore_fallible_syscall_errors() {
let mut result_processing = if !insert_error_processing {
Self::build_result_processing_ignored(signature)
} else if fallible {
Self::build_result_processing_fallible(signature, &param_setters)
Expand Down
8 changes: 7 additions & 1 deletion utils/wasm-gen/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,12 @@ fn execute_wasm_with_syscall_injected(
let mut injection_amounts = SysCallsInjectionAmounts::all_never();
injection_amounts.set(syscall, INJECTED_SYSCALLS, INJECTED_SYSCALLS);

let error_processing_config = if ignore_fallible_errors {
ErrorProcessingConfig::None
} else {
ErrorProcessingConfig::All
};

let gear_config = (
GearWasmGeneratorConfigBuilder::new()
.with_memory_config(MemoryPagesConfig {
Expand All @@ -256,7 +262,7 @@ fn execute_wasm_with_syscall_injected(
.with_sys_calls_config(
SysCallsConfigBuilder::new(injection_amounts)
.with_params_config(params_config)
.set_ignore_fallible_syscall_errors(ignore_fallible_errors)
.set_error_processing_config(error_processing_config)
.build(),
)
.with_entry_points_config(EntryPointsSet::Init)
Expand Down

0 comments on commit 4c3bb97

Please sign in to comment.