mirror of
https://github.com/fluencelabs/aquavm
synced 2025-06-23 11:41:33 +00:00
WIP soft limits triggering is signalled via AVMOutcome
This commit is contained in:
@ -25,6 +25,7 @@ use crate::INTERPRETER_SUCCESS;
|
|||||||
use air_interpreter_data::InterpreterDataEnvelope;
|
use air_interpreter_data::InterpreterDataEnvelope;
|
||||||
use air_interpreter_interface::CallRequests;
|
use air_interpreter_interface::CallRequests;
|
||||||
use air_interpreter_interface::CallRequestsRepr;
|
use air_interpreter_interface::CallRequestsRepr;
|
||||||
|
use air_interpreter_interface::SoftLimitsTriggering;
|
||||||
use air_interpreter_sede::ToSerialized;
|
use air_interpreter_sede::ToSerialized;
|
||||||
use air_interpreter_signatures::KeyPair;
|
use air_interpreter_signatures::KeyPair;
|
||||||
use air_utils::measure;
|
use air_utils::measure;
|
||||||
@ -41,6 +42,7 @@ pub(crate) fn from_success_result(
|
|||||||
exec_ctx: ExecutionCtx<'_>,
|
exec_ctx: ExecutionCtx<'_>,
|
||||||
trace_handler: TraceHandler,
|
trace_handler: TraceHandler,
|
||||||
keypair: &KeyPair,
|
keypair: &KeyPair,
|
||||||
|
soft_limits_triggering: SoftLimitsTriggering,
|
||||||
) -> Result<InterpreterOutcome, InterpreterOutcome> {
|
) -> Result<InterpreterOutcome, InterpreterOutcome> {
|
||||||
let (ret_code, error_message) = if exec_ctx.call_results.is_empty() {
|
let (ret_code, error_message) = if exec_ctx.call_results.is_empty() {
|
||||||
(INTERPRETER_SUCCESS, String::new())
|
(INTERPRETER_SUCCESS, String::new())
|
||||||
@ -49,7 +51,14 @@ pub(crate) fn from_success_result(
|
|||||||
(farewell_error.to_error_code(), farewell_error.to_string())
|
(farewell_error.to_error_code(), farewell_error.to_string())
|
||||||
};
|
};
|
||||||
|
|
||||||
let outcome = populate_outcome_from_contexts(exec_ctx, trace_handler, ret_code, error_message, keypair);
|
let outcome = populate_outcome_from_contexts(
|
||||||
|
exec_ctx,
|
||||||
|
trace_handler,
|
||||||
|
ret_code,
|
||||||
|
error_message,
|
||||||
|
keypair,
|
||||||
|
soft_limits_triggering,
|
||||||
|
);
|
||||||
Ok(outcome)
|
Ok(outcome)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,6 +68,7 @@ pub(crate) fn from_success_result(
|
|||||||
pub(crate) fn from_uncatchable_error(
|
pub(crate) fn from_uncatchable_error(
|
||||||
data: impl Into<Vec<u8>> + Debug,
|
data: impl Into<Vec<u8>> + Debug,
|
||||||
error: impl ToErrorCode + ToString + Debug,
|
error: impl ToErrorCode + ToString + Debug,
|
||||||
|
soft_limits_triggering: SoftLimitsTriggering,
|
||||||
) -> InterpreterOutcome {
|
) -> InterpreterOutcome {
|
||||||
let ret_code = error.to_error_code();
|
let ret_code = error.to_error_code();
|
||||||
let data = data.into();
|
let data = data.into();
|
||||||
@ -66,7 +76,14 @@ pub(crate) fn from_uncatchable_error(
|
|||||||
.serialize(&CallRequests::new())
|
.serialize(&CallRequests::new())
|
||||||
.expect("default serializer shouldn't fail");
|
.expect("default serializer shouldn't fail");
|
||||||
|
|
||||||
InterpreterOutcome::new(ret_code, error.to_string(), data, vec![], call_requests)
|
InterpreterOutcome::new(
|
||||||
|
ret_code,
|
||||||
|
error.to_string(),
|
||||||
|
data,
|
||||||
|
vec![],
|
||||||
|
call_requests,
|
||||||
|
soft_limits_triggering,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create InterpreterOutcome from supplied execution context, trace handler, and error,
|
/// Create InterpreterOutcome from supplied execution context, trace handler, and error,
|
||||||
@ -77,6 +94,7 @@ pub(crate) fn from_execution_error(
|
|||||||
trace_handler: TraceHandler,
|
trace_handler: TraceHandler,
|
||||||
error: impl ToErrorCode + ToString + Debug,
|
error: impl ToErrorCode + ToString + Debug,
|
||||||
keypair: &KeyPair,
|
keypair: &KeyPair,
|
||||||
|
soft_limits_triggering: SoftLimitsTriggering,
|
||||||
) -> InterpreterOutcome {
|
) -> InterpreterOutcome {
|
||||||
populate_outcome_from_contexts(
|
populate_outcome_from_contexts(
|
||||||
exec_ctx,
|
exec_ctx,
|
||||||
@ -84,6 +102,7 @@ pub(crate) fn from_execution_error(
|
|||||||
error.to_error_code(),
|
error.to_error_code(),
|
||||||
error.to_string(),
|
error.to_string(),
|
||||||
keypair,
|
keypair,
|
||||||
|
soft_limits_triggering,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,13 +113,14 @@ fn populate_outcome_from_contexts(
|
|||||||
ret_code: i64,
|
ret_code: i64,
|
||||||
error_message: String,
|
error_message: String,
|
||||||
keypair: &KeyPair,
|
keypair: &KeyPair,
|
||||||
|
soft_limits_triggering: SoftLimitsTriggering,
|
||||||
) -> InterpreterOutcome {
|
) -> InterpreterOutcome {
|
||||||
match compactify_streams(&mut exec_ctx, &mut trace_handler) {
|
match compactify_streams(&mut exec_ctx, &mut trace_handler, soft_limits_triggering) {
|
||||||
Ok(()) => {}
|
Ok(()) => {}
|
||||||
Err(outcome) => return outcome,
|
Err(outcome) => return outcome,
|
||||||
};
|
};
|
||||||
|
|
||||||
match sign_result(&mut exec_ctx, keypair) {
|
match sign_result(&mut exec_ctx, keypair, soft_limits_triggering) {
|
||||||
Ok(()) => {}
|
Ok(()) => {}
|
||||||
Err(outcome) => return outcome,
|
Err(outcome) => return outcome,
|
||||||
};
|
};
|
||||||
@ -126,22 +146,37 @@ fn populate_outcome_from_contexts(
|
|||||||
tracing::Level::INFO,
|
tracing::Level::INFO,
|
||||||
"CallRequestsRepr.serialize",
|
"CallRequestsRepr.serialize",
|
||||||
);
|
);
|
||||||
InterpreterOutcome::new(ret_code, error_message, data, next_peer_pks, call_requests)
|
InterpreterOutcome::new(
|
||||||
|
ret_code,
|
||||||
|
error_message,
|
||||||
|
data,
|
||||||
|
next_peer_pks,
|
||||||
|
call_requests,
|
||||||
|
soft_limits_triggering,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compactify_streams(exec_ctx: &mut ExecutionCtx<'_>, trace_ctx: &mut TraceHandler) -> Result<(), InterpreterOutcome> {
|
fn compactify_streams(
|
||||||
|
exec_ctx: &mut ExecutionCtx<'_>,
|
||||||
|
trace_ctx: &mut TraceHandler,
|
||||||
|
soft_limits_triggering: SoftLimitsTriggering,
|
||||||
|
) -> Result<(), InterpreterOutcome> {
|
||||||
exec_ctx
|
exec_ctx
|
||||||
.streams
|
.streams
|
||||||
.compactify(trace_ctx)
|
.compactify(trace_ctx)
|
||||||
.and_then(|_| exec_ctx.stream_maps.compactify(trace_ctx))
|
.and_then(|_| exec_ctx.stream_maps.compactify(trace_ctx))
|
||||||
.map_err(execution_error_into_outcome)
|
.map_err(|err| execution_error_into_outcome(err, soft_limits_triggering))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sign_result(exec_ctx: &mut ExecutionCtx<'_>, keypair: &KeyPair) -> Result<(), InterpreterOutcome> {
|
fn sign_result(
|
||||||
|
exec_ctx: &mut ExecutionCtx<'_>,
|
||||||
|
keypair: &KeyPair,
|
||||||
|
soft_limits_triggering: SoftLimitsTriggering,
|
||||||
|
) -> Result<(), InterpreterOutcome> {
|
||||||
let current_signature = exec_ctx
|
let current_signature = exec_ctx
|
||||||
.peer_cid_tracker
|
.peer_cid_tracker
|
||||||
.gen_signature(&exec_ctx.run_parameters.salt, keypair)
|
.gen_signature(&exec_ctx.run_parameters.salt, keypair)
|
||||||
.map_err(signing_error_into_outcome)?;
|
.map_err(|err| signing_error_into_outcome(err, soft_limits_triggering))?;
|
||||||
|
|
||||||
let current_pubkey = keypair.public();
|
let current_pubkey = keypair.public();
|
||||||
exec_ctx.signature_store.put(current_pubkey, current_signature);
|
exec_ctx.signature_store.put(current_pubkey, current_signature);
|
||||||
@ -151,12 +186,29 @@ fn sign_result(exec_ctx: &mut ExecutionCtx<'_>, keypair: &KeyPair) -> Result<(),
|
|||||||
|
|
||||||
// these methods are called only if there is an internal error in the interpreter and
|
// these methods are called only if there is an internal error in the interpreter and
|
||||||
// new execution trace was corrupted
|
// new execution trace was corrupted
|
||||||
fn execution_error_into_outcome(error: ExecutionError) -> InterpreterOutcome {
|
fn execution_error_into_outcome(
|
||||||
InterpreterOutcome::new(error.to_error_code(), error.to_string(), vec![], vec![], <_>::default())
|
error: ExecutionError,
|
||||||
|
soft_limits_triggering: SoftLimitsTriggering,
|
||||||
|
) -> InterpreterOutcome {
|
||||||
|
InterpreterOutcome::new(
|
||||||
|
error.to_error_code(),
|
||||||
|
error.to_string(),
|
||||||
|
vec![],
|
||||||
|
vec![],
|
||||||
|
<_>::default(),
|
||||||
|
soft_limits_triggering,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signing_error_into_outcome(error: SigningError) -> InterpreterOutcome {
|
fn signing_error_into_outcome(error: SigningError, soft_limits_triggering: SoftLimitsTriggering) -> InterpreterOutcome {
|
||||||
InterpreterOutcome::new(error.to_error_code(), error.to_string(), vec![], vec![], <_>::default())
|
InterpreterOutcome::new(
|
||||||
|
error.to_error_code(),
|
||||||
|
error.to_string(),
|
||||||
|
vec![],
|
||||||
|
vec![],
|
||||||
|
<_>::default(),
|
||||||
|
soft_limits_triggering,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deduplicate values in a supplied vector.
|
/// Deduplicate values in a supplied vector.
|
||||||
|
@ -128,7 +128,7 @@ impl PreparationError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn air_size_limit(actual_size: usize, limit: u64) -> Self {
|
pub fn air_size_limit(actual_size: usize, limit: u64) -> Self {
|
||||||
Self::SizeLimitsExceded(SizeLimitsExceded::AIR(actual_size, limit))
|
Self::SizeLimitsExceded(SizeLimitsExceded::Air(actual_size, limit))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn particle_size_limit(actual_size: usize, limit: u64) -> Self {
|
pub fn particle_size_limit(actual_size: usize, limit: u64) -> Self {
|
||||||
@ -144,7 +144,7 @@ impl PreparationError {
|
|||||||
pub enum SizeLimitsExceded {
|
pub enum SizeLimitsExceded {
|
||||||
/// AIR script size is bigger than the allowed limit.
|
/// AIR script size is bigger than the allowed limit.
|
||||||
#[error("air size: {0} bytes is bigger than the limit allowed: {1} bytes")]
|
#[error("air size: {0} bytes is bigger than the limit allowed: {1} bytes")]
|
||||||
AIR(usize, u64),
|
Air(usize, u64),
|
||||||
|
|
||||||
/// Current_data particle size is bigger than the allowed limit.
|
/// 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")]
|
#[error("Current_data particle size: {0} bytes is bigger than the limit allowed: {1} bytes")]
|
||||||
|
@ -26,6 +26,7 @@ use air_interpreter_data::Versions;
|
|||||||
use air_interpreter_interface::CallResultsRepr;
|
use air_interpreter_interface::CallResultsRepr;
|
||||||
use air_interpreter_interface::RunParameters;
|
use air_interpreter_interface::RunParameters;
|
||||||
use air_interpreter_interface::SerializedCallResults;
|
use air_interpreter_interface::SerializedCallResults;
|
||||||
|
use air_interpreter_interface::SoftLimitsTriggering;
|
||||||
use air_interpreter_sede::FromSerialized;
|
use air_interpreter_sede::FromSerialized;
|
||||||
use air_interpreter_signatures::KeyError;
|
use air_interpreter_signatures::KeyError;
|
||||||
use air_interpreter_signatures::KeyPair;
|
use air_interpreter_signatures::KeyPair;
|
||||||
@ -75,6 +76,7 @@ pub(crate) fn prepare<'i>(
|
|||||||
call_results: &SerializedCallResults,
|
call_results: &SerializedCallResults,
|
||||||
run_parameters: RunParameters,
|
run_parameters: RunParameters,
|
||||||
signature_store: SignatureStore,
|
signature_store: SignatureStore,
|
||||||
|
soft_limits_triggering: &mut SoftLimitsTriggering,
|
||||||
) -> PreparationResult<PreparationDescriptor<'static, 'i>> {
|
) -> PreparationResult<PreparationDescriptor<'static, 'i>> {
|
||||||
let air: Instruction<'i> = air_parser::parse(raw_air).map_err(PreparationError::AIRParseError)?;
|
let air: Instruction<'i> = air_parser::parse(raw_air).map_err(PreparationError::AIRParseError)?;
|
||||||
|
|
||||||
@ -94,6 +96,7 @@ pub(crate) fn prepare<'i>(
|
|||||||
call_results,
|
call_results,
|
||||||
signature_store,
|
signature_store,
|
||||||
&run_parameters,
|
&run_parameters,
|
||||||
|
soft_limits_triggering,
|
||||||
)?;
|
)?;
|
||||||
let trace_handler = TraceHandler::from_trace(prev_data.trace, current_data.trace);
|
let trace_handler = TraceHandler::from_trace(prev_data.trace, current_data.trace);
|
||||||
|
|
||||||
@ -143,6 +146,7 @@ fn make_exec_ctx(
|
|||||||
call_results: &SerializedCallResults,
|
call_results: &SerializedCallResults,
|
||||||
signature_store: SignatureStore,
|
signature_store: SignatureStore,
|
||||||
run_parameters: &RunParameters,
|
run_parameters: &RunParameters,
|
||||||
|
soft_limits_triggering: &mut SoftLimitsTriggering,
|
||||||
) -> PreparationResult<ExecutionCtx<'static>> {
|
) -> PreparationResult<ExecutionCtx<'static>> {
|
||||||
use crate::preparation_step::sizes_limits_check::limit_behavior;
|
use crate::preparation_step::sizes_limits_check::limit_behavior;
|
||||||
|
|
||||||
@ -159,8 +163,12 @@ fn make_exec_ctx(
|
|||||||
.values()
|
.values()
|
||||||
.any(|call_result| call_result.result.len() > run_parameters.call_result_size_limit as usize)
|
.any(|call_result| call_result.result.len() > run_parameters.call_result_size_limit as usize)
|
||||||
{
|
{
|
||||||
let error = PreparationError::call_result_size_limit(run_parameters.call_result_size_limit);
|
let error: PreparationError = PreparationError::call_result_size_limit(run_parameters.call_result_size_limit);
|
||||||
limit_behavior(run_parameters, error)?;
|
limit_behavior(
|
||||||
|
run_parameters,
|
||||||
|
error,
|
||||||
|
&mut soft_limits_triggering.particle_size_limit_exceeded,
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let ctx = ExecutionCtx::new(
|
let ctx = ExecutionCtx::new(
|
||||||
|
@ -17,12 +17,17 @@
|
|||||||
use super::preparation::PreparationResult;
|
use super::preparation::PreparationResult;
|
||||||
use crate::PreparationError;
|
use crate::PreparationError;
|
||||||
|
|
||||||
use air_interpreter_interface::RunParameters;
|
use air_interpreter_interface::{RunParameters, SoftLimitsTriggering};
|
||||||
|
|
||||||
pub(crate) fn limit_behavior(run_parameters: &RunParameters, error: PreparationError) -> PreparationResult<()> {
|
pub(crate) fn limit_behavior(
|
||||||
|
run_parameters: &RunParameters,
|
||||||
|
error: PreparationError,
|
||||||
|
soft_limit_flag: &mut bool,
|
||||||
|
) -> PreparationResult<()> {
|
||||||
if run_parameters.hard_limit_enabled {
|
if run_parameters.hard_limit_enabled {
|
||||||
Err(error)
|
Err(error)
|
||||||
} else {
|
} else {
|
||||||
|
*soft_limit_flag = true;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -31,16 +36,26 @@ pub(crate) fn check_against_size_limits(
|
|||||||
run_parameters: &RunParameters,
|
run_parameters: &RunParameters,
|
||||||
air: &str,
|
air: &str,
|
||||||
raw_current_data: &[u8],
|
raw_current_data: &[u8],
|
||||||
) -> PreparationResult<()> {
|
) -> PreparationResult<SoftLimitsTriggering> {
|
||||||
|
let mut soft_limits_triggering = SoftLimitsTriggering::default();
|
||||||
|
|
||||||
if air.len() as u64 > run_parameters.air_size_limit {
|
if air.len() as u64 > run_parameters.air_size_limit {
|
||||||
let error = 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)?;
|
limit_behavior(
|
||||||
|
run_parameters,
|
||||||
|
error,
|
||||||
|
&mut soft_limits_triggering.air_size_limit_exceeded,
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if raw_current_data.len() as u64 > 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);
|
let error = PreparationError::particle_size_limit(raw_current_data.len(), run_parameters.particle_size_limit);
|
||||||
limit_behavior(run_parameters, error)?;
|
limit_behavior(
|
||||||
|
run_parameters,
|
||||||
|
error,
|
||||||
|
&mut soft_limits_triggering.particle_size_limit_exceeded,
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(soft_limits_triggering)
|
||||||
}
|
}
|
||||||
|
@ -63,20 +63,34 @@ fn execute_air_impl(
|
|||||||
) -> Result<InterpreterOutcome, InterpreterOutcome> {
|
) -> Result<InterpreterOutcome, InterpreterOutcome> {
|
||||||
use crate::preparation_step::check_against_size_limits;
|
use crate::preparation_step::check_against_size_limits;
|
||||||
|
|
||||||
farewell_if_fail!(
|
let mut soft_limits_triggering = farewell_if_fail!(
|
||||||
check_against_size_limits(¶ms, &air, &raw_current_data),
|
check_against_size_limits(¶ms, &air, &raw_current_data),
|
||||||
raw_prev_data
|
raw_prev_data
|
||||||
);
|
);
|
||||||
|
|
||||||
|
farewell_if_fail!(
|
||||||
|
check_against_size_limits(¶ms, &air, &raw_current_data),
|
||||||
|
raw_prev_data,
|
||||||
|
soft_limits_triggering
|
||||||
|
);
|
||||||
|
|
||||||
let ParsedDataPair {
|
let ParsedDataPair {
|
||||||
prev_data,
|
prev_data,
|
||||||
current_data,
|
current_data,
|
||||||
} = farewell_if_fail!(parse_data(&raw_prev_data, &raw_current_data), raw_prev_data);
|
} = farewell_if_fail!(
|
||||||
|
parse_data(&raw_prev_data, &raw_current_data),
|
||||||
|
raw_prev_data,
|
||||||
|
soft_limits_triggering
|
||||||
|
);
|
||||||
|
|
||||||
// TODO currently we use particle ID, but it should be changed to signature,
|
// TODO currently we use particle ID, but it should be changed to signature,
|
||||||
// as partical ID can be equally replayed
|
// as partical ID can be equally replayed
|
||||||
let salt = params.particle_id.clone();
|
let salt = params.particle_id.clone();
|
||||||
let signature_store = farewell_if_fail!(verify(&prev_data, ¤t_data, &salt), raw_prev_data);
|
let signature_store = farewell_if_fail!(
|
||||||
|
verify(&prev_data, ¤t_data, &salt),
|
||||||
|
raw_prev_data,
|
||||||
|
soft_limits_triggering
|
||||||
|
);
|
||||||
|
|
||||||
let PreparationDescriptor {
|
let PreparationDescriptor {
|
||||||
mut exec_ctx,
|
mut exec_ctx,
|
||||||
@ -84,8 +98,17 @@ fn execute_air_impl(
|
|||||||
air,
|
air,
|
||||||
keypair,
|
keypair,
|
||||||
} = farewell_if_fail!(
|
} = farewell_if_fail!(
|
||||||
prepare(prev_data, current_data, &air, &call_results, params, signature_store,),
|
prepare(
|
||||||
raw_prev_data
|
prev_data,
|
||||||
|
current_data,
|
||||||
|
&air,
|
||||||
|
&call_results,
|
||||||
|
params,
|
||||||
|
signature_store,
|
||||||
|
&mut soft_limits_triggering
|
||||||
|
),
|
||||||
|
raw_prev_data,
|
||||||
|
soft_limits_triggering
|
||||||
);
|
);
|
||||||
|
|
||||||
// match here is used instead of map_err, because the compiler can't determine that
|
// match here is used instead of map_err, because the compiler can't determine that
|
||||||
@ -103,18 +126,29 @@ fn execute_air_impl(
|
|||||||
&salt,
|
&salt,
|
||||||
&keypair,
|
&keypair,
|
||||||
),
|
),
|
||||||
raw_prev_data
|
raw_prev_data,
|
||||||
|
soft_limits_triggering
|
||||||
);
|
);
|
||||||
|
|
||||||
measure!(
|
measure!(
|
||||||
match exec_result {
|
match exec_result {
|
||||||
Ok(_) => farewell::from_success_result(exec_ctx, trace_handler, &keypair),
|
Ok(_) => farewell::from_success_result(exec_ctx, trace_handler, &keypair, soft_limits_triggering),
|
||||||
// return new collected trace in case of errors
|
// return new collected trace in case of errors
|
||||||
Err(error) if error.is_catchable() => {
|
Err(error) if error.is_catchable() => {
|
||||||
Err(farewell::from_execution_error(exec_ctx, trace_handler, error, &keypair))
|
Err(farewell::from_execution_error(
|
||||||
|
exec_ctx,
|
||||||
|
trace_handler,
|
||||||
|
error,
|
||||||
|
&keypair,
|
||||||
|
soft_limits_triggering,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
// return the prev data in case of any trace errors
|
// return the prev data in case of any trace errors
|
||||||
Err(error) => Err(farewell::from_uncatchable_error(raw_prev_data, error)),
|
Err(error) => Err(farewell::from_uncatchable_error(
|
||||||
|
raw_prev_data,
|
||||||
|
error,
|
||||||
|
soft_limits_triggering
|
||||||
|
)),
|
||||||
},
|
},
|
||||||
tracing::Level::INFO,
|
tracing::Level::INFO,
|
||||||
"farewell",
|
"farewell",
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
use super::CallRequests;
|
use super::CallRequests;
|
||||||
use crate::raw_outcome::RawAVMOutcome;
|
use crate::raw_outcome::RawAVMOutcome;
|
||||||
|
|
||||||
|
use air_interpreter_interface::SoftLimitsTriggering;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
@ -40,6 +41,8 @@ pub struct AVMOutcome {
|
|||||||
/// Time of a particle execution
|
/// Time of a particle execution
|
||||||
/// (it counts only execution time without operations with DataStore and so on)
|
/// (it counts only execution time without operations with DataStore and so on)
|
||||||
pub execution_time: Duration,
|
pub execution_time: Duration,
|
||||||
|
|
||||||
|
soft_limits_triggering: SoftLimitsTriggering, // WIP
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
@ -56,6 +59,7 @@ impl AVMOutcome {
|
|||||||
next_peer_pks: Vec<String>,
|
next_peer_pks: Vec<String>,
|
||||||
memory_delta: usize,
|
memory_delta: usize,
|
||||||
execution_time: Duration,
|
execution_time: Duration,
|
||||||
|
soft_limits_triggering: SoftLimitsTriggering,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
data,
|
data,
|
||||||
@ -63,6 +67,7 @@ impl AVMOutcome {
|
|||||||
next_peer_pks,
|
next_peer_pks,
|
||||||
memory_delta,
|
memory_delta,
|
||||||
execution_time,
|
execution_time,
|
||||||
|
soft_limits_triggering,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,6 +85,7 @@ impl AVMOutcome {
|
|||||||
data,
|
data,
|
||||||
call_requests,
|
call_requests,
|
||||||
next_peer_pks,
|
next_peer_pks,
|
||||||
|
soft_limits_triggering,
|
||||||
} = raw_outcome;
|
} = raw_outcome;
|
||||||
|
|
||||||
let avm_outcome = AVMOutcome::new(
|
let avm_outcome = AVMOutcome::new(
|
||||||
@ -88,6 +94,7 @@ impl AVMOutcome {
|
|||||||
next_peer_pks,
|
next_peer_pks,
|
||||||
memory_delta,
|
memory_delta,
|
||||||
execution_time,
|
execution_time,
|
||||||
|
soft_limits_triggering,
|
||||||
);
|
);
|
||||||
|
|
||||||
if ret_code == INTERPRETER_SUCCESS {
|
if ret_code == INTERPRETER_SUCCESS {
|
||||||
|
@ -20,6 +20,7 @@ use super::CallRequests;
|
|||||||
|
|
||||||
use air_interpreter_interface::InterpreterOutcome;
|
use air_interpreter_interface::InterpreterOutcome;
|
||||||
|
|
||||||
|
use air_interpreter_interface::SoftLimitsTriggering;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
@ -31,6 +32,7 @@ pub struct RawAVMOutcome {
|
|||||||
pub data: Vec<u8>,
|
pub data: Vec<u8>,
|
||||||
pub call_requests: CallRequests,
|
pub call_requests: CallRequests,
|
||||||
pub next_peer_pks: Vec<String>,
|
pub next_peer_pks: Vec<String>,
|
||||||
|
pub soft_limits_triggering: SoftLimitsTriggering,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RawAVMOutcome {
|
impl RawAVMOutcome {
|
||||||
@ -41,9 +43,17 @@ impl RawAVMOutcome {
|
|||||||
data,
|
data,
|
||||||
call_requests,
|
call_requests,
|
||||||
next_peer_pks,
|
next_peer_pks,
|
||||||
|
air_size_limit_exceeded,
|
||||||
|
particle_size_limit_exceeded,
|
||||||
|
call_result_size_limit_exceeded,
|
||||||
} = outcome;
|
} = outcome;
|
||||||
|
|
||||||
let call_requests = crate::from_raw_call_requests(call_requests.into())?;
|
let call_requests = crate::from_raw_call_requests(call_requests.into())?;
|
||||||
|
let soft_limits_triggering = SoftLimitsTriggering::new(
|
||||||
|
air_size_limit_exceeded,
|
||||||
|
particle_size_limit_exceeded,
|
||||||
|
call_result_size_limit_exceeded,
|
||||||
|
);
|
||||||
|
|
||||||
let raw_avm_outcome = Self {
|
let raw_avm_outcome = Self {
|
||||||
ret_code,
|
ret_code,
|
||||||
@ -51,6 +61,7 @@ impl RawAVMOutcome {
|
|||||||
data,
|
data,
|
||||||
call_requests,
|
call_requests,
|
||||||
next_peer_pks,
|
next_peer_pks,
|
||||||
|
soft_limits_triggering,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(raw_avm_outcome)
|
Ok(raw_avm_outcome)
|
||||||
|
@ -43,6 +43,7 @@ pub struct AVMRuntimeLimits {
|
|||||||
pub hard_limit_enabled: bool,
|
pub hard_limit_enabled: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
pub struct RuntimeLimits {
|
pub struct RuntimeLimits {
|
||||||
// The AIR script size limit.
|
// The AIR script size limit.
|
||||||
pub air_size_limit: Option<u64>,
|
pub air_size_limit: Option<u64>,
|
||||||
@ -392,17 +393,6 @@ impl RuntimeLimits {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
impl From<RuntimeLimits> for AVMRuntimeLimits {
|
||||||
fn from(value: RuntimeLimits) -> Self {
|
fn from(value: RuntimeLimits) -> Self {
|
||||||
use air_interpreter_interface::MAX_AIR_SIZE;
|
use air_interpreter_interface::MAX_AIR_SIZE;
|
||||||
|
@ -25,6 +25,7 @@ pub struct AVMRuntimeLimits {
|
|||||||
pub hard_limit_enabled: bool,
|
pub hard_limit_enabled: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
pub struct RuntimeLimits {
|
pub struct RuntimeLimits {
|
||||||
pub air_size_limit: Option<u64>,
|
pub air_size_limit: Option<u64>,
|
||||||
pub particle_size_limit: Option<u64>,
|
pub particle_size_limit: Option<u64>,
|
||||||
@ -48,17 +49,6 @@ impl AVMRuntimeLimits {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
impl From<RuntimeLimits> for AVMRuntimeLimits {
|
||||||
fn from(value: RuntimeLimits) -> Self {
|
fn from(value: RuntimeLimits) -> Self {
|
||||||
use air_interpreter_interface::MAX_AIR_SIZE;
|
use air_interpreter_interface::MAX_AIR_SIZE;
|
||||||
|
@ -24,6 +24,13 @@ use serde::Serialize;
|
|||||||
|
|
||||||
pub const INTERPRETER_SUCCESS: i64 = 0;
|
pub const INTERPRETER_SUCCESS: i64 = 0;
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct SoftLimitsTriggering {
|
||||||
|
pub air_size_limit_exceeded: bool,
|
||||||
|
pub particle_size_limit_exceeded: bool,
|
||||||
|
pub call_result_size_limit_exceeded: bool,
|
||||||
|
}
|
||||||
|
|
||||||
/// Describes a result returned at the end of the interpreter execution_step.
|
/// Describes a result returned at the end of the interpreter execution_step.
|
||||||
#[cfg_attr(feature = "marine", marine)]
|
#[cfg_attr(feature = "marine", marine)]
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
@ -43,6 +50,25 @@ pub struct InterpreterOutcome {
|
|||||||
|
|
||||||
/// Collected parameters of all met call instructions that could be executed on a current peer.
|
/// Collected parameters of all met call instructions that could be executed on a current peer.
|
||||||
pub call_requests: Vec<u8>,
|
pub call_requests: Vec<u8>,
|
||||||
|
|
||||||
|
/// WIP
|
||||||
|
pub air_size_limit_exceeded: bool,
|
||||||
|
pub particle_size_limit_exceeded: bool,
|
||||||
|
pub call_result_size_limit_exceeded: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SoftLimitsTriggering {
|
||||||
|
pub fn new(
|
||||||
|
air_size_limit_exceeded: bool,
|
||||||
|
particle_size_limit_exceeded: bool,
|
||||||
|
call_result_size_limit_exceeded: bool,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
air_size_limit_exceeded,
|
||||||
|
particle_size_limit_exceeded,
|
||||||
|
call_result_size_limit_exceeded,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InterpreterOutcome {
|
impl InterpreterOutcome {
|
||||||
@ -52,6 +78,7 @@ impl InterpreterOutcome {
|
|||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
next_peer_pks: Vec<String>,
|
next_peer_pks: Vec<String>,
|
||||||
call_requests: SerializedCallRequests,
|
call_requests: SerializedCallRequests,
|
||||||
|
soft_limits_triggering: SoftLimitsTriggering,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let call_requests = call_requests.into();
|
let call_requests = call_requests.into();
|
||||||
Self {
|
Self {
|
||||||
@ -60,6 +87,9 @@ impl InterpreterOutcome {
|
|||||||
data,
|
data,
|
||||||
next_peer_pks,
|
next_peer_pks,
|
||||||
call_requests,
|
call_requests,
|
||||||
|
air_size_limit_exceeded: soft_limits_triggering.air_size_limit_exceeded,
|
||||||
|
particle_size_limit_exceeded: soft_limits_triggering.particle_size_limit_exceeded,
|
||||||
|
call_result_size_limit_exceeded: soft_limits_triggering.call_result_size_limit_exceeded,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -67,7 +97,7 @@ impl InterpreterOutcome {
|
|||||||
#[cfg(feature = "marine")]
|
#[cfg(feature = "marine")]
|
||||||
impl InterpreterOutcome {
|
impl InterpreterOutcome {
|
||||||
pub fn from_ivalue(ivalue: IValue) -> Result<Self, String> {
|
pub fn from_ivalue(ivalue: IValue) -> Result<Self, String> {
|
||||||
const OUTCOME_FIELDS_COUNT: usize = 5;
|
const OUTCOME_FIELDS_COUNT: usize = 8;
|
||||||
|
|
||||||
let mut record_values = try_as_record(ivalue)?.into_vec();
|
let mut record_values = try_as_record(ivalue)?.into_vec();
|
||||||
if record_values.len() != OUTCOME_FIELDS_COUNT {
|
if record_values.len() != OUTCOME_FIELDS_COUNT {
|
||||||
@ -76,11 +106,24 @@ impl InterpreterOutcome {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let air_size_limit_exceeded =
|
||||||
|
try_as_boolean(record_values.pop().unwrap(), "air_size_limit_exceeded")?;
|
||||||
|
let particle_size_limit_exceeded =
|
||||||
|
try_as_boolean(record_values.pop().unwrap(), "particle_size_limit_exceeded")?;
|
||||||
|
let call_result_size_limit_exceeded = try_as_boolean(
|
||||||
|
record_values.pop().unwrap(),
|
||||||
|
"call_result_size_limit_exceeded",
|
||||||
|
)?;
|
||||||
let call_requests = try_as_byte_vec(record_values.pop().unwrap(), "call_requests")?;
|
let call_requests = try_as_byte_vec(record_values.pop().unwrap(), "call_requests")?;
|
||||||
let next_peer_pks = try_as_string_vec(record_values.pop().unwrap(), "next_peer_pks")?;
|
let next_peer_pks = try_as_string_vec(record_values.pop().unwrap(), "next_peer_pks")?;
|
||||||
let data = try_as_byte_vec(record_values.pop().unwrap(), "data")?;
|
let data = try_as_byte_vec(record_values.pop().unwrap(), "data")?;
|
||||||
let error_message = try_as_string(record_values.pop().unwrap(), "error_message")?;
|
let error_message = try_as_string(record_values.pop().unwrap(), "error_message")?;
|
||||||
let ret_code = try_as_i64(record_values.pop().unwrap(), "ret_code")?;
|
let ret_code = try_as_i64(record_values.pop().unwrap(), "ret_code")?;
|
||||||
|
let soft_limits_triggering = SoftLimitsTriggering::new(
|
||||||
|
air_size_limit_exceeded,
|
||||||
|
particle_size_limit_exceeded,
|
||||||
|
call_result_size_limit_exceeded,
|
||||||
|
);
|
||||||
|
|
||||||
let outcome = Self::new(
|
let outcome = Self::new(
|
||||||
ret_code,
|
ret_code,
|
||||||
@ -88,6 +131,7 @@ impl InterpreterOutcome {
|
|||||||
data,
|
data,
|
||||||
next_peer_pks,
|
next_peer_pks,
|
||||||
call_requests.into(),
|
call_requests.into(),
|
||||||
|
soft_limits_triggering,
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(outcome)
|
Ok(outcome)
|
||||||
@ -160,3 +204,11 @@ fn try_as_string_vec(ivalue: IValue, field_name: &str) -> Result<Vec<String>, St
|
|||||||
v => Err(format!("expected an array for {field_name}, got {v:?}")),
|
v => Err(format!("expected an array for {field_name}, got {v:?}")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "marine")]
|
||||||
|
fn try_as_boolean(ivalue: IValue, field_name: &str) -> Result<bool, String> {
|
||||||
|
match ivalue {
|
||||||
|
IValue::Boolean(value) => Ok(value),
|
||||||
|
v => Err(format!("expected a bool for {field_name}, got {v:?}")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -57,7 +57,7 @@ impl AirRunner for WasmAirRunner {
|
|||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
let runner = pool.pull(|| make_pooled_avm_runner(test_init_parameters.clone()));
|
let runner = pool.pull(|| make_pooled_avm_runner(test_init_parameters));
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
current_peer_id: current_peer_id.into(),
|
current_peer_id: current_peer_id.into(),
|
||||||
|
@ -51,11 +51,26 @@ macro_rules! auto_checked_add {
|
|||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! farewell_if_fail {
|
macro_rules! farewell_if_fail {
|
||||||
|
($cmd:expr, $raw_prev_data:expr, $soft_limits_triggering:expr) => {
|
||||||
|
match $cmd {
|
||||||
|
Ok(result) => result,
|
||||||
|
// return the prev data in case of errors
|
||||||
|
Err(error) => {
|
||||||
|
return Err(farewell::from_uncatchable_error(
|
||||||
|
$raw_prev_data,
|
||||||
|
error,
|
||||||
|
$soft_limits_triggering,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
($cmd:expr, $raw_prev_data:expr) => {
|
($cmd:expr, $raw_prev_data:expr) => {
|
||||||
match $cmd {
|
match $cmd {
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
// return the prev data in case of errors
|
// return the prev data in case of errors
|
||||||
Err(error) => return Err(farewell::from_uncatchable_error($raw_prev_data, error)),
|
Err(error) => {
|
||||||
|
farewell_if_fail!($cmd, $raw_prev_data, <_>::default())
|
||||||
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,7 @@ impl<R: AirRunner> Network<R> {
|
|||||||
resolver: Default::default(),
|
resolver: Default::default(),
|
||||||
});
|
});
|
||||||
for peer_name in named_peers {
|
for peer_name in named_peers {
|
||||||
network.ensure_named_peer(peer_name, test_init_params.clone());
|
network.ensure_named_peer(peer_name, test_init_params);
|
||||||
}
|
}
|
||||||
network
|
network
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ impl<R: AirRunner> AirScriptExecutor<R> {
|
|||||||
annotated_air_script: &str,
|
annotated_air_script: &str,
|
||||||
) -> Result<Self, String> {
|
) -> Result<Self, String> {
|
||||||
let transformed =
|
let transformed =
|
||||||
TransformedAirScript::new(annotated_air_script, network, test_init_parameters.clone())?;
|
TransformedAirScript::new(annotated_air_script, network, test_init_parameters)?;
|
||||||
|
|
||||||
Self::from_transformed_air_script(test_parameters, test_init_parameters, transformed)
|
Self::from_transformed_air_script(test_parameters, test_init_parameters, transformed)
|
||||||
}
|
}
|
||||||
@ -115,10 +115,10 @@ impl<R: AirRunner> AirScriptExecutor<R> {
|
|||||||
let network = Network::new(
|
let network = Network::new(
|
||||||
extra_peers.into_iter(),
|
extra_peers.into_iter(),
|
||||||
common_services,
|
common_services,
|
||||||
test_init_parameters.clone(),
|
test_init_parameters,
|
||||||
);
|
);
|
||||||
let transformed =
|
let transformed =
|
||||||
TransformedAirScript::new(annotated_air_script, network, test_init_parameters.clone())?;
|
TransformedAirScript::new(annotated_air_script, network, test_init_parameters)?;
|
||||||
|
|
||||||
Self::from_transformed_air_script(test_parameters, test_init_parameters, transformed)
|
Self::from_transformed_air_script(test_parameters, test_init_parameters, transformed)
|
||||||
}
|
}
|
||||||
|
@ -83,11 +83,11 @@ struct Transformer<'net, R> {
|
|||||||
impl<R: AirRunner> Transformer<'_, R> {
|
impl<R: AirRunner> Transformer<'_, R> {
|
||||||
pub(crate) fn transform(&self, sexp: &mut Sexp, test_init_parameters: TestInitParameters) {
|
pub(crate) fn transform(&self, sexp: &mut Sexp, test_init_parameters: TestInitParameters) {
|
||||||
match sexp {
|
match sexp {
|
||||||
Sexp::Call(call) => self.handle_call(call, test_init_parameters.clone()),
|
Sexp::Call(call) => self.handle_call(call, test_init_parameters),
|
||||||
Sexp::Canon(canon) => self.handle_canon(canon, test_init_parameters.clone()),
|
Sexp::Canon(canon) => self.handle_canon(canon, test_init_parameters),
|
||||||
Sexp::List(children) => {
|
Sexp::List(children) => {
|
||||||
for child in children.iter_mut().skip(1) {
|
for child in children.iter_mut().skip(1) {
|
||||||
self.transform(child, test_init_parameters.clone());
|
self.transform(child, test_init_parameters);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Sexp::Symbol(_) | Sexp::String(_) => {}
|
Sexp::Symbol(_) | Sexp::String(_) => {}
|
||||||
|
Reference in New Issue
Block a user