Skip to content

Commit

Permalink
refactor(wasm-instrument, wasm-gen): Make syscalls errors config and …
Browse files Browse the repository at this point in the history
…syscalls results processing more consistent (#3554)
  • Loading branch information
techraed authored Dec 12, 2023
1 parent 20d413c commit 5b021ea
Show file tree
Hide file tree
Showing 14 changed files with 887 additions and 685 deletions.
2 changes: 1 addition & 1 deletion gsys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ extern "C" {
err_mid_pid: *mut ErrorWithTwoHashes,
);

/// Fallible `gr_reply_deposit` syscall.
/// Fallible `gr_reply_deposit` control syscall.
///
/// Arguments type:
/// - `message_id`: `const ptr` for message id.
Expand Down
11 changes: 7 additions & 4 deletions pallets/gear/src/benchmarking/code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,10 +236,13 @@ where
// Import supervisor functions. They start with idx 0.
for name in def.imported_functions {
let sign = name.signature();
let sig = builder::signature()
.with_params(sign.params.into_iter().map(Into::into))
.with_results(sign.results.into_iter())
.build_sig();
let sig_builder =
builder::signature().with_params(sign.params().iter().copied().map(Into::into));
let results = sign
.results()
.map(|results| results.to_vec())
.unwrap_or_default();
let sig = sig_builder.with_results(results.into_iter()).build_sig();
let sig = program.push_signature(sig);
program = program
.import()
Expand Down
4 changes: 2 additions & 2 deletions pallets/gear/src/benchmarking/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1385,10 +1385,10 @@ where
assert!(repetitions <= 1);

let params = if let Some(c) = param {
assert!(name.signature().params.len() == 1);
assert!(name.signature().params().len() == 1);
vec![InstrI32Const(c)]
} else {
assert!(name.signature().params.is_empty());
assert!(name.signature().params().is_empty());
vec![]
};

Expand Down
11 changes: 7 additions & 4 deletions utils/node-loader/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ use gear_core::ids::{MessageId, ProgramId};
use gear_core_errors::ReplyCode;
use gear_utils::NonEmpty;
use gear_wasm_gen::{
EntryPointsSet, InvocableSyscall, ParamType, StandardGearWasmConfigsBundle, SyscallName,
SyscallsInjectionTypes, SyscallsParamsConfig,
EntryPointsSet, InvocableSyscall, ParamType, RegularParamType, StandardGearWasmConfigsBundle,
SyscallName, SyscallsInjectionTypes, SyscallsParamsConfig,
};
use gsdk::metadata::runtime_types::{
gear_common::event::DispatchStatus as GenDispatchStatus,
Expand Down Expand Up @@ -230,8 +230,11 @@ pub fn get_wasm_gen_config(
);

let mut params_config = SyscallsParamsConfig::default();
params_config.add_rule(ParamType::Alloc, (1..=10).into());
params_config.add_rule(ParamType::Free, (initial_pages..=initial_pages + 50).into());
params_config.add_rule(ParamType::Regular(RegularParamType::Alloc), (1..=10).into());
params_config.add_rule(
ParamType::Regular(RegularParamType::Free),
(initial_pages..=initial_pages + 50).into(),
);

StandardGearWasmConfigsBundle {
log_info: Some(format!("Gear program seed = '{seed}'")),
Expand Down
14 changes: 10 additions & 4 deletions utils/runtime-fuzzer/src/gear_calls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ use gear_call_gen::{ClaimValueArgs, SendReplyArgs};
use gear_core::ids::{CodeId, MessageId, ProgramId};
use gear_utils::NonEmpty;
use gear_wasm_gen::{
EntryPointsSet, InvocableSyscall, ParamType, StandardGearWasmConfigsBundle, SyscallName,
SyscallsInjectionTypes, SyscallsParamsConfig,
EntryPointsSet, InvocableSyscall, ParamType, RegularParamType, StandardGearWasmConfigsBundle,
SyscallName, SyscallsInjectionTypes, SyscallsParamsConfig,
};
use std::mem;

Expand Down Expand Up @@ -425,8 +425,14 @@ fn config(
);

let mut params_config = SyscallsParamsConfig::default();
params_config.add_rule(ParamType::Alloc, (10..=20).into());
params_config.add_rule(ParamType::Free, (initial_pages..=initial_pages + 35).into());
params_config.add_rule(
ParamType::Regular(RegularParamType::Alloc),
(10..=20).into(),
);
params_config.add_rule(
ParamType::Regular(RegularParamType::Free),
(initial_pages..=initial_pages + 35).into(),
);

let existing_addresses = NonEmpty::collect(
programs
Expand Down
27 changes: 2 additions & 25 deletions utils/wasm-gen/src/config/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,16 @@
mod injection;
mod param;
mod precise;
mod process_errors;

use gear_utils::NonEmpty;
use gear_wasm_instrument::syscalls::SyscallName;
use gsys::{Hash, HashWithValue};
use std::collections::HashSet;

pub use injection::*;
pub use param::*;
pub use precise::*;
pub use process_errors::*;

use crate::InvocableSyscall;

Expand Down Expand Up @@ -117,30 +118,6 @@ 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 syscalls generator module.
#[derive(Debug, Clone, Default)]
pub struct SyscallsConfig {
Expand Down
2 changes: 1 addition & 1 deletion utils/wasm-gen/src/config/syscalls/injection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ impl SyscallsInjectionTypes {
}
}

/// Imports the given syscall, if necessary.
/// Imports the given syscall, if possible.
pub(crate) fn enable_syscall_import(&mut self, name: InvocableSyscall) {
if let Some(injection_type @ SyscallInjectionType::None) = self.0.get_mut(&name) {
*injection_type = SyscallInjectionType::Import;
Expand Down
45 changes: 26 additions & 19 deletions utils/wasm-gen/src/config/syscalls/param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use crate::DEFAULT_INITIAL_SIZE;
use arbitrary::{Result, Unstructured};
use std::{collections::HashMap, ops::RangeInclusive};

pub use gear_wasm_instrument::syscalls::ParamType;
pub use gear_wasm_instrument::syscalls::{ParamType, RegularParamType};

/// Syscalls params config.
///
Expand All @@ -50,17 +50,21 @@ impl SyscallsParamsConfig {

/// New [`SyscallsParamsConfig`] with all rules set to produce one constant value.
pub fn all_constant_value(value: i64) -> Self {
use ParamType::*;
use RegularParamType::*;

let allowed_values: SyscallParamAllowedValues = (value..=value).into();
Self(
[
ParamType::Length,
ParamType::Gas,
ParamType::Offset,
ParamType::DurationBlockNumber,
ParamType::DelayBlockNumber,
ParamType::Handler,
ParamType::Free,
ParamType::Version,
Regular(Length),
Regular(Gas),
Regular(Offset),
Regular(DurationBlockNumber),
Regular(DelayBlockNumber),
Regular(Handler),
Regular(Free),
Regular(FreeUpperBound),
Regular(Version),
]
.into_iter()
.map(|param_type| (param_type, allowed_values.clone()))
Expand All @@ -75,7 +79,7 @@ impl SyscallsParamsConfig {

/// Set allowed values for the `param`.
pub fn add_rule(&mut self, param: ParamType, allowed_values: SyscallParamAllowedValues) {
matches!(param, ParamType::Ptr(..))
matches!(param, ParamType::Regular(RegularParamType::Pointer(_)))
.then(|| panic!("ParamType::Ptr(..) isn't supported in SyscallsParamsConfig"));

self.0.insert(param, allowed_values);
Expand All @@ -84,21 +88,24 @@ impl SyscallsParamsConfig {

impl Default for SyscallsParamsConfig {
fn default() -> Self {
use ParamType::*;
use RegularParamType::*;

let free_start = DEFAULT_INITIAL_SIZE as i64;
let free_end = free_start + 5;
Self(
[
(ParamType::Length, (0..=0x10000).into()),
(Regular(Length), (0..=0x10000).into()),
// There are no rules for memory arrays and pointers as they are chosen
// in accordance to memory pages config.
(ParamType::Gas, (0..=250_000_000_000).into()),
(ParamType::Offset, (0..=10).into()),
(ParamType::DurationBlockNumber, (1..=8).into()),
(ParamType::DelayBlockNumber, (0..=4).into()),
(ParamType::Handler, (0..=100).into()),
(ParamType::Free, (free_start..=free_end).into()),
(ParamType::FreeUpperBound, (0..=10).into()),
(ParamType::Version, (1..=1).into()),
(Regular(Gas), (0..=250_000_000_000).into()),
(Regular(Offset), (0..=10).into()),
(Regular(DurationBlockNumber), (1..=8).into()),
(Regular(DelayBlockNumber), (0..=4).into()),
(Regular(Handler), (0..=100).into()),
(Regular(Free), (free_start..=free_end).into()),
(Regular(Version), (1..=1).into()),
(Regular(FreeUpperBound), (0..=10).into()),
]
.into_iter()
.collect(),
Expand Down
84 changes: 84 additions & 0 deletions utils/wasm-gen/src/config/syscalls/process_errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// This file is part of Gear.

// Copyright (C) 2021-2023 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 <https://www.gnu.org/licenses/>.

//! Processing syscalls errors config.
use std::collections::HashSet;

use crate::InvocableSyscall;

#[derive(Debug, Clone, Default)]
pub enum ErrorProcessingConfig {
/// Process errors on all the fallible syscalls.
All,
/// Process only errors on provided syscalls.
Whitelist(ErrorProneSyscalls),
/// Process errors on all the syscalls excluding provided.
Blacklist(ErrorProneSyscalls),
/// 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) => {
if syscall.returns_error() {
!bl.contains(syscall)
} else {
false
}
}
Self::None => false,
}
}
}

/// Set of syscalls that return an error.
///
/// Basically, it's a wrapper over a hash set of [`InvocableSysCall`],
/// that controls types of inserted syscalls.
#[derive(Debug, Clone, Default)]
pub struct ErrorProneSyscalls(HashSet<InvocableSyscall>);

impl ErrorProneSyscalls {
/// Create an empty set of returning error syscalls.
pub fn new() -> Self {
Self(HashSet::new())
}

/// Insert an error-prone syscall into the set.
pub fn insert(&mut self, syscall: InvocableSyscall) {
if syscall.returns_error() {
self.0.insert(syscall);
} else {
panic!(
"{syscall_str} is neither fallible, nor returns error value.",
syscall_str = syscall.to_str()
);
}
}

/// Check if the `syscall` is in the set.
pub fn contains(&self, syscall: InvocableSyscall) -> bool {
self.0.contains(&syscall)
}
}
Loading

0 comments on commit 5b021ea

Please sign in to comment.