mirror of
https://github.com/fluencelabs/aquavm
synced 2025-04-24 23:02:16 +00:00
WIP new structs to hand limits over in runtime
This commit is contained in:
parent
1da02d197d
commit
81019e6633
@ -91,17 +91,9 @@ pub enum PreparationError {
|
||||
#[error(transparent)]
|
||||
DataSignatureCheckError(#[from] DataVerifierError),
|
||||
|
||||
/// AIR script size is bigger than the allowed limit.
|
||||
#[error("air size: {0} bytes is bigger than the limit allowed: {1} bytes")]
|
||||
AIRSizeLimitReached(usize, u64),
|
||||
|
||||
/// Current_data particle size is bigger than the allowed limit.
|
||||
#[error("Current_data particle size: {0} bytes is bigger than the limit allowed: {1} bytes")]
|
||||
ParticleSizeLimitReached(usize, u64),
|
||||
|
||||
/// CallResult size is bigger than the allowed limit.
|
||||
#[error("Call result size is bigger than the limit allowed: {0} bytes")]
|
||||
CallResultSizeLimitReached(u64),
|
||||
/// RAM limits are excedeed.
|
||||
#[error(transparent)]
|
||||
SizeLimitsExceded(#[from] SizeLimitsExceded),
|
||||
}
|
||||
|
||||
impl ToErrorCode for PreparationError {
|
||||
@ -136,14 +128,29 @@ impl PreparationError {
|
||||
}
|
||||
|
||||
pub fn air_size_limit(actual_size: usize, limit: u64) -> Self {
|
||||
Self::AIRSizeLimitReached(actual_size, limit)
|
||||
Self::SizeLimitsExceded(SizeLimitsExceded::AIR(actual_size, limit))
|
||||
}
|
||||
|
||||
pub fn particle_size_limit(actual_size: usize, limit: u64) -> Self {
|
||||
Self::ParticleSizeLimitReached(actual_size, limit)
|
||||
Self::SizeLimitsExceded(SizeLimitsExceded::Particle(actual_size, limit))
|
||||
}
|
||||
|
||||
pub fn call_result_size_limit(limit: u64) -> Self {
|
||||
Self::CallResultSizeLimitReached(limit)
|
||||
Self::SizeLimitsExceded(SizeLimitsExceded::CallResult(limit))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, ThisError)]
|
||||
pub enum SizeLimitsExceded {
|
||||
/// AIR script size is bigger than the allowed limit.
|
||||
#[error("air size: {0} bytes is bigger than the limit allowed: {1} bytes")]
|
||||
AIR(usize, u64),
|
||||
|
||||
/// Current_data particle size is bigger than the allowed limit.
|
||||
#[error("Current_data particle size: {0} bytes is bigger than the limit allowed: {1} bytes")]
|
||||
Particle(usize, u64),
|
||||
|
||||
/// CallResult size is bigger than the allowed limit.
|
||||
#[error("Call result size is bigger than the limit allowed: {0} bytes")]
|
||||
CallResult(u64),
|
||||
}
|
||||
|
@ -144,6 +144,8 @@ fn make_exec_ctx(
|
||||
signature_store: SignatureStore,
|
||||
run_parameters: &RunParameters,
|
||||
) -> PreparationResult<ExecutionCtx<'static>> {
|
||||
use crate::preparation_step::sizes_limits_check::limit_behavior;
|
||||
|
||||
let call_results = measure!(
|
||||
CallResultsRepr
|
||||
.deserialize(call_results)
|
||||
@ -157,9 +159,8 @@ fn make_exec_ctx(
|
||||
.values()
|
||||
.any(|call_result| call_result.result.len() > run_parameters.call_result_size_limit as usize)
|
||||
{
|
||||
return Err(PreparationError::call_result_size_limit(
|
||||
run_parameters.call_result_size_limit,
|
||||
));
|
||||
let error = PreparationError::call_result_size_limit(run_parameters.call_result_size_limit);
|
||||
limit_behavior(run_parameters, error)?;
|
||||
}
|
||||
|
||||
let ctx = ExecutionCtx::new(
|
||||
|
@ -19,23 +19,27 @@ use crate::PreparationError;
|
||||
|
||||
use air_interpreter_interface::RunParameters;
|
||||
|
||||
pub(crate) fn limit_behavior(run_parameters: &RunParameters, error: PreparationError) -> PreparationResult<()> {
|
||||
if run_parameters.hard_limit_enabled {
|
||||
Err(error)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn check_against_size_limits(
|
||||
run_parameters: &RunParameters,
|
||||
air: &str,
|
||||
raw_current_data: &[u8],
|
||||
) -> PreparationResult<()> {
|
||||
if air.len() as u64 > run_parameters.air_size_limit {
|
||||
return Err(PreparationError::air_size_limit(
|
||||
air.len(),
|
||||
run_parameters.air_size_limit,
|
||||
));
|
||||
let error = PreparationError::air_size_limit(air.len(), run_parameters.air_size_limit);
|
||||
limit_behavior(run_parameters, error)?;
|
||||
}
|
||||
|
||||
if raw_current_data.len() > run_parameters.particle_size_limit as usize {
|
||||
return Err(PreparationError::particle_size_limit(
|
||||
raw_current_data.len(),
|
||||
run_parameters.particle_size_limit,
|
||||
));
|
||||
if raw_current_data.len() as u64 > run_parameters.particle_size_limit {
|
||||
let error = PreparationError::particle_size_limit(raw_current_data.len(), run_parameters.particle_size_limit);
|
||||
limit_behavior(run_parameters, error)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -102,6 +102,7 @@ fn invalid_callresults() {
|
||||
let air_size_limit = MAX_AIR_SIZE;
|
||||
let particle_size_limit = MAX_PARTICLE_SIZE;
|
||||
let call_result_size_limit = MAX_CALL_RESULT_SIZE;
|
||||
let hard_limit_enable = false;
|
||||
|
||||
let run_parameters = RunParameters::new(
|
||||
client_peer_id.clone(),
|
||||
@ -114,6 +115,7 @@ fn invalid_callresults() {
|
||||
air_size_limit,
|
||||
particle_size_limit,
|
||||
call_result_size_limit,
|
||||
hard_limit_enable,
|
||||
);
|
||||
|
||||
let result = air::execute_air(air, prev_data, data, run_parameters, wrong_call_results.clone().into());
|
||||
@ -128,50 +130,111 @@ fn invalid_callresults() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn air_size_limit() {
|
||||
fn air_size_hard_limit() {
|
||||
let script = "a".repeat((MAX_AIR_SIZE + 1) as usize);
|
||||
let mut vm = create_avm(unit_call_service(), "some_peer_id");
|
||||
let result = vm.call(script, "", "", <_>::default()).unwrap();
|
||||
|
||||
let expected_error = PreparationError::AIRSizeLimitReached((MAX_AIR_SIZE + 1) as usize, MAX_AIR_SIZE);
|
||||
let peer_id = "some_peer_id".to_owned();
|
||||
let air_size_limit = MAX_AIR_SIZE;
|
||||
let particle_size_limit = MAX_PARTICLE_SIZE;
|
||||
let call_result_size_limit = MAX_CALL_RESULT_SIZE;
|
||||
let hard_limit_enable = true;
|
||||
|
||||
let run_parameters = RunParameters::new(
|
||||
peer_id.clone(),
|
||||
peer_id,
|
||||
0,
|
||||
0,
|
||||
<_>::default(),
|
||||
<_>::default(),
|
||||
"".to_owned(),
|
||||
air_size_limit,
|
||||
particle_size_limit,
|
||||
call_result_size_limit,
|
||||
hard_limit_enable,
|
||||
);
|
||||
|
||||
let result = air::execute_air(script, vec![], vec![], run_parameters, <_>::default());
|
||||
let result = RawAVMOutcome::from_interpreter_outcome(result).unwrap();
|
||||
|
||||
let expected_error = PreparationError::air_size_limit((MAX_AIR_SIZE + 1) as usize, MAX_AIR_SIZE);
|
||||
|
||||
assert!(check_error(&result, expected_error));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn particle_size_limit() {
|
||||
let script = "(null)";
|
||||
let mut vm = create_avm(unit_call_service(), "some_peer_id");
|
||||
fn particle_size_hard_limit() {
|
||||
let script = "(null)".to_owned();
|
||||
let cur_data = vec![0; (MAX_PARTICLE_SIZE + 1) as usize];
|
||||
let result = vm.call(script, "", cur_data, <_>::default()).unwrap();
|
||||
|
||||
let expected_error =
|
||||
PreparationError::ParticleSizeLimitReached((MAX_PARTICLE_SIZE + 1) as usize, MAX_PARTICLE_SIZE);
|
||||
let peer_id = "some_peer_id".to_owned();
|
||||
let air_size_limit = MAX_AIR_SIZE;
|
||||
let particle_size_limit = MAX_PARTICLE_SIZE;
|
||||
let call_result_size_limit = MAX_CALL_RESULT_SIZE;
|
||||
let hard_limit_enable = true;
|
||||
|
||||
let run_parameters = RunParameters::new(
|
||||
peer_id.clone(),
|
||||
peer_id,
|
||||
0,
|
||||
0,
|
||||
<_>::default(),
|
||||
<_>::default(),
|
||||
"".to_owned(),
|
||||
air_size_limit,
|
||||
particle_size_limit,
|
||||
call_result_size_limit,
|
||||
hard_limit_enable,
|
||||
);
|
||||
|
||||
let result = air::execute_air(script, vec![], cur_data, run_parameters, <_>::default());
|
||||
let result = RawAVMOutcome::from_interpreter_outcome(result).unwrap();
|
||||
|
||||
let expected_error = PreparationError::particle_size_limit((MAX_PARTICLE_SIZE + 1) as usize, MAX_PARTICLE_SIZE);
|
||||
|
||||
assert!(check_error(&result, expected_error));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn call_result_size_limit() {
|
||||
fn call_result_size_hard_limit() {
|
||||
use maplit::hashmap;
|
||||
|
||||
use air::ToErrorCode;
|
||||
use air_interpreter_interface::MAX_CALL_RESULT_SIZE;
|
||||
use air_interpreter_sede::ToSerialized;
|
||||
|
||||
let peer_id = "some_peer_id";
|
||||
let mut vm = create_avm(unit_call_service(), "some_peer_id");
|
||||
|
||||
let script = "(null)";
|
||||
let script = "(null)".to_owned();
|
||||
let result_1 = "a".repeat((MAX_CALL_RESULT_SIZE / 2 + 1) as usize);
|
||||
let result_2 = "b".repeat((MAX_CALL_RESULT_SIZE + 1) as usize);
|
||||
let call_results: CallResults =
|
||||
hashmap! {0 => CallServiceResult::ok(result_1.into()), 1 => CallServiceResult::ok(result_2.into())};
|
||||
|
||||
let result = vm
|
||||
.call_single(script, "", "", peer_id, 0, 64, None, call_results, "particle_id")
|
||||
.unwrap();
|
||||
let raw_call_results = into_raw_result(call_results);
|
||||
let raw_call_results = CallResultsRepr.serialize(&raw_call_results).unwrap();
|
||||
|
||||
let expected_error = PreparationError::CallResultSizeLimitReached(MAX_CALL_RESULT_SIZE);
|
||||
let peer_id = "some_peer_id".to_owned();
|
||||
let air_size_limit = MAX_AIR_SIZE;
|
||||
let particle_size_limit = MAX_PARTICLE_SIZE;
|
||||
let call_result_size_limit = MAX_CALL_RESULT_SIZE;
|
||||
let hard_limit_enable = true;
|
||||
|
||||
let run_parameters = RunParameters::new(
|
||||
peer_id.clone(),
|
||||
peer_id,
|
||||
0,
|
||||
0,
|
||||
<_>::default(),
|
||||
<_>::default(),
|
||||
"".to_owned(),
|
||||
air_size_limit,
|
||||
particle_size_limit,
|
||||
call_result_size_limit,
|
||||
hard_limit_enable,
|
||||
);
|
||||
|
||||
let result = air::execute_air(script, vec![], vec![], run_parameters, raw_call_results);
|
||||
let result = RawAVMOutcome::from_interpreter_outcome(result).unwrap();
|
||||
|
||||
let expected_error = PreparationError::call_result_size_limit(MAX_CALL_RESULT_SIZE);
|
||||
|
||||
assert_eq!(result.ret_code, expected_error.to_error_code());
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ impl<E> AVM<E> {
|
||||
|
||||
data_store.initialize()?;
|
||||
|
||||
let runner = AVMRunner::new(air_wasm_path, max_heap_size, None, None, None, logging_mask)
|
||||
let runner = AVMRunner::new(air_wasm_path, max_heap_size, <_>::default(), logging_mask)
|
||||
.map_err(AVMError::RunnerError)?;
|
||||
let runner = SendSafeRunner(runner);
|
||||
let avm = Self { runner, data_store };
|
||||
|
@ -28,11 +28,14 @@ mod avm;
|
||||
mod config;
|
||||
mod errors;
|
||||
mod runner;
|
||||
mod runtime_limits;
|
||||
|
||||
pub use avm::AVM;
|
||||
pub use config::AVMConfig;
|
||||
pub use errors::AVMError;
|
||||
pub use runner::AVMMemoryStats;
|
||||
pub use runner::AVMRuntimeLimits;
|
||||
pub use runner::RuntimeLimits;
|
||||
|
||||
pub use avm_interface::*;
|
||||
|
||||
|
@ -32,18 +32,36 @@ use marine::ModuleDescriptor;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct AVMRuntimeLimits {
|
||||
pub air_size_limit: u64, // WIP remove pub?
|
||||
/// The particle data size limit.
|
||||
pub particle_size_limit: u64,
|
||||
/// This is the limit for the size of service call result.
|
||||
pub call_result_size_limit: u64,
|
||||
/// This knob controls hard RAM limits behavior for AVMRunner.
|
||||
pub hard_limit_enabled: bool,
|
||||
}
|
||||
|
||||
pub struct RuntimeLimits {
|
||||
// The AIR script size limit.
|
||||
pub air_size_limit: Option<u64>,
|
||||
/// The particle data size limit.
|
||||
pub particle_size_limit: Option<u64>,
|
||||
/// This is the limit for the size of service call result.
|
||||
pub call_result_size_limit: Option<u64>,
|
||||
/// This knob controls hard RAM limits behavior for AVMRunner.
|
||||
pub hard_limit_enabled: bool,
|
||||
}
|
||||
|
||||
pub struct AVMRunner {
|
||||
marine: Marine,
|
||||
/// file name of the AIR interpreter .wasm
|
||||
wasm_filename: String,
|
||||
/// The memory limit provided by constructor
|
||||
total_memory_limit: Option<u64>,
|
||||
/// The AIR script size limit.
|
||||
pub air_size_limit: u64,
|
||||
/// The particle data size limit.
|
||||
pub particle_size_limit: u64,
|
||||
// This is the limit for the size of service call result.
|
||||
pub call_result_size_limit: u64,
|
||||
/// This struct contains runtime RAM allowance.
|
||||
avm_runtime_limits: AVMRuntimeLimits,
|
||||
}
|
||||
|
||||
/// Return statistic of AVM server Wasm module heap footprint.
|
||||
@ -63,32 +81,21 @@ impl AVMRunner {
|
||||
pub fn new(
|
||||
air_wasm_path: PathBuf,
|
||||
total_memory_limit: Option<u64>,
|
||||
air_size_limit: Option<u64>,
|
||||
particle_size_limit: Option<u64>,
|
||||
call_result_size_limit: Option<u64>,
|
||||
runtime_limits: RuntimeLimits,
|
||||
logging_mask: i32,
|
||||
) -> RunnerResult<Self> {
|
||||
use air_interpreter_interface::MAX_AIR_SIZE;
|
||||
use air_interpreter_interface::MAX_CALL_RESULT_SIZE;
|
||||
use air_interpreter_interface::MAX_PARTICLE_SIZE;
|
||||
|
||||
let (wasm_dir, wasm_filename) = split_dirname(air_wasm_path)?;
|
||||
|
||||
let marine_config =
|
||||
make_marine_config(wasm_dir, &wasm_filename, total_memory_limit, logging_mask);
|
||||
let marine = Marine::with_raw_config(marine_config)?;
|
||||
|
||||
let air_size_limit = air_size_limit.unwrap_or(MAX_AIR_SIZE);
|
||||
let particle_size_limit = particle_size_limit.unwrap_or(MAX_PARTICLE_SIZE);
|
||||
let call_result_size_limit = call_result_size_limit.unwrap_or(MAX_CALL_RESULT_SIZE);
|
||||
let avm_runtime_limits = runtime_limits.into();
|
||||
|
||||
let avm = Self {
|
||||
marine,
|
||||
wasm_filename,
|
||||
total_memory_limit,
|
||||
air_size_limit,
|
||||
particle_size_limit,
|
||||
call_result_size_limit,
|
||||
avm_runtime_limits,
|
||||
};
|
||||
|
||||
Ok(avm)
|
||||
@ -122,9 +129,7 @@ impl AVMRunner {
|
||||
init_peer_id.into(),
|
||||
timestamp,
|
||||
ttl,
|
||||
self.air_size_limit,
|
||||
self.particle_size_limit,
|
||||
self.call_result_size_limit,
|
||||
self.avm_runtime_limits,
|
||||
call_results,
|
||||
key_format.into(),
|
||||
secret_key_bytes,
|
||||
@ -173,9 +178,7 @@ impl AVMRunner {
|
||||
init_peer_id.into(),
|
||||
timestamp,
|
||||
ttl,
|
||||
self.air_size_limit,
|
||||
self.particle_size_limit,
|
||||
self.call_result_size_limit,
|
||||
self.avm_runtime_limits,
|
||||
call_results,
|
||||
key_format,
|
||||
secret_key_bytes,
|
||||
@ -242,14 +245,19 @@ fn prepare_args(
|
||||
init_peer_id: String,
|
||||
timestamp: u64,
|
||||
ttl: u32,
|
||||
air_size_limit: u64,
|
||||
particle_size_limit: u64,
|
||||
call_result_size_limit: u64,
|
||||
avm_runtime_limits: AVMRuntimeLimits,
|
||||
call_results: CallResults,
|
||||
key_format: u8,
|
||||
secret_key_bytes: Vec<u8>,
|
||||
particle_id: String,
|
||||
) -> Vec<IValue> {
|
||||
let AVMRuntimeLimits {
|
||||
air_size_limit,
|
||||
particle_size_limit,
|
||||
call_result_size_limit,
|
||||
hard_limit_enabled,
|
||||
} = avm_runtime_limits;
|
||||
|
||||
let run_parameters = air_interpreter_interface::RunParameters::new(
|
||||
init_peer_id,
|
||||
current_peer_id,
|
||||
@ -261,6 +269,7 @@ fn prepare_args(
|
||||
air_size_limit,
|
||||
particle_size_limit,
|
||||
call_result_size_limit,
|
||||
hard_limit_enabled,
|
||||
)
|
||||
.into_ivalue();
|
||||
|
||||
@ -350,3 +359,61 @@ fn try_as_one_value_vec(mut ivalues: Vec<IValue>) -> RunnerResult<IValue> {
|
||||
|
||||
Ok(ivalues.remove(0))
|
||||
}
|
||||
|
||||
impl AVMRuntimeLimits {
|
||||
pub fn new(
|
||||
air_size_limit: u64,
|
||||
particle_size_limit: u64,
|
||||
call_result_size_limit: u64,
|
||||
hard_limit_enabled: bool,
|
||||
) -> Self {
|
||||
Self {
|
||||
air_size_limit,
|
||||
particle_size_limit,
|
||||
call_result_size_limit,
|
||||
hard_limit_enabled,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RuntimeLimits {
|
||||
pub fn new(
|
||||
air_size_limit: Option<u64>,
|
||||
particle_size_limit: Option<u64>,
|
||||
call_result_size_limit: Option<u64>,
|
||||
hard_limit_enabled: bool,
|
||||
) -> Self {
|
||||
Self {
|
||||
air_size_limit,
|
||||
particle_size_limit,
|
||||
call_result_size_limit,
|
||||
hard_limit_enabled,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for RuntimeLimits {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
air_size_limit: None,
|
||||
particle_size_limit: None,
|
||||
call_result_size_limit: None,
|
||||
hard_limit_enabled: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RuntimeLimits> for AVMRuntimeLimits {
|
||||
fn from(value: RuntimeLimits) -> Self {
|
||||
use air_interpreter_interface::MAX_AIR_SIZE;
|
||||
use air_interpreter_interface::MAX_CALL_RESULT_SIZE;
|
||||
use air_interpreter_interface::MAX_PARTICLE_SIZE;
|
||||
|
||||
AVMRuntimeLimits::new(
|
||||
value.air_size_limit.unwrap_or(MAX_AIR_SIZE),
|
||||
value.particle_size_limit.unwrap_or(MAX_PARTICLE_SIZE),
|
||||
value.call_result_size_limit.unwrap_or(MAX_CALL_RESULT_SIZE),
|
||||
value.hard_limit_enabled,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
75
avm/server/src/runtime_limits.rs
Normal file
75
avm/server/src/runtime_limits.rs
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2024 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
pub struct AVMRuntimeLimits {
|
||||
/// AIR script size limit.
|
||||
pub air_size_limit: u64,
|
||||
/// Particle data size limit.
|
||||
pub particle_size_limit: u64,
|
||||
/// Service call result size limit.
|
||||
pub call_result_size_limit: u64,
|
||||
/// Knob to enable/disable RAM consumption hard limits in AquaVM.
|
||||
pub hard_limit_enabled: bool,
|
||||
}
|
||||
|
||||
pub struct RuntimeLimits {
|
||||
pub air_size_limit: Option<u64>,
|
||||
pub particle_size_limit: Option<u64>,
|
||||
pub call_result_size_limit: Option<u64>,
|
||||
pub hard_limit_enabled: bool,
|
||||
}
|
||||
|
||||
impl AVMRuntimeLimits {
|
||||
pub fn new(
|
||||
air_size_limit: u64,
|
||||
particle_size_limit: u64,
|
||||
call_result_size_limit: u64,
|
||||
hard_limit_enabled: bool,
|
||||
) -> Self {
|
||||
Self {
|
||||
air_size_limit,
|
||||
particle_size_limit,
|
||||
call_result_size_limit,
|
||||
hard_limit_enabled,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for RuntimeLimits {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
air_size_limit: None,
|
||||
particle_size_limit: None,
|
||||
call_result_size_limit: None,
|
||||
hard_limit_enabled: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RuntimeLimits> for AVMRuntimeLimits {
|
||||
fn from(value: RuntimeLimits) -> Self {
|
||||
use air_interpreter_interface::MAX_AIR_SIZE;
|
||||
use air_interpreter_interface::MAX_CALL_RESULT_SIZE;
|
||||
use air_interpreter_interface::MAX_PARTICLE_SIZE;
|
||||
|
||||
AVMRuntimeLimits::new(
|
||||
value.air_size_limit.unwrap_or(MAX_AIR_SIZE),
|
||||
value.particle_size_limit.unwrap_or(MAX_PARTICLE_SIZE),
|
||||
value.call_result_size_limit.unwrap_or(MAX_CALL_RESULT_SIZE),
|
||||
value.hard_limit_enabled,
|
||||
)
|
||||
}
|
||||
}
|
@ -62,6 +62,9 @@ pub struct RunParameters {
|
||||
|
||||
/// This is the limit for the size of service call result.
|
||||
pub call_result_size_limit: u64,
|
||||
|
||||
/// This knob controls hard RAM limits behavior for AVMRunner.
|
||||
pub hard_limit_enabled: bool,
|
||||
}
|
||||
|
||||
impl RunParameters {
|
||||
@ -77,6 +80,7 @@ impl RunParameters {
|
||||
air_size_limit: u64,
|
||||
particle_size_limit: u64,
|
||||
call_result_size_limit: u64,
|
||||
hard_limit_enabled: bool,
|
||||
) -> Self {
|
||||
Self {
|
||||
init_peer_id,
|
||||
@ -89,6 +93,7 @@ impl RunParameters {
|
||||
air_size_limit,
|
||||
particle_size_limit,
|
||||
call_result_size_limit,
|
||||
hard_limit_enabled,
|
||||
}
|
||||
}
|
||||
|
||||
@ -105,6 +110,7 @@ impl RunParameters {
|
||||
IValue::U64(self.air_size_limit),
|
||||
IValue::U64(self.particle_size_limit),
|
||||
IValue::U64(self.call_result_size_limit),
|
||||
IValue::Boolean(self.hard_limit_enabled),
|
||||
];
|
||||
// unwrap is safe here because run_parameters is non-empty array
|
||||
let run_parameters = NEVec::new(run_parameters).unwrap();
|
||||
|
@ -21,6 +21,7 @@ use air_interpreter_interface::RunParameters;
|
||||
use air_interpreter_sede::ToSerialized;
|
||||
use avm_server::avm_runner::*;
|
||||
use avm_server::into_raw_result;
|
||||
use avm_server::AVMRuntimeLimits;
|
||||
use fluence_keypair::KeyPair;
|
||||
|
||||
pub struct NativeAirRunner {
|
||||
@ -59,8 +60,12 @@ impl AirRunner for NativeAirRunner {
|
||||
let key_format = keypair.key_format().into();
|
||||
let secret_key_bytes = keypair.secret().unwrap();
|
||||
|
||||
let (air_size_limit, particle_size_limit, call_result_size_limit) =
|
||||
self.test_init_parameters.to_attributes_w_default();
|
||||
let AVMRuntimeLimits {
|
||||
air_size_limit,
|
||||
particle_size_limit,
|
||||
call_result_size_limit,
|
||||
hard_limit_enabled,
|
||||
} = self.test_init_parameters.into();
|
||||
|
||||
let outcome = air::execute_air(
|
||||
air.into(),
|
||||
@ -77,6 +82,7 @@ impl AirRunner for NativeAirRunner {
|
||||
air_size_limit,
|
||||
particle_size_limit,
|
||||
call_result_size_limit,
|
||||
hard_limit_enabled,
|
||||
},
|
||||
raw_call_results,
|
||||
);
|
||||
|
@ -27,6 +27,8 @@ pub use crate::wasm_test_runner::WasmAirRunner;
|
||||
use super::CallServiceClosure;
|
||||
|
||||
use avm_server::avm_runner::*;
|
||||
use avm_server::AVMRuntimeLimits;
|
||||
use avm_server::RuntimeLimits;
|
||||
use fluence_keypair::KeyPair;
|
||||
|
||||
use std::collections::HashMap;
|
||||
@ -69,11 +71,12 @@ pub struct TestRunParameters {
|
||||
}
|
||||
|
||||
/// This struct is used to set limits for the test runner creating AVMRunner.
|
||||
#[derive(Debug, Default, Clone)]
|
||||
#[derive(Debug, Default, Clone, Copy)]
|
||||
pub struct TestInitParameters {
|
||||
pub air_size_limit: Option<u64>,
|
||||
pub particle_size_limit: Option<u64>,
|
||||
pub call_result_size_limit: Option<u64>,
|
||||
pub hard_limit_enabled: bool,
|
||||
}
|
||||
|
||||
impl<R: AirRunner> TestRunner<R> {
|
||||
@ -247,11 +250,17 @@ impl TestRunParameters {
|
||||
}
|
||||
|
||||
impl TestInitParameters {
|
||||
pub fn new(air_size_limit: u64, particle_size_limit: u64, call_result_size_limit: u64) -> Self {
|
||||
pub fn new(
|
||||
air_size_limit: u64,
|
||||
particle_size_limit: u64,
|
||||
call_result_size_limit: u64,
|
||||
hard_limit_enabled: bool,
|
||||
) -> Self {
|
||||
Self {
|
||||
air_size_limit: Some(air_size_limit),
|
||||
particle_size_limit: Some(particle_size_limit),
|
||||
call_result_size_limit: Some(call_result_size_limit),
|
||||
hard_limit_enabled,
|
||||
}
|
||||
}
|
||||
|
||||
@ -260,18 +269,37 @@ impl TestInitParameters {
|
||||
air_size_limit: Some(u64::MAX),
|
||||
particle_size_limit: Some(u64::MAX),
|
||||
call_result_size_limit: Some(u64::MAX),
|
||||
hard_limit_enabled: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_attributes_w_default(&self) -> (u64, u64, u64) {
|
||||
impl From<TestInitParameters> for RuntimeLimits {
|
||||
fn from(value: TestInitParameters) -> Self {
|
||||
RuntimeLimits::new(
|
||||
value.air_size_limit,
|
||||
value.particle_size_limit,
|
||||
value.call_result_size_limit,
|
||||
value.hard_limit_enabled,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TestInitParameters> for AVMRuntimeLimits {
|
||||
fn from(value: TestInitParameters) -> Self {
|
||||
use air_interpreter_interface::MAX_AIR_SIZE;
|
||||
use air_interpreter_interface::MAX_CALL_RESULT_SIZE;
|
||||
use air_interpreter_interface::MAX_PARTICLE_SIZE;
|
||||
let air_size_limit = value.air_size_limit.unwrap_or(MAX_AIR_SIZE);
|
||||
let particle_size_limit: u64 = value.particle_size_limit.unwrap_or(MAX_PARTICLE_SIZE);
|
||||
let call_result_size_limit = value.call_result_size_limit.unwrap_or(MAX_CALL_RESULT_SIZE);
|
||||
|
||||
let air_size_limit = self.air_size_limit.unwrap_or(MAX_AIR_SIZE);
|
||||
let particle_size_limit: u64 = self.particle_size_limit.unwrap_or(MAX_PARTICLE_SIZE);
|
||||
let call_result_size_limit = self.call_result_size_limit.unwrap_or(MAX_CALL_RESULT_SIZE);
|
||||
(air_size_limit, particle_size_limit, call_result_size_limit)
|
||||
AVMRuntimeLimits::new(
|
||||
air_size_limit,
|
||||
particle_size_limit,
|
||||
call_result_size_limit,
|
||||
value.hard_limit_enabled,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,15 +35,11 @@ pub struct WasmAirRunner {
|
||||
|
||||
fn make_pooled_avm_runner(test_init_parameters: TestInitParameters) -> AVMRunner {
|
||||
let logging_mask = i32::MAX;
|
||||
let (air_size_limit, particle_size_limit, call_result_size_limit) =
|
||||
test_init_parameters.to_attributes_w_default();
|
||||
|
||||
AVMRunner::new(
|
||||
PathBuf::from(AIR_WASM_PATH),
|
||||
Some(AVM_MAX_HEAP_SIZE),
|
||||
Some(air_size_limit),
|
||||
Some(particle_size_limit),
|
||||
Some(call_result_size_limit),
|
||||
test_init_parameters.into(),
|
||||
logging_mask,
|
||||
)
|
||||
.expect("vm should be created")
|
||||
@ -114,15 +110,11 @@ pub struct ReleaseWasmAirRunner {
|
||||
impl AirRunner for ReleaseWasmAirRunner {
|
||||
fn new(current_peer_id: impl Into<String>, test_init_parameters: TestInitParameters) -> Self {
|
||||
let logging_mask = i32::MAX;
|
||||
let (air_size_limit, particle_size_limit, call_result_size_limit) =
|
||||
test_init_parameters.to_attributes_w_default();
|
||||
|
||||
let runner = AVMRunner::new(
|
||||
PathBuf::from(RELEASE_AIR_WASM_PATH),
|
||||
Some(AVM_MAX_HEAP_SIZE),
|
||||
Some(air_size_limit),
|
||||
Some(particle_size_limit),
|
||||
Some(call_result_size_limit),
|
||||
test_init_parameters.into(),
|
||||
logging_mask,
|
||||
)
|
||||
.expect("vm should be created");
|
||||
|
@ -17,6 +17,7 @@ avm-interface = { version = "0.31.2", path = "../../../avm/interface" }
|
||||
air-interpreter-interface = { version = "0.17.2", path = "../../../crates/air-lib/interpreter-interface", default-features = false }
|
||||
air-interpreter-data = { version = "0.17.0", path = "../../../crates/air-lib/interpreter-data" }
|
||||
air-interpreter-sede = { version = "0.1.0", path = "../../../crates/air-lib/interpreter-sede", default-features = false }
|
||||
avm-server = { version = "0.35.0", path = "../../../avm/server" }
|
||||
air-test-utils = { version = "0.15.1",path = "../../../crates/air-lib/test-utils", optional = true }
|
||||
|
||||
clap = { version = "4.4.7", features = ["derive", "env"] }
|
||||
|
@ -55,6 +55,9 @@ pub(crate) struct PlainDataArgs {
|
||||
|
||||
#[clap(long = "call-result-size-limit")]
|
||||
call_result_size_limit: Option<u64>,
|
||||
|
||||
#[clap(long = "hard-limit-enabled", default_value = "false")]
|
||||
hard_limit_enabled: bool,
|
||||
}
|
||||
|
||||
pub(crate) fn load(args: &PlainDataArgs) -> eyre::Result<ExecutionData<'_>> {
|
||||
@ -80,11 +83,12 @@ pub(crate) fn load(args: &PlainDataArgs) -> eyre::Result<ExecutionData<'_>> {
|
||||
current_peer_id.into(),
|
||||
);
|
||||
|
||||
let test_init_parameters = TestInitParameters {
|
||||
air_size_limit: args.air_size_limit,
|
||||
particle_size_limit: args.particle_size_limit,
|
||||
call_result_size_limit: args.call_result_size_limit,
|
||||
};
|
||||
let test_init_parameters = TestInitParameters::new(
|
||||
args.air_size_limit,
|
||||
args.particle_size_limit,
|
||||
args.call_result_size_limit,
|
||||
args.hard_limit_enabled,
|
||||
);
|
||||
|
||||
Ok(ExecutionData {
|
||||
air_script,
|
||||
|
@ -21,14 +21,13 @@ use super::runner::TestInitParameters;
|
||||
use air_interpreter_interface::CallResultsRepr;
|
||||
use air_interpreter_interface::RunParameters;
|
||||
use avm_interface::raw_outcome::RawAVMOutcome;
|
||||
use avm_server::AVMRuntimeLimits;
|
||||
use fluence_keypair::KeyPair;
|
||||
|
||||
use std::error::Error as StdError;
|
||||
|
||||
pub(crate) struct NativeAvmRunner {
|
||||
pub air_size_limit: u64,
|
||||
pub particle_size_limit: u64,
|
||||
pub call_result_size_limit: u64,
|
||||
pub avm_runtime_limits: AVMRuntimeLimits,
|
||||
}
|
||||
|
||||
impl AirRunner for NativeAvmRunner {
|
||||
@ -57,6 +56,12 @@ impl AirRunner for NativeAvmRunner {
|
||||
|
||||
let key_format = keypair.key_format().into();
|
||||
let secret_key_bytes = keypair.secret().expect("Failed to get secret key");
|
||||
let AVMRuntimeLimits {
|
||||
air_size_limit,
|
||||
particle_size_limit,
|
||||
call_result_size_limit,
|
||||
hard_limit_enabled,
|
||||
} = self.avm_runtime_limits;
|
||||
|
||||
let outcome = air::execute_air(
|
||||
air,
|
||||
@ -67,12 +72,13 @@ impl AirRunner for NativeAvmRunner {
|
||||
current_peer_id,
|
||||
timestamp,
|
||||
ttl,
|
||||
air_size_limit: self.air_size_limit,
|
||||
particle_size_limit: self.particle_size_limit,
|
||||
call_result_size_limit: self.call_result_size_limit,
|
||||
key_format,
|
||||
secret_key_bytes,
|
||||
particle_id,
|
||||
air_size_limit,
|
||||
particle_size_limit,
|
||||
call_result_size_limit,
|
||||
hard_limit_enabled,
|
||||
},
|
||||
raw_call_results,
|
||||
);
|
||||
@ -91,12 +97,7 @@ impl DataToHumanReadable for NativeAvmRunner {
|
||||
pub(crate) fn create_native_avm_runner(
|
||||
test_init_parameters: TestInitParameters,
|
||||
) -> eyre::Result<Box<NativeAvmRunner>> {
|
||||
let (air_size_limit, particle_size_limit, call_result_size_limit) =
|
||||
test_init_parameters.to_attributes_w_default();
|
||||
let avm_runtime_limits: AVMRuntimeLimits = test_init_parameters.into();
|
||||
|
||||
Ok(Box::new(NativeAvmRunner {
|
||||
air_size_limit,
|
||||
particle_size_limit,
|
||||
call_result_size_limit,
|
||||
}))
|
||||
Ok(Box::new(NativeAvmRunner { avm_runtime_limits }))
|
||||
}
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
use avm_interface::raw_outcome::RawAVMOutcome;
|
||||
use avm_interface::CallResults;
|
||||
use avm_server::AVMRuntimeLimits;
|
||||
use avm_server::RuntimeLimits;
|
||||
use fluence_keypair::KeyPair;
|
||||
|
||||
use std::error::Error as StdError;
|
||||
@ -49,25 +51,54 @@ pub struct TestInitParameters {
|
||||
pub air_size_limit: Option<u64>,
|
||||
pub particle_size_limit: Option<u64>,
|
||||
pub call_result_size_limit: Option<u64>,
|
||||
pub hard_limit_enabled: bool,
|
||||
}
|
||||
|
||||
impl TestInitParameters {
|
||||
pub fn to_attributes_w_default(&self) -> (u64, u64, u64) {
|
||||
use air_interpreter_interface::MAX_AIR_SIZE;
|
||||
use air_interpreter_interface::MAX_CALL_RESULT_SIZE;
|
||||
use air_interpreter_interface::MAX_PARTICLE_SIZE;
|
||||
|
||||
let air_size_limit = self.air_size_limit.unwrap_or(MAX_AIR_SIZE);
|
||||
let particle_size_limit: u64 = self.particle_size_limit.unwrap_or(MAX_PARTICLE_SIZE);
|
||||
let call_result_size_limit = self.call_result_size_limit.unwrap_or(MAX_CALL_RESULT_SIZE);
|
||||
(air_size_limit, particle_size_limit, call_result_size_limit)
|
||||
pub fn new(
|
||||
air_size_limit: Option<u64>,
|
||||
particle_size_limit: Option<u64>,
|
||||
call_result_size_limit: Option<u64>,
|
||||
hard_limit_enabled: bool,
|
||||
) -> Self {
|
||||
Self {
|
||||
air_size_limit,
|
||||
particle_size_limit,
|
||||
call_result_size_limit,
|
||||
hard_limit_enabled,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn no_limits() -> Self {
|
||||
Self {
|
||||
air_size_limit: Some(u64::MAX),
|
||||
particle_size_limit: Some(u64::MAX),
|
||||
call_result_size_limit: Some(u64::MAX),
|
||||
hard_limit_enabled: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TestInitParameters> for RuntimeLimits {
|
||||
fn from(value: TestInitParameters) -> Self {
|
||||
RuntimeLimits::new(
|
||||
value.air_size_limit,
|
||||
value.particle_size_limit,
|
||||
value.call_result_size_limit,
|
||||
value.hard_limit_enabled,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TestInitParameters> for AVMRuntimeLimits {
|
||||
fn from(value: TestInitParameters) -> Self {
|
||||
use air_interpreter_interface::MAX_AIR_SIZE;
|
||||
use air_interpreter_interface::MAX_CALL_RESULT_SIZE;
|
||||
use air_interpreter_interface::MAX_PARTICLE_SIZE;
|
||||
|
||||
AVMRuntimeLimits::new(
|
||||
value.air_size_limit.unwrap_or(MAX_AIR_SIZE),
|
||||
value.particle_size_limit.unwrap_or(MAX_PARTICLE_SIZE),
|
||||
value.call_result_size_limit.unwrap_or(MAX_CALL_RESULT_SIZE),
|
||||
value.hard_limit_enabled,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -74,15 +74,10 @@ pub(crate) fn create_wasm_avm_runner(
|
||||
max_heap_size: Option<u64>,
|
||||
test_init_parameters: TestInitParameters,
|
||||
) -> eyre::Result<Box<WasmAvmRunner>> {
|
||||
let (air_size_limit, particle_size_limit, call_result_size_limit) =
|
||||
test_init_parameters.to_attributes_w_default();
|
||||
|
||||
Ok(Box::new(WasmAvmRunner(AVMRunner::new(
|
||||
air_interpreter_wasm_path.to_owned(),
|
||||
max_heap_size,
|
||||
Some(air_size_limit),
|
||||
Some(particle_size_limit),
|
||||
Some(call_result_size_limit),
|
||||
test_init_parameters.into(),
|
||||
0,
|
||||
)?)))
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user