mirror of
https://github.com/fluencelabs/aquavm
synced 2024-12-04 07:10:18 +00:00
introduce farewell step; reafactoring
This commit is contained in:
parent
8dbae91bda
commit
54e383cdaf
13
Cargo.lock
generated
13
Cargo.lock
generated
@ -25,6 +25,7 @@ dependencies = [
|
||||
"air-test-utils",
|
||||
"air-trace-handler",
|
||||
"boolinator",
|
||||
"concat-idents",
|
||||
"criterion",
|
||||
"csv",
|
||||
"env_logger",
|
||||
@ -73,7 +74,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "air-interpreter-interface"
|
||||
version = "0.7.0"
|
||||
version = "0.8.0"
|
||||
dependencies = [
|
||||
"fluence-it-types",
|
||||
"marine-rs-sdk",
|
||||
@ -408,6 +409,16 @@ dependencies = [
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "concat-idents"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b6f90860248d75014b7b103db8fee4f291c07bfb41306cdf77a0a5ab7a10d2f"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.1.5"
|
||||
|
@ -30,6 +30,7 @@ serde = { version = "1.0.118", features = [ "derive", "rc" ] }
|
||||
serde_json = "1.0.61"
|
||||
|
||||
boolinator = "2.4.0"
|
||||
concat-idents = "1.1.3"
|
||||
maplit = "1.0.2"
|
||||
log = "0.4.11"
|
||||
thiserror = "1.0.23"
|
||||
|
@ -22,7 +22,7 @@ use super::ExecutionResult;
|
||||
use super::TraceHandler;
|
||||
use crate::execution_step::air::ValueAggregate;
|
||||
use crate::execution_step::boxed_value::Variable;
|
||||
use crate::execution_step::utils::apply_lambda;
|
||||
use crate::execution_step::resolver::apply_lambda;
|
||||
use crate::trace_to_exec_err;
|
||||
use crate::JValue;
|
||||
use crate::SecurityTetraplet;
|
||||
|
@ -52,7 +52,7 @@ fn apply_last_error(
|
||||
exec_ctx: &ExecutionCtx<'_>,
|
||||
trace_ctx: &TraceHandler,
|
||||
) -> ExecutionResult<ValueAggregate> {
|
||||
let (value, mut tetraplets) = crate::execution_step::utils::prepare_last_error(error_path, exec_ctx)?;
|
||||
let (value, mut tetraplets) = crate::execution_step::resolver::prepare_last_error(error_path, exec_ctx)?;
|
||||
let value = Rc::new(value);
|
||||
// removing is safe because prepare_last_error always returns a vec with one element.
|
||||
let tetraplet = tetraplets.remove(0);
|
||||
|
@ -149,7 +149,7 @@ impl<'i> ResolvedCall<'i> {
|
||||
|
||||
/// Prepare arguments of this call instruction by resolving and preparing their security tetraplets.
|
||||
fn resolve_args(&self, exec_ctx: &ExecutionCtx<'i>) -> ExecutionResult<ResolvedArguments> {
|
||||
use crate::execution_step::utils::resolve_to_args;
|
||||
use crate::execution_step::resolver::resolve_to_args;
|
||||
|
||||
let function_args = self.function_arg_paths.iter();
|
||||
let mut call_arguments = Vec::new();
|
||||
|
@ -45,7 +45,7 @@ pub(crate) fn resolve<'i>(triplet: &ast::Triplet<'i>, ctx: &ExecutionCtx<'i>) ->
|
||||
/// Resolve value to string by either resolving variable from `ExecutionCtx`, taking literal value, or etc.
|
||||
// TODO: return Rc<String> to avoid excess cloning
|
||||
fn resolve_to_string<'i>(value: &ast::CallInstrValue<'i>, ctx: &ExecutionCtx<'i>) -> ExecutionResult<String> {
|
||||
use crate::execution_step::utils::resolve_ast_variable_wl;
|
||||
use crate::execution_step::resolver::resolve_ast_variable_wl;
|
||||
use ast::CallInstrValue::*;
|
||||
|
||||
let resolved = match value {
|
||||
|
@ -16,8 +16,8 @@
|
||||
|
||||
use crate::execution_step::air::ExecutionResult;
|
||||
use crate::execution_step::execution_context::ExecutionCtx;
|
||||
use crate::execution_step::utils::prepare_last_error;
|
||||
use crate::execution_step::utils::resolve_ast_variable_wl;
|
||||
use crate::execution_step::resolver::prepare_last_error;
|
||||
use crate::execution_step::resolver::resolve_ast_variable_wl;
|
||||
use crate::JValue;
|
||||
|
||||
use air_parser::ast;
|
||||
|
@ -14,10 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use super::ExecutionError;
|
||||
use super::ExecutionError::LambdaApplierError;
|
||||
use super::ExecutionResult;
|
||||
use super::JValuable;
|
||||
use super::LambdaAST;
|
||||
use super::LambdaError::EmptyStream;
|
||||
use crate::exec_err;
|
||||
use crate::execution_step::ExecutionCtx;
|
||||
use crate::execution_step::RSecurityTetraplet;
|
||||
@ -29,7 +30,7 @@ use std::borrow::Cow;
|
||||
impl JValuable for () {
|
||||
fn apply_lambda<'i>(&self, _lambda: &LambdaAST<'_>, _exec_ctx: &ExecutionCtx<'i>) -> ExecutionResult<&JValue> {
|
||||
// applying lambda to an empty stream will produce a join behaviour
|
||||
exec_err!(ExecutionError::EmptyStreamLambdaError)
|
||||
exec_err!(LambdaApplierError(EmptyStream))
|
||||
}
|
||||
|
||||
fn apply_lambda_with_tetraplets<'i>(
|
||||
@ -38,7 +39,7 @@ impl JValuable for () {
|
||||
_exec_ctx: &ExecutionCtx<'i>,
|
||||
) -> ExecutionResult<(&JValue, RSecurityTetraplet)> {
|
||||
// applying lambda to an empty stream will produce a join behaviour
|
||||
exec_err!(ExecutionError::EmptyStreamLambdaError)
|
||||
exec_err!(LambdaApplierError(EmptyStream))
|
||||
}
|
||||
|
||||
fn as_jvalue(&self) -> Cow<'_, JValue> {
|
||||
|
@ -23,8 +23,8 @@ pub(crate) use joinable::Joinable;
|
||||
use super::Stream;
|
||||
use crate::execution_step::lambda_applier::LambdaError;
|
||||
use crate::JValue;
|
||||
use crate::ToErrorCode;
|
||||
|
||||
use air_interpreter_interface::CallResults;
|
||||
use air_trace_handler::MergerApResult;
|
||||
use air_trace_handler::TraceHandlerError;
|
||||
use strum::IntoEnumIterator;
|
||||
@ -54,10 +54,6 @@ pub(crate) enum ExecutionError {
|
||||
#[error(transparent)]
|
||||
LambdaApplierError(#[from] LambdaError),
|
||||
|
||||
/// An error occurred while trying to apply lambda to an empty stream.
|
||||
#[error("lambda is applied to an empty stream")]
|
||||
EmptyStreamLambdaError,
|
||||
|
||||
/// Provided JValue has incompatible type with a requested one.
|
||||
#[error(
|
||||
"expected JValue type '{expected_value_type}' for the variable `{variable_name}`, but got '{actual_value}'"
|
||||
@ -108,12 +104,6 @@ pub(crate) enum ExecutionError {
|
||||
/// could be applied to a stream, but result doesn't contain generation in a source position.
|
||||
#[error("ap result {0:?} doesn't match corresponding instruction")]
|
||||
ApResultNotCorrespondToInstr(MergerApResult),
|
||||
|
||||
/// Call results should be empty at the end of execution thanks to a execution invariant.
|
||||
#[error(
|
||||
"after finishing execution of supplied AIR, call results aren't empty: `{0:?}`, probably wrong call_id used"
|
||||
)]
|
||||
CallResultsNotEmpty(CallResults),
|
||||
}
|
||||
|
||||
impl From<LambdaError> for Rc<ExecutionError> {
|
||||
@ -131,15 +121,31 @@ macro_rules! trace_to_exec_err {
|
||||
};
|
||||
}
|
||||
|
||||
impl ExecutionError {
|
||||
pub(crate) fn to_error_code(&self) -> u32 {
|
||||
const EXECUTION_ERRORS_START_ID: u32 = 1000;
|
||||
/*
|
||||
impl ToErrorCode for ExecutionError {
|
||||
fn to_error_code(&self) -> i64 {
|
||||
const EXECUTION_ERRORS_START_ID: i64 = 1000;
|
||||
|
||||
let mut errors = ExecutionErrorDiscriminants::iter();
|
||||
let actual_error_type = ExecutionErrorDiscriminants::from(self);
|
||||
|
||||
// unwrap is safe here because errors are guaranteed to contain all errors variants
|
||||
let enum_variant_position = errors.position(|et| et == actual_error_type).unwrap() as u32;
|
||||
let enum_variant_position = errors.position(|et| et == actual_error_type).unwrap() as i64;
|
||||
EXECUTION_ERRORS_START_ID + enum_variant_position
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
impl ToErrorCode for Rc<ExecutionError> {
|
||||
fn to_error_code(&self) -> i64 {
|
||||
const EXECUTION_ERRORS_START_ID: i64 = 1000;
|
||||
|
||||
let mut errors = ExecutionErrorDiscriminants::iter();
|
||||
let actual_error_type = ExecutionErrorDiscriminants::from(self.as_ref());
|
||||
|
||||
// unwrap is safe here because errors are guaranteed to contain all errors variants
|
||||
let enum_variant_position = errors.position(|et| et == actual_error_type).unwrap() as i64;
|
||||
EXECUTION_ERRORS_START_ID + enum_variant_position
|
||||
}
|
||||
}
|
||||
@ -166,7 +172,7 @@ impl Joinable for ExecutionError {
|
||||
log_join!(" waiting for an argument with idx '{}' on stream with size '{}'", idx, stream_size);
|
||||
true
|
||||
}
|
||||
EmptyStreamLambdaError => {
|
||||
LambdaApplierError(LambdaError::EmptyStream) => {
|
||||
log_join!(" waiting on empty stream for path ");
|
||||
true
|
||||
}
|
||||
|
@ -23,6 +23,10 @@ pub(crate) enum LambdaError {
|
||||
#[error("lambda is applied to a stream that have only '{stream_size}' elements, but '{idx}' requested")]
|
||||
StreamNotHaveEnoughValues { stream_size: usize, idx: u32 },
|
||||
|
||||
/// An error occurred while trying to apply lambda to an empty stream.
|
||||
#[error("lambda is applied to an empty stream")]
|
||||
EmptyStream,
|
||||
|
||||
#[error("field accessor (with field name = '{field_name}') can't be applied to a stream")]
|
||||
FieldAccessorAppliedToStream { field_name: String },
|
||||
|
||||
|
@ -19,7 +19,7 @@ mod boxed_value;
|
||||
mod errors;
|
||||
pub(crate) mod execution_context;
|
||||
mod lambda_applier;
|
||||
mod utils;
|
||||
mod resolver;
|
||||
|
||||
pub(super) use self::air::ExecutableInstruction;
|
||||
pub(super) use self::air::FoldState;
|
||||
|
47
air/src/farewell_step/errors.rs
Normal file
47
air/src/farewell_step/errors.rs
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2021 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.
|
||||
*/
|
||||
|
||||
use crate::ToErrorCode;
|
||||
use air_interpreter_interface::CallResults;
|
||||
|
||||
use strum::IntoEnumIterator;
|
||||
use strum_macros::EnumDiscriminants;
|
||||
use strum_macros::EnumIter;
|
||||
use thiserror::Error as ThisError;
|
||||
|
||||
/// Errors happened during the interpreter farewell step.
|
||||
#[derive(Debug, EnumDiscriminants, ThisError)]
|
||||
#[strum_discriminants(derive(EnumIter))]
|
||||
pub enum FarewellError {
|
||||
/// Call results should be empty at the end of execution thanks to a execution invariant.
|
||||
#[error(
|
||||
"after finishing execution of supplied AIR, call results aren't empty: `{0:?}`, probably wrong call_id used"
|
||||
)]
|
||||
CallResultsNotEmpty(CallResults),
|
||||
}
|
||||
|
||||
impl ToErrorCode for FarewellError {
|
||||
fn to_error_code(&self) -> i64 {
|
||||
const FAREWELL_ERRORS_START_ID: i64 = 20000;
|
||||
|
||||
let mut errors = FarewellErrorDiscriminants::iter();
|
||||
let actual_error_type = FarewellErrorDiscriminants::from(self);
|
||||
|
||||
// unwrap is safe here because errors are guaranteed to contain all errors variants
|
||||
let enum_variant_position = errors.position(|et| et == actual_error_type).unwrap() as i64;
|
||||
FAREWELL_ERRORS_START_ID + enum_variant_position
|
||||
}
|
||||
}
|
23
air/src/farewell_step/mod.rs
Normal file
23
air/src/farewell_step/mod.rs
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2021 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.
|
||||
*/
|
||||
|
||||
mod errors;
|
||||
mod outcome;
|
||||
|
||||
pub(crate) use errors::FarewellError;
|
||||
pub(crate) use outcome::from_execution_error;
|
||||
pub(crate) use outcome::from_success_result;
|
||||
pub(crate) use outcome::from_uncatchable_error;
|
@ -14,11 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use super::FarewellError;
|
||||
use crate::execution_step::ExecutionCtx;
|
||||
use crate::execution_step::ExecutionError;
|
||||
use crate::execution_step::TraceHandler;
|
||||
use crate::preparation_step::PreparationError;
|
||||
use crate::InterpreterOutcome;
|
||||
use crate::ToErrorCode;
|
||||
use crate::INTERPRETER_SUCCESS;
|
||||
|
||||
use air_interpreter_data::InterpreterData;
|
||||
@ -29,53 +29,34 @@ use std::rc::Rc;
|
||||
|
||||
/// Create InterpreterOutcome from supplied execution context and trace handler,
|
||||
/// set ret_code to INTERPRETER_SUCCESS.
|
||||
pub(crate) fn from_success_result(exec_ctx: ExecutionCtx<'_>, trace_handler: TraceHandler) -> InterpreterOutcome {
|
||||
let (global_streams, restricted_streams) = exec_ctx.streams.into_streams_data();
|
||||
let data = InterpreterData::from_execution_result(
|
||||
trace_handler.into_result_trace(),
|
||||
global_streams,
|
||||
restricted_streams,
|
||||
exec_ctx.last_call_request_id,
|
||||
);
|
||||
let data = serde_json::to_vec(&data).expect("default serializer shouldn't fail");
|
||||
let next_peer_pks = dedup(exec_ctx.next_peer_pks);
|
||||
let call_requests = serde_json::to_vec(&exec_ctx.call_requests).expect("default serializer shouldn't fail");
|
||||
pub(crate) fn from_success_result(
|
||||
exec_ctx: ExecutionCtx<'_>,
|
||||
trace_handler: TraceHandler,
|
||||
) -> Result<InterpreterOutcome, InterpreterOutcome> {
|
||||
let (ret_code, error_message) = if exec_ctx.call_results.is_empty() {
|
||||
(INTERPRETER_SUCCESS, String::new())
|
||||
} else {
|
||||
let farewell_error = Rc::new(FarewellError::CallResultsNotEmpty(exec_ctx.call_results.clone()));
|
||||
(farewell_error.to_error_code(), farewell_error.to_string())
|
||||
};
|
||||
|
||||
InterpreterOutcome {
|
||||
ret_code: INTERPRETER_SUCCESS,
|
||||
error_message: String::new(),
|
||||
data,
|
||||
next_peer_pks,
|
||||
call_requests,
|
||||
}
|
||||
let outcome = populate_outcome_from_contexts(exec_ctx, trace_handler, ret_code, error_message);
|
||||
Ok(outcome)
|
||||
}
|
||||
|
||||
/// Create InterpreterOutcome from supplied data and error,
|
||||
/// set ret_code based on the error.
|
||||
pub(crate) fn from_preparation_error(data: impl Into<Vec<u8>>, err: PreparationError) -> InterpreterOutcome {
|
||||
let ret_code = err.to_error_code() as i32;
|
||||
pub(crate) fn from_uncatchable_error(
|
||||
data: impl Into<Vec<u8>>,
|
||||
error: impl ToErrorCode + ToString,
|
||||
) -> InterpreterOutcome {
|
||||
let ret_code = error.to_error_code();
|
||||
let data = data.into();
|
||||
let call_requests = serde_json::to_vec(&CallRequests::new()).expect("default serializer shouldn't fail");
|
||||
|
||||
InterpreterOutcome {
|
||||
ret_code,
|
||||
error_message: format!("{}", err),
|
||||
data,
|
||||
next_peer_pks: vec![],
|
||||
call_requests,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create InterpreterOutcome from supplied data and error,
|
||||
/// set ret_code based on the error.
|
||||
pub(crate) fn from_trace_error(data: impl Into<Vec<u8>>, err: Rc<ExecutionError>) -> InterpreterOutcome {
|
||||
let ret_code = err.to_error_code() as i32;
|
||||
let data = data.into();
|
||||
let call_requests = serde_json::to_vec(&CallRequests::new()).expect("default serializer shouldn't fail");
|
||||
|
||||
InterpreterOutcome {
|
||||
ret_code,
|
||||
error_message: format!("{}", err),
|
||||
error_message: error.to_string(),
|
||||
data,
|
||||
next_peer_pks: vec![],
|
||||
call_requests,
|
||||
@ -87,10 +68,17 @@ pub(crate) fn from_trace_error(data: impl Into<Vec<u8>>, err: Rc<ExecutionError>
|
||||
pub(crate) fn from_execution_error(
|
||||
exec_ctx: ExecutionCtx<'_>,
|
||||
trace_handler: TraceHandler,
|
||||
err: Rc<ExecutionError>,
|
||||
error: impl ToErrorCode + ToString,
|
||||
) -> InterpreterOutcome {
|
||||
let ret_code = err.to_error_code() as i32;
|
||||
populate_outcome_from_contexts(exec_ctx, trace_handler, error.to_error_code(), error.to_string())
|
||||
}
|
||||
|
||||
fn populate_outcome_from_contexts(
|
||||
exec_ctx: ExecutionCtx<'_>,
|
||||
trace_handler: TraceHandler,
|
||||
ret_code: i64,
|
||||
error_message: String,
|
||||
) -> InterpreterOutcome {
|
||||
let (global_streams, restricted_streams) = exec_ctx.streams.into_streams_data();
|
||||
let data = InterpreterData::from_execution_result(
|
||||
trace_handler.into_result_trace(),
|
||||
@ -104,7 +92,7 @@ pub(crate) fn from_execution_error(
|
||||
|
||||
InterpreterOutcome {
|
||||
ret_code,
|
||||
error_message: format!("{}", err),
|
||||
error_message,
|
||||
data,
|
||||
next_peer_pks,
|
||||
call_requests,
|
@ -27,8 +27,10 @@
|
||||
)]
|
||||
|
||||
mod execution_step;
|
||||
mod farewell_step;
|
||||
mod preparation_step;
|
||||
mod runner;
|
||||
mod utils;
|
||||
|
||||
pub use air_interpreter_interface::InterpreterOutcome;
|
||||
pub use air_interpreter_interface::RunParameters;
|
||||
@ -53,4 +55,6 @@ pub mod parser {
|
||||
}
|
||||
|
||||
pub(crate) type JValue = serde_json::Value;
|
||||
pub(crate) use utils::ToErrorCode;
|
||||
|
||||
use air_lambda_parser::LambdaAST;
|
||||
|
@ -14,6 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::ToErrorCode;
|
||||
use air_interpreter_data::DATA_FORMAT_VERSION;
|
||||
|
||||
use serde_json::Error as SerdeJsonError;
|
||||
@ -22,7 +23,7 @@ use strum_macros::EnumDiscriminants;
|
||||
use strum_macros::EnumIter;
|
||||
use thiserror::Error as ThisError;
|
||||
|
||||
/// Errors happened during the interpreter preparation_step step.
|
||||
/// Errors happened during the interpreter preparation step.
|
||||
#[derive(Debug, EnumDiscriminants, ThisError)]
|
||||
#[strum_discriminants(derive(EnumIter))]
|
||||
pub enum PreparationError {
|
||||
@ -40,15 +41,15 @@ pub enum PreparationError {
|
||||
CallResultsDeFailed(SerdeJsonError, Vec<u8>),
|
||||
}
|
||||
|
||||
impl PreparationError {
|
||||
pub(crate) fn to_error_code(&self) -> u32 {
|
||||
const PREPARATION_ERRORS_START_ID: u32 = 1;
|
||||
impl ToErrorCode for PreparationError {
|
||||
fn to_error_code(&self) -> i64 {
|
||||
const PREPARATION_ERRORS_START_ID: i64 = 1;
|
||||
|
||||
let mut errors = PreparationErrorDiscriminants::iter();
|
||||
let actual_error_type = PreparationErrorDiscriminants::from(self);
|
||||
|
||||
// unwrap is safe here because errors are guaranteed to contain all errors variants
|
||||
let enum_variant_position = errors.position(|et| et == actual_error_type).unwrap() as u32;
|
||||
let enum_variant_position = errors.position(|et| et == actual_error_type).unwrap() as i64;
|
||||
PREPARATION_ERRORS_START_ID + enum_variant_position
|
||||
}
|
||||
}
|
||||
|
@ -14,13 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
mod outcome;
|
||||
|
||||
use crate::execution_step::Catchable;
|
||||
use crate::execution_step::ExecutableInstruction;
|
||||
use crate::execution_step::ExecutionCtx;
|
||||
use crate::execution_step::ExecutionError;
|
||||
use crate::execution_step::TraceHandler;
|
||||
use crate::farewell_step as farewell;
|
||||
use crate::preparation_step::prepare;
|
||||
use crate::preparation_step::PreparationDescriptor;
|
||||
|
||||
@ -28,8 +24,6 @@ use air_interpreter_interface::InterpreterOutcome;
|
||||
use air_interpreter_interface::RunParameters;
|
||||
use air_log_targets::RUN_PARAMS;
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
pub fn execute_air(
|
||||
air: String,
|
||||
prev_data: Vec<u8>,
|
||||
@ -66,30 +60,16 @@ fn execute_air_impl(
|
||||
} = match prepare(&prev_data, &data, air.as_str(), &call_results, params) {
|
||||
Ok(desc) => desc,
|
||||
// return the initial data in case of errors
|
||||
Err(error) => return Err(outcome::from_preparation_error(prev_data, error)),
|
||||
Err(error) => return Err(farewell::from_uncatchable_error(prev_data, error)),
|
||||
};
|
||||
|
||||
// match here is used instead of map_err, because the compiler can't determine that
|
||||
// they are exclusive and would treat exec_ctx and trace_handler as moved
|
||||
match air.execute(&mut exec_ctx, &mut trace_handler) {
|
||||
Ok(_) => try_make_outcome(exec_ctx, trace_handler),
|
||||
// return the old data in case of any trace errors
|
||||
Err(e) if !e.is_catchable() => Err(outcome::from_trace_error(prev_data, e)),
|
||||
Ok(_) => farewell::from_success_result(exec_ctx, trace_handler),
|
||||
// return new collected trace in case of errors
|
||||
Err(e) => Err(outcome::from_execution_error(exec_ctx, trace_handler, e)),
|
||||
Err(error) if error.is_catchable() => Err(farewell::from_execution_error(exec_ctx, trace_handler, error)),
|
||||
// return the old data in case of any trace errors
|
||||
Err(error) => Err(farewell::from_uncatchable_error(prev_data, error)),
|
||||
}
|
||||
}
|
||||
|
||||
fn try_make_outcome(
|
||||
exec_ctx: ExecutionCtx<'_>,
|
||||
trace_handler: TraceHandler,
|
||||
) -> Result<InterpreterOutcome, InterpreterOutcome> {
|
||||
if exec_ctx.call_results.is_empty() {
|
||||
let outcome = outcome::from_success_result(exec_ctx, trace_handler);
|
||||
return Ok(outcome);
|
||||
}
|
||||
|
||||
let exec_error = Rc::new(ExecutionError::CallResultsNotEmpty(exec_ctx.call_results.clone()));
|
||||
let outcome = outcome::from_execution_error(exec_ctx, trace_handler, exec_error);
|
||||
Err(outcome)
|
||||
}
|
||||
|
19
air/src/utils/mod.rs
Normal file
19
air/src/utils/mod.rs
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2021 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.
|
||||
*/
|
||||
|
||||
mod to_error_code;
|
||||
|
||||
pub(crate) use to_error_code::ToErrorCode;
|
37
air/src/utils/to_error_code.rs
Normal file
37
air/src/utils/to_error_code.rs
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2021 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(crate) trait ToErrorCode {
|
||||
fn to_error_code(&self) -> i64;
|
||||
}
|
||||
|
||||
/*
|
||||
use concat_idents::concat_idents;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! generate_to_error_code {
|
||||
($error_type:ident, $start_id: ident) => {
|
||||
const PREPARATION_ERRORS_START_ID: u32 = $start_id;
|
||||
|
||||
let mut errors = PreparationErrorDiscriminants::iter();
|
||||
let actual_error_type = PreparationErrorDiscriminants::from(self);
|
||||
|
||||
// unwrap is safe here because errors are guaranteed to contain all errors variants
|
||||
let enum_variant_position = errors.position(|et| et == actual_error_type).unwrap() as i64;
|
||||
PREPARATION_ERRORS_START_ID + enum_variant_position
|
||||
}
|
||||
}
|
||||
*/
|
@ -16,7 +16,7 @@ name = "avm_server"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
air-interpreter-interface = { version = "0.7.0", path = "../../crates/air-lib/interpreter-interface" }
|
||||
air-interpreter-interface = { version = "0.8.0", path = "../../crates/air-lib/interpreter-interface" }
|
||||
avm-data-store = { version = "0.1.0", path = "../../crates/data-store" }
|
||||
fluence-faas = "0.10.0"
|
||||
polyplets = { version = "0.2.0", path = "../../crates/air-lib/polyplets" }
|
||||
|
@ -37,7 +37,7 @@ pub struct AVMOutcome {
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct ErrorAVMOutcome {
|
||||
pub error_code: i32,
|
||||
pub error_code: i64,
|
||||
pub error_message: String,
|
||||
pub outcome: AVMOutcome,
|
||||
}
|
||||
@ -78,7 +78,7 @@ impl AVMOutcome {
|
||||
}
|
||||
|
||||
impl ErrorAVMOutcome {
|
||||
pub(self) fn new(error_code: i32, error_msg: String, outcome: AVMOutcome) -> Self {
|
||||
pub(self) fn new(error_code: i64, error_msg: String, outcome: AVMOutcome) -> Self {
|
||||
Self {
|
||||
error_code,
|
||||
error_message: error_msg,
|
||||
|
@ -25,7 +25,7 @@ use serde::Serialize;
|
||||
/// This struct is very similar to AVMOutcome, but keeps error_code and error_msg for test purposes.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct RawAVMOutcome {
|
||||
pub ret_code: i32,
|
||||
pub ret_code: i64,
|
||||
pub error_message: String,
|
||||
pub data: Vec<u8>,
|
||||
pub call_requests: CallRequests,
|
||||
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "air-interpreter-interface"
|
||||
description = "Interface of the AIR interpreter"
|
||||
version = "0.7.0"
|
||||
version = "0.8.0"
|
||||
authors = ["Fluence Labs"]
|
||||
edition = "2018"
|
||||
license = "Apache-2.0"
|
||||
|
@ -20,14 +20,14 @@ use fluence_it_types::IValue;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
pub const INTERPRETER_SUCCESS: i32 = 0;
|
||||
pub const INTERPRETER_SUCCESS: i64 = 0;
|
||||
|
||||
/// Describes a result returned at the end of the interpreter execution_step.
|
||||
#[marine]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct InterpreterOutcome {
|
||||
/// A return code, where INTERPRETER_SUCCESS means success.
|
||||
pub ret_code: i32,
|
||||
pub ret_code: i64,
|
||||
|
||||
/// Contains error message if ret_code != INTERPRETER_SUCCESS.
|
||||
pub error_message: String,
|
||||
@ -59,7 +59,7 @@ impl InterpreterOutcome {
|
||||
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 error_message = try_as_string(record_values.pop().unwrap(), "error_message")?;
|
||||
let ret_code = try_as_i32(record_values.pop().unwrap(), "ret_code")?;
|
||||
let ret_code = try_as_i64(record_values.pop().unwrap(), "ret_code")?;
|
||||
|
||||
let outcome = Self {
|
||||
ret_code,
|
||||
@ -87,10 +87,10 @@ fn try_as_record(ivalue: IValue) -> Result<NEVec<IValue>, String> {
|
||||
}
|
||||
}
|
||||
|
||||
fn try_as_i32(ivalue: IValue, field_name: &str) -> Result<i32, String> {
|
||||
fn try_as_i64(ivalue: IValue, field_name: &str) -> Result<i64, String> {
|
||||
match ivalue {
|
||||
IValue::S32(value) => Ok(value),
|
||||
v => return Err(format!("expected an i32 for {}, got {:?}", field_name, v)),
|
||||
IValue::S64(value) => Ok(value),
|
||||
v => return Err(format!("expected an i64 for {}, got {:?}", field_name, v)),
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user