Decouple trace handler (#150)

This commit is contained in:
Mike Voronov 2021-10-05 14:07:38 +03:00 committed by GitHub
parent 37ed77cb81
commit adba9e8e65
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 212 additions and 117 deletions

12
Cargo.lock generated
View File

@ -19,6 +19,7 @@ dependencies = [
"air-interpreter-interface", "air-interpreter-interface",
"air-parser", "air-parser",
"air-test-utils", "air-test-utils",
"air-trace-handler",
"boolinator", "boolinator",
"criterion", "criterion",
"csv", "csv",
@ -107,6 +108,17 @@ dependencies = [
"serde_json", "serde_json",
] ]
[[package]]
name = "air-trace-handler"
version = "0.1.0"
dependencies = [
"air-interpreter-data",
"air-parser",
"log",
"serde_json",
"thiserror",
]
[[package]] [[package]]
name = "ansi_term" name = "ansi_term"
version = "0.11.0" version = "0.11.0"

View File

@ -9,6 +9,7 @@ members = [
"crates/interpreter-data", "crates/interpreter-data",
"crates/test-module", "crates/test-module",
"crates/test-utils", "crates/test-utils",
"crates/trace-handler",
"avm/server", "avm/server",
] ]

View File

@ -12,10 +12,11 @@ doctest = false
[dependencies] [dependencies]
air-parser = { path = "../crates/air-parser" } air-parser = { path = "../crates/air-parser" }
polyplets = { path = "../crates/polyplets" }
air-interpreter-data = { path = "../crates/interpreter-data" } air-interpreter-data = { path = "../crates/interpreter-data" }
air-interpreter-interface = { path = "../crates/interpreter-interface" } air-interpreter-interface = { path = "../crates/interpreter-interface" }
air-trace-handler = { path = "../crates/trace-handler" }
marine-rs-sdk = { version = "0.6.11", features = ["logger"] } marine-rs-sdk = { version = "0.6.11", features = ["logger"] }
polyplets = { path = "../crates/polyplets" }
serde = { version = "1.0.118", features = [ "derive", "rc" ] } serde = { version = "1.0.118", features = [ "derive", "rc" ] }
serde_json = "1.0.61" serde_json = "1.0.61"

View File

@ -24,8 +24,8 @@ use super::ExecutionResult;
use super::TraceHandler; use super::TraceHandler;
use crate::execution_step::air::ResolvedCallResult; use crate::execution_step::air::ResolvedCallResult;
use crate::execution_step::boxed_value::Variable; use crate::execution_step::boxed_value::Variable;
use crate::execution_step::trace_handler::MergerApResult;
use crate::execution_step::utils::apply_json_path; use crate::execution_step::utils::apply_json_path;
use crate::trace_to_exec_err;
use crate::JValue; use crate::JValue;
use crate::SecurityTetraplet; use crate::SecurityTetraplet;
use apply_to_arguments::*; use apply_to_arguments::*;
@ -35,6 +35,7 @@ use air_parser::ast::ApArgument;
use air_parser::ast::AstVariable; use air_parser::ast::AstVariable;
use air_parser::ast::JsonPath; use air_parser::ast::JsonPath;
use air_parser::ast::{Ap, LastErrorPath}; use air_parser::ast::{Ap, LastErrorPath};
use air_trace_handler::MergerApResult;
use std::cell::RefCell; use std::cell::RefCell;
use std::rc::Rc; use std::rc::Rc;
@ -44,7 +45,7 @@ impl<'i> super::ExecutableInstruction<'i> for Ap<'i> {
let should_touch_trace = should_touch_trace(self); let should_touch_trace = should_touch_trace(self);
let merger_ap_result = if should_touch_trace { let merger_ap_result = if should_touch_trace {
let merger_ap_result = trace_ctx.meet_ap_start()?; let merger_ap_result = trace_to_exec_err!(trace_ctx.meet_ap_start())?;
try_match_result_to_instr(&merger_ap_result, self)?; try_match_result_to_instr(&merger_ap_result, self)?;
merger_ap_result merger_ap_result
} else { } else {

View File

@ -16,12 +16,12 @@
use super::ExecutionCtx; use super::ExecutionCtx;
use super::ExecutionResult; use super::ExecutionResult;
use crate::execution_step::trace_handler::MergerApResult;
use crate::execution_step::Generation; use crate::execution_step::Generation;
use air_interpreter_data::ApResult; use air_interpreter_data::ApResult;
use air_parser::ast::Ap; use air_parser::ast::Ap;
use air_parser::ast::AstVariable; use air_parser::ast::AstVariable;
use air_trace_handler::MergerApResult;
pub(super) fn ap_result_to_generation(ap_result: &MergerApResult) -> Generation { pub(super) fn ap_result_to_generation(ap_result: &MergerApResult) -> Generation {
match ap_result { match ap_result {

View File

@ -17,7 +17,6 @@
use super::*; use super::*;
use crate::exec_err; use crate::exec_err;
use crate::execution_step::execution_context::*; use crate::execution_step::execution_context::*;
use crate::execution_step::trace_handler::TraceHandler;
use crate::execution_step::AstVariable; use crate::execution_step::AstVariable;
use crate::execution_step::Generation; use crate::execution_step::Generation;
use crate::execution_step::ResolvedCallResult; use crate::execution_step::ResolvedCallResult;
@ -27,6 +26,7 @@ use crate::execution_step::Stream;
use air_interpreter_data::CallResult; use air_interpreter_data::CallResult;
use air_interpreter_data::Value; use air_interpreter_data::Value;
use air_parser::ast::CallOutputValue; use air_parser::ast::CallOutputValue;
use air_trace_handler::TraceHandler;
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::collections::hash_map::Entry::{Occupied, Vacant};

View File

@ -17,13 +17,13 @@
use super::*; use super::*;
use crate::exec_err; use crate::exec_err;
use crate::execution_step::air::call::call_result_setter::set_result_from_value; use crate::execution_step::air::call::call_result_setter::set_result_from_value;
use crate::execution_step::trace_handler::TraceHandler;
use crate::execution_step::RSecurityTetraplet; use crate::execution_step::RSecurityTetraplet;
use air_interpreter_data::CallResult; use air_interpreter_data::CallResult;
use air_interpreter_data::Sender; use air_interpreter_data::Sender;
use air_interpreter_interface::CallServiceResult; use air_interpreter_interface::CallServiceResult;
use air_parser::ast::CallOutputValue; use air_parser::ast::CallOutputValue;
use air_trace_handler::TraceHandler;
/// This function looks at the existing call state, validates it, /// This function looks at the existing call state, validates it,
/// and returns Ok(true) if the call should be executed further. /// and returns Ok(true) if the call should be executed further.

View File

@ -20,16 +20,17 @@ use super::call_result_setter::*;
use super::prev_result_handler::*; use super::prev_result_handler::*;
use super::triplet::Triplet; use super::triplet::Triplet;
use super::*; use super::*;
use crate::execution_step::trace_handler::MergerCallResult;
use crate::execution_step::trace_handler::TraceHandler;
use crate::execution_step::RSecurityTetraplet; use crate::execution_step::RSecurityTetraplet;
use crate::execution_step::SecurityTetraplets; use crate::execution_step::SecurityTetraplets;
use crate::trace_to_exec_err;
use crate::JValue; use crate::JValue;
use crate::SecurityTetraplet; use crate::SecurityTetraplet;
use air_interpreter_data::CallResult; use air_interpreter_data::CallResult;
use air_interpreter_interface::CallRequestParams; use air_interpreter_interface::CallRequestParams;
use air_parser::ast::{AstVariable, CallInstrArgValue, CallOutputValue}; use air_parser::ast::{AstVariable, CallInstrArgValue, CallOutputValue};
use air_trace_handler::MergerCallResult;
use air_trace_handler::TraceHandler;
use polyplets::ResolvedTriplet; use polyplets::ResolvedTriplet;
use std::cell::RefCell; use std::cell::RefCell;
@ -125,7 +126,7 @@ impl<'i> ResolvedCall<'i> {
exec_ctx: &mut ExecutionCtx<'i>, exec_ctx: &mut ExecutionCtx<'i>,
trace_ctx: &mut TraceHandler, trace_ctx: &mut TraceHandler,
) -> ExecutionResult<bool> { ) -> ExecutionResult<bool> {
let (call_result, trace_pos) = match trace_ctx.meet_call_start(&self.output)? { let (call_result, trace_pos) = match trace_to_exec_err!(trace_ctx.meet_call_start(&self.output))? {
MergerCallResult::CallResult { value, trace_pos } => (value, trace_pos), MergerCallResult::CallResult { value, trace_pos } => (value, trace_pos),
MergerCallResult::Empty => return Ok(true), MergerCallResult::Empty => return Ok(true),
}; };

View File

@ -21,6 +21,7 @@ use super::ExecutionCtx;
use super::ExecutionResult; use super::ExecutionResult;
use super::TraceHandler; use super::TraceHandler;
use crate::log_instruction; use crate::log_instruction;
use crate::trace_to_exec_err;
use air_parser::ast::FoldStream; use air_parser::ast::FoldStream;
@ -34,7 +35,7 @@ impl<'i> ExecutableInstruction<'i> for FoldStream<'i> {
}; };
let fold_id = exec_ctx.tracker.fold.seen_stream_count; let fold_id = exec_ctx.tracker.fold.seen_stream_count;
trace_ctx.meet_fold_start(fold_id)?; trace_to_exec_err!(trace_ctx.meet_fold_start(fold_id))?;
for iterable in iterables { for iterable in iterables {
let value = match iterable.peek() { let value = match iterable.peek() {
@ -45,7 +46,7 @@ impl<'i> ExecutableInstruction<'i> for FoldStream<'i> {
}; };
let value_pos = value.pos(); let value_pos = value.pos();
trace_ctx.meet_iteration_start(fold_id, value_pos)?; trace_to_exec_err!(trace_ctx.meet_iteration_start(fold_id, value_pos))?;
fold( fold(
iterable, iterable,
IterableType::Stream(fold_id), IterableType::Stream(fold_id),
@ -54,14 +55,14 @@ impl<'i> ExecutableInstruction<'i> for FoldStream<'i> {
exec_ctx, exec_ctx,
trace_ctx, trace_ctx,
)?; )?;
trace_ctx.meet_generation_end(fold_id)?; trace_to_exec_err!(trace_ctx.meet_generation_end(fold_id))?;
if !exec_ctx.subtree_complete { if !exec_ctx.subtree_complete {
break; break;
} }
} }
trace_ctx.meet_fold_end(fold_id)?; trace_to_exec_err!(trace_ctx.meet_fold_end(fold_id))?;
Ok(()) Ok(())
} }

View File

@ -23,6 +23,7 @@ use super::Scalar;
use super::TraceHandler; use super::TraceHandler;
use crate::exec_err; use crate::exec_err;
use crate::log_instruction; use crate::log_instruction;
use crate::trace_to_exec_err;
use air_parser::ast::Next; use air_parser::ast::Next;
@ -89,7 +90,7 @@ fn try_get_fold_state<'i, 'ctx>(
fn maybe_meet_iteration_start(fold_state: &FoldState<'_>, trace_ctx: &mut TraceHandler) -> ExecutionResult<()> { fn maybe_meet_iteration_start(fold_state: &FoldState<'_>, trace_ctx: &mut TraceHandler) -> ExecutionResult<()> {
if let IterableType::Stream(fold_id) = &fold_state.iterable_type { if let IterableType::Stream(fold_id) = &fold_state.iterable_type {
trace_ctx.meet_iteration_start(*fold_id, fold_state.iterable.peek().unwrap().pos())?; trace_to_exec_err!(trace_ctx.meet_iteration_start(*fold_id, fold_state.iterable.peek().unwrap().pos()))?;
} }
Ok(()) Ok(())
@ -97,7 +98,7 @@ fn maybe_meet_iteration_start(fold_state: &FoldState<'_>, trace_ctx: &mut TraceH
fn maybe_meet_iteration_end(fold_state: &FoldState<'_>, trace_ctx: &mut TraceHandler) -> ExecutionResult<()> { fn maybe_meet_iteration_end(fold_state: &FoldState<'_>, trace_ctx: &mut TraceHandler) -> ExecutionResult<()> {
if let IterableType::Stream(fold_id) = &fold_state.iterable_type { if let IterableType::Stream(fold_id) = &fold_state.iterable_type {
trace_ctx.meet_iteration_end(*fold_id)?; trace_to_exec_err!(trace_ctx.meet_iteration_end(*fold_id))?;
} }
Ok(()) Ok(())
@ -105,7 +106,7 @@ fn maybe_meet_iteration_end(fold_state: &FoldState<'_>, trace_ctx: &mut TraceHan
fn maybe_meet_back_iterator(fold_state: &FoldState<'_>, trace_ctx: &mut TraceHandler) -> ExecutionResult<()> { fn maybe_meet_back_iterator(fold_state: &FoldState<'_>, trace_ctx: &mut TraceHandler) -> ExecutionResult<()> {
if let IterableType::Stream(fold_id) = &fold_state.iterable_type { if let IterableType::Stream(fold_id) = &fold_state.iterable_type {
trace_ctx.meet_back_iterator(*fold_id)?; trace_to_exec_err!(trace_ctx.meet_back_iterator(*fold_id))?;
} }
Ok(()) Ok(())

View File

@ -23,11 +23,13 @@ use super::ExecutionError;
use super::ExecutionResult; use super::ExecutionResult;
use super::Instruction; use super::Instruction;
use super::TraceHandler; use super::TraceHandler;
use crate::execution_step::trace_handler::SubtreeType;
use crate::log_instruction; use crate::log_instruction;
use crate::trace_to_exec_err;
use completeness_updater::ParCompletenessUpdater; use completeness_updater::ParCompletenessUpdater;
use air_parser::ast::Par; use air_parser::ast::Par;
use air_trace_handler::SubtreeType;
use std::rc::Rc; use std::rc::Rc;
#[rustfmt::skip] #[rustfmt::skip]
@ -36,7 +38,7 @@ impl<'i> ExecutableInstruction<'i> for Par<'i> {
log_instruction!(par, exec_ctx, trace_ctx); log_instruction!(par, exec_ctx, trace_ctx);
let mut completeness_updater = ParCompletenessUpdater::new(); let mut completeness_updater = ParCompletenessUpdater::new();
trace_ctx.meet_par_start()?; trace_to_exec_err!(trace_ctx.meet_par_start())?;
// execute a left subtree of par // execute a left subtree of par
let left_result = execute_subtree(&self.0, exec_ctx, trace_ctx, &mut completeness_updater, SubtreeType::Left)?; let left_result = execute_subtree(&self.0, exec_ctx, trace_ctx, &mut completeness_updater, SubtreeType::Left)?;
@ -62,14 +64,14 @@ fn execute_subtree<'i>(
// execute a subtree // execute a subtree
let result = match subtree.execute(exec_ctx, trace_ctx) { let result = match subtree.execute(exec_ctx, trace_ctx) {
Ok(_) => { Ok(_) => {
trace_ctx.meet_par_subtree_end(subtree_type)?; trace_to_exec_err!(trace_ctx.meet_par_subtree_end(subtree_type))?;
SubtreeResult::Succeeded SubtreeResult::Succeeded
} }
Err(e) if !e.is_catchable() => { Err(e) if !e.is_catchable() => {
return Err(e); return Err(e);
} }
Err(e) => { Err(e) => {
trace_ctx.meet_par_subtree_end(subtree_type)?; trace_to_exec_err!(trace_ctx.meet_par_subtree_end(subtree_type))?;
SubtreeResult::Failed(e) SubtreeResult::Failed(e)
} }
}; };

View File

@ -20,13 +20,13 @@ mod joinable;
pub(crate) use catchable::Catchable; pub(crate) use catchable::Catchable;
pub(crate) use joinable::Joinable; pub(crate) use joinable::Joinable;
use super::trace_handler::MergerApResult;
use super::trace_handler::TraceHandlerError;
use super::ResolvedCallResult; use super::ResolvedCallResult;
use super::Stream; use super::Stream;
use crate::JValue; use crate::JValue;
use air_interpreter_interface::CallResults; use air_interpreter_interface::CallResults;
use air_trace_handler::MergerApResult;
use air_trace_handler::TraceHandlerError;
use jsonpath_lib::JsonPathError; use jsonpath_lib::JsonPathError;
use strum::IntoEnumIterator; use strum::IntoEnumIterator;
use strum_macros::EnumDiscriminants; use strum_macros::EnumDiscriminants;
@ -35,7 +35,7 @@ use thiserror::Error as ThisError;
use std::rc::Rc; use std::rc::Rc;
/// Errors arised while executing AIR script. /// Errors arisen while executing AIR script.
#[derive(ThisError, EnumDiscriminants, Debug)] #[derive(ThisError, EnumDiscriminants, Debug)]
#[strum_discriminants(derive(EnumIter))] #[strum_discriminants(derive(EnumIter))]
pub(crate) enum ExecutionError { pub(crate) enum ExecutionError {
@ -134,10 +134,13 @@ pub(crate) enum ExecutionError {
CallResultsNotEmpty(CallResults), CallResultsNotEmpty(CallResults),
} }
impl From<TraceHandlerError> for Rc<ExecutionError> { /// This macro is needed because it's impossible to implement
fn from(trace_error: TraceHandlerError) -> Self { /// From<TraceHandlerError> for Rc<ExecutionError> due to the orphan rule.
Rc::new(ExecutionError::TraceError(trace_error)) #[macro_export]
} macro_rules! trace_to_exec_err {
($trace_expr: expr) => {
$trace_expr.map_err(|e| std::rc::Rc::new(crate::execution_step::ExecutionError::TraceError(e)))
};
} }
impl ExecutionError { impl ExecutionError {

View File

@ -18,7 +18,6 @@ mod air;
mod boxed_value; mod boxed_value;
mod errors; mod errors;
pub(crate) mod execution_context; pub(crate) mod execution_context;
mod trace_handler;
mod utils; mod utils;
pub(super) use self::air::ExecutableInstruction; pub(super) use self::air::ExecutableInstruction;
@ -31,7 +30,8 @@ pub(crate) use errors::Catchable;
pub(super) use errors::ExecutionError; pub(super) use errors::ExecutionError;
pub(crate) use errors::Joinable; pub(crate) use errors::Joinable;
pub(crate) use execution_context::ExecutionCtx; pub(crate) use execution_context::ExecutionCtx;
pub(crate) use trace_handler::TraceHandler;
pub(crate) use air_trace_handler::TraceHandler;
use std::cell::RefCell; use std::cell::RefCell;
use std::rc::Rc; use std::rc::Rc;

View File

@ -0,0 +1 @@
max_width = 120

View File

@ -0,0 +1,23 @@
[package]
name = "air-trace-handler"
version = "0.1.0"
description = "Implementation of AIR trace handler"
authors = ["Fluence Labs"]
edition = "2018"
license = "Apache-2.0"
repository = "https://github.com/fluencelabs/air/crates/trace-handler"
publish = false
keywords = ["fluence", "air", "webassembly", "programming-language"]
categories = ["wasm"]
[lib]
name = "air_trace_handler"
path = "src/lib.rs"
[dependencies]
air-interpreter-data = { path = "../interpreter-data" }
air-parser = { path = "../air-parser" }
serde_json = "1.0.68"
log = "0.4.14"
thiserror = "1.0.29"

View File

@ -0,0 +1,41 @@
## AIR trace handler
This crate contains implementation of the CRDT-based merging data algorithm. It exposes the `TraceHandler` struct that based on the visitor pattern and has public methods that should be called in certain places of AIR instructions execution. Internally `TraceHandler` contains several FSM and each such public methods do state transitioning of one or more these FSMs. Below are state transition sequences for all instructions that caller must follow.
### Ap instruction
Expected sequence of `TraceHandler` calls for the `ap` instruction:
```
meet_ap_start
-> meet_ap_end
```
### Call instruction
Expected sequence of `TraceHandler` calls for the `call` instruction:
```
meet_call_start
-> meet_call_end
```
### Par instruction
Expected sequence of `TraceHandler` calls for the `par` instruction:
```
meet_par_start
-> meet_par_subtree_end(..., SubtreeType::Left)
-> meet_par_subtree_end(..., SubtreeType::Right)
```
### Fold instruction
Expected sequence of `TraceHandler` calls for the `fold` instruction:
```
meet_fold_start.1 ->
meet_generation_start.N ->
meet_next.M ->
meet_prev.M ->
meet_generation_end.N ->
meet_fold_end.1
```
where .T means that this function should be called exactly T times.

View File

@ -19,7 +19,7 @@ use thiserror::Error as ThisError;
/// Errors arose out while accessing various interpreter data. /// Errors arose out while accessing various interpreter data.
#[derive(ThisError, Debug, PartialEq, Eq)] #[derive(ThisError, Debug, PartialEq, Eq)]
pub(crate) enum KeeperError { pub enum KeeperError {
/// Errors occurred when trace_len - trace_position < requested_subtrace_len. /// Errors occurred when trace_len - trace_position < requested_subtrace_len.
#[error( #[error(
"executed trace has {trace_len} elements and current position is {trace_position}, \ "executed trace has {trace_len} elements and current position is {trace_position}, \

View File

@ -26,9 +26,9 @@ use std::collections::HashMap;
/// Contains all necessary information about data. /// Contains all necessary information about data.
#[derive(Debug, Default, PartialEq)] #[derive(Debug, Default, PartialEq)]
pub(crate) struct MergeCtx { pub struct MergeCtx {
pub(crate) slider: TraceSlider, pub slider: TraceSlider,
pub(crate) streams: StreamGenerations, pub streams: StreamGenerations,
} }
impl MergeCtx { impl MergeCtx {

View File

@ -19,11 +19,12 @@ mod keeper;
mod merge_ctx; mod merge_ctx;
mod trace_slider; mod trace_slider;
pub(crate) use errors::KeeperError; pub use errors::KeeperError;
pub use merge_ctx::MergeCtx;
pub use trace_slider::TraceSlider;
pub(crate) use keeper::DataKeeper; pub(crate) use keeper::DataKeeper;
pub(crate) use keeper::DataPositions; pub(crate) use keeper::DataPositions;
pub(super) use merge_ctx::MergeCtx;
pub(super) use trace_slider::TraceSlider;
pub(self) type KeeperResult<T> = std::result::Result<T, KeeperError>; pub(self) type KeeperResult<T> = std::result::Result<T, KeeperError>;

View File

@ -23,7 +23,7 @@ use super::KeeperResult;
/// is identified by position and len. /// is identified by position and len.
// TODO: check for overflow // TODO: check for overflow
#[derive(Debug, Default, Clone, PartialEq, Eq)] #[derive(Debug, Default, Clone, PartialEq, Eq)]
pub(crate) struct TraceSlider { pub struct TraceSlider {
/// Trace that slider slide on. /// Trace that slider slide on.
trace: ExecutionTrace, trace: ExecutionTrace,

View File

@ -23,7 +23,7 @@ use thiserror::Error as ThisError;
/// Errors arose out of merging previous data with a new. /// Errors arose out of merging previous data with a new.
#[derive(ThisError, Debug)] #[derive(ThisError, Debug)]
#[allow(clippy::enum_variant_names)] #[allow(clippy::enum_variant_names)]
pub(crate) enum TraceHandlerError { pub enum TraceHandlerError {
#[error(transparent)] #[error(transparent)]
KeeperError(#[from] KeeperError), KeeperError(#[from] KeeperError),

View File

@ -15,20 +15,19 @@
*/ */
use super::*; use super::*;
use crate::log_targets::EXECUTED_STATE_CHANGING;
use merger::*; use merger::*;
use air_interpreter_data::InterpreterData; use air_interpreter_data::InterpreterData;
use air_parser::ast::CallOutputValue; use air_parser::ast::CallOutputValue;
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub(crate) struct TraceHandler { pub struct TraceHandler {
pub(crate) data_keeper: DataKeeper, data_keeper: DataKeeper,
fsm_keeper: FSMKeeper, fsm_keeper: FSMKeeper,
} }
impl TraceHandler { impl TraceHandler {
pub(crate) fn from_data(prev_data: InterpreterData, current_data: InterpreterData) -> Self { pub fn from_data(prev_data: InterpreterData, current_data: InterpreterData) -> Self {
let data_keeper = DataKeeper::from_data(prev_data, current_data); let data_keeper = DataKeeper::from_data(prev_data, current_data);
Self { Self {
@ -39,19 +38,19 @@ impl TraceHandler {
/// Returns size of elements inside result trace and intended to provide /// Returns size of elements inside result trace and intended to provide
/// a position of next inserted elements. /// a position of next inserted elements.
pub(crate) fn trace_pos(&self) -> usize { pub fn trace_pos(&self) -> usize {
self.data_keeper.result_trace.len() self.data_keeper.result_trace.len()
} }
pub(crate) fn into_result_trace(self) -> ExecutionTrace { pub fn into_result_trace(self) -> ExecutionTrace {
self.data_keeper.result_trace self.data_keeper.result_trace
} }
pub(crate) fn as_result_trace(&self) -> &ExecutionTrace { pub fn as_result_trace(&self) -> &ExecutionTrace {
&self.data_keeper.result_trace &self.data_keeper.result_trace
} }
pub(crate) fn subtree_sizes(&self) -> (usize, usize) { pub fn subtree_sizes(&self) -> (usize, usize) {
let prev_len = self.data_keeper.prev_slider().subtrace_len(); let prev_len = self.data_keeper.prev_slider().subtrace_len();
let current_len = self.data_keeper.current_slider().subtrace_len(); let current_len = self.data_keeper.current_slider().subtrace_len();
@ -61,18 +60,15 @@ impl TraceHandler {
impl TraceHandler { impl TraceHandler {
/// Should be called at the beginning of a call execution. /// Should be called at the beginning of a call execution.
pub(crate) fn meet_call_start( pub fn meet_call_start(&mut self, output_value: &CallOutputValue<'_>) -> TraceHandlerResult<MergerCallResult> {
&mut self,
output_value: &CallOutputValue<'_>,
) -> TraceHandlerResult<MergerCallResult> {
try_merge_next_state_as_call(&mut self.data_keeper, output_value).map_err(Into::into) try_merge_next_state_as_call(&mut self.data_keeper, output_value).map_err(Into::into)
} }
/// Should be called when a call instruction was executed successfully. It adds the supplied /// Should be called when a call instruction was executed successfully. It adds the supplied
/// state to the result trace. /// state to the result trace.
pub(crate) fn meet_call_end(&mut self, call_result: CallResult) { pub fn meet_call_end(&mut self, call_result: CallResult) {
log::trace!( log::trace!(
target: EXECUTED_STATE_CHANGING, target: crate::EXECUTED_STATE_CHANGING,
" adding new call executed state {:?}", " adding new call executed state {:?}",
call_result call_result
); );
@ -81,17 +77,17 @@ impl TraceHandler {
} }
impl TraceHandler { impl TraceHandler {
pub(crate) fn meet_ap_start(&mut self) -> TraceHandlerResult<MergerApResult> { pub fn meet_ap_start(&mut self) -> TraceHandlerResult<MergerApResult> {
try_merge_next_state_as_ap(&mut self.data_keeper).map_err(Into::into) try_merge_next_state_as_ap(&mut self.data_keeper).map_err(Into::into)
} }
pub(crate) fn meet_ap_end(&mut self, ap_result: ApResult) { pub fn meet_ap_end(&mut self, ap_result: ApResult) {
self.data_keeper.result_trace.push(ExecutedState::Ap(ap_result)); self.data_keeper.result_trace.push(ExecutedState::Ap(ap_result));
} }
} }
impl TraceHandler { impl TraceHandler {
pub(crate) fn meet_par_start(&mut self) -> TraceHandlerResult<()> { pub fn meet_par_start(&mut self) -> TraceHandlerResult<()> {
let ingredients = merger::try_merge_next_state_as_par(&mut self.data_keeper)?; let ingredients = merger::try_merge_next_state_as_par(&mut self.data_keeper)?;
let par_fsm = ParFSM::from_left_started(ingredients, &mut self.data_keeper)?; let par_fsm = ParFSM::from_left_started(ingredients, &mut self.data_keeper)?;
self.fsm_keeper.push_par(par_fsm); self.fsm_keeper.push_par(par_fsm);
@ -99,7 +95,7 @@ impl TraceHandler {
Ok(()) Ok(())
} }
pub(crate) fn meet_par_subtree_end(&mut self, subtree_type: SubtreeType) -> TraceHandlerResult<()> { pub fn meet_par_subtree_end(&mut self, subtree_type: SubtreeType) -> TraceHandlerResult<()> {
match subtree_type { match subtree_type {
SubtreeType::Left => { SubtreeType::Left => {
let par_fsm = self.fsm_keeper.last_par()?; let par_fsm = self.fsm_keeper.last_par()?;
@ -116,7 +112,7 @@ impl TraceHandler {
} }
impl TraceHandler { impl TraceHandler {
pub(crate) fn meet_fold_start(&mut self, fold_id: u32) -> TraceHandlerResult<()> { pub fn meet_fold_start(&mut self, fold_id: u32) -> TraceHandlerResult<()> {
let ingredients = try_merge_next_state_as_fold(&mut self.data_keeper)?; let ingredients = try_merge_next_state_as_fold(&mut self.data_keeper)?;
let fold_fsm = FoldFSM::from_fold_start(ingredients, &mut self.data_keeper)?; let fold_fsm = FoldFSM::from_fold_start(ingredients, &mut self.data_keeper)?;
self.fsm_keeper.add_fold(fold_id, fold_fsm); self.fsm_keeper.add_fold(fold_id, fold_fsm);
@ -124,42 +120,42 @@ impl TraceHandler {
Ok(()) Ok(())
} }
pub(crate) fn meet_iteration_start(&mut self, fold_id: u32, value_pos: usize) -> TraceHandlerResult<()> { pub fn meet_iteration_start(&mut self, fold_id: u32, value_pos: usize) -> TraceHandlerResult<()> {
let fold_fsm = self.fsm_keeper.fold_mut(fold_id)?; let fold_fsm = self.fsm_keeper.fold_mut(fold_id)?;
fold_fsm.meet_iteration_start(value_pos, &mut self.data_keeper)?; fold_fsm.meet_iteration_start(value_pos, &mut self.data_keeper)?;
Ok(()) Ok(())
} }
pub(crate) fn meet_iteration_end(&mut self, fold_id: u32) -> TraceHandlerResult<()> { pub fn meet_iteration_end(&mut self, fold_id: u32) -> TraceHandlerResult<()> {
let fold_fsm = self.fsm_keeper.fold_mut(fold_id)?; let fold_fsm = self.fsm_keeper.fold_mut(fold_id)?;
fold_fsm.meet_iteration_end(&mut self.data_keeper); fold_fsm.meet_iteration_end(&mut self.data_keeper);
Ok(()) Ok(())
} }
pub(crate) fn meet_back_iterator(&mut self, fold_id: u32) -> TraceHandlerResult<()> { pub fn meet_back_iterator(&mut self, fold_id: u32) -> TraceHandlerResult<()> {
let fold_fsm = self.fsm_keeper.fold_mut(fold_id)?; let fold_fsm = self.fsm_keeper.fold_mut(fold_id)?;
fold_fsm.meet_back_iterator(&mut self.data_keeper)?; fold_fsm.meet_back_iterator(&mut self.data_keeper)?;
Ok(()) Ok(())
} }
pub(crate) fn meet_generation_end(&mut self, fold_id: u32) -> TraceHandlerResult<()> { pub fn meet_generation_end(&mut self, fold_id: u32) -> TraceHandlerResult<()> {
let fold_fsm = self.fsm_keeper.fold_mut(fold_id)?; let fold_fsm = self.fsm_keeper.fold_mut(fold_id)?;
fold_fsm.meet_generation_end(&mut self.data_keeper); fold_fsm.meet_generation_end(&mut self.data_keeper);
Ok(()) Ok(())
} }
pub(crate) fn meet_fold_end(&mut self, fold_id: u32) -> TraceHandlerResult<()> { pub fn meet_fold_end(&mut self, fold_id: u32) -> TraceHandlerResult<()> {
let fold_fsm = self.fsm_keeper.extract_fold(fold_id)?; let fold_fsm = self.fsm_keeper.extract_fold(fold_id)?;
fold_fsm.meet_fold_end(&mut self.data_keeper); fold_fsm.meet_fold_end(&mut self.data_keeper);
Ok(()) Ok(())
} }
pub(crate) fn fold_end_with_error(&mut self, fold_id: u32) { pub fn fold_end_with_error(&mut self, fold_id: u32) {
let fold_fsm = match self.fsm_keeper.extract_fold(fold_id) { let fold_fsm = match self.fsm_keeper.extract_fold(fold_id) {
Ok(fold_fsm) => fold_fsm, Ok(fold_fsm) => fold_fsm,
// just passing here is ok, because error could be produced while fold initialization // just passing here is ok, because error could be produced while fold initialization

View File

@ -20,18 +20,24 @@ mod handler;
mod merger; mod merger;
mod state_automata; mod state_automata;
pub(crate) use errors::TraceHandlerError; pub use errors::TraceHandlerError;
pub(crate) use handler::TraceHandler; pub use handler::TraceHandler;
pub(crate) use merger::MergerApResult; pub use merger::ApResultError;
pub(crate) use merger::MergerCallResult; pub use merger::CallResultError;
pub(crate) use state_automata::SubtreeType; pub use merger::FoldResultError;
pub use merger::MergeCtxType;
pub use merger::MergeError;
pub use merger::MergerApResult;
pub use merger::MergerCallResult;
pub use state_automata::SubtreeType;
pub(crate) type TraceHandlerResult<T> = std::result::Result<T, TraceHandlerError>; pub type TraceHandlerResult<T> = std::result::Result<T, TraceHandlerError>;
pub const EXECUTED_STATE_CHANGING: &str = "executed_state_changing";
use air_interpreter_data::*; use air_interpreter_data::*;
use data_keeper::DataKeeper; use data_keeper::DataKeeper;
use data_keeper::MergeCtx; use data_keeper::MergeCtx;
use merger::MergeCtxType;
use merger::MergerFoldResult; use merger::MergerFoldResult;
use merger::ResolvedFold; use merger::ResolvedFold;
use merger::ResolvedSubTraceDescs; use merger::ResolvedSubTraceDescs;

View File

@ -17,7 +17,7 @@
use super::*; use super::*;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub(crate) enum MergerApResult { pub enum MergerApResult {
/// There is no corresponding state in a trace for this call. /// There is no corresponding state in a trace for this call.
Empty, Empty,

View File

@ -23,7 +23,7 @@ use call_result_constructor::*;
use utils::*; use utils::*;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub(crate) enum MergerCallResult { pub enum MergerCallResult {
/// There is no corresponding state in a trace for this call. /// There is no corresponding state in a trace for this call.
Empty, Empty,

View File

@ -15,7 +15,8 @@
*/ */
use super::*; use super::*;
use crate::JValue;
type JValue = serde_json::Value;
use std::rc::Rc; use std::rc::Rc;

View File

@ -26,7 +26,7 @@ use thiserror::Error as ThisError;
/// Errors arose out of merging previous data with a new. /// Errors arose out of merging previous data with a new.
#[derive(ThisError, Debug)] #[derive(ThisError, Debug)]
pub(crate) enum MergeError { pub enum MergeError {
/// Errors occurred when previous and current executed states are incompatible. /// Errors occurred when previous and current executed states are incompatible.
#[error("previous and current data have incompatible states: '{0:?}' '{1:?}'")] #[error("previous and current data have incompatible states: '{0:?}' '{1:?}'")]
IncompatibleExecutedStates(ExecutedState, ExecutedState), IncompatibleExecutedStates(ExecutedState, ExecutedState),
@ -50,14 +50,14 @@ pub(crate) enum MergeError {
} }
#[derive(ThisError, Debug)] #[derive(ThisError, Debug)]
pub(crate) enum ApResultError { pub enum ApResultError {
/// Error occurred when Ap results contains more then 1 generation in destination. /// Error occurred when Ap results contains more then 1 generation in destination.
#[error("{0:?} ap result contains too many generations in destination")] #[error("{0:?} ap result contains too many generations in destination")]
TooManyDstGenerations(ApResult), TooManyDstGenerations(ApResult),
} }
#[derive(ThisError, Debug)] #[derive(ThisError, Debug)]
pub(crate) enum CallResultError { pub enum CallResultError {
#[error("values in call results are not equal: {prev_value:?} != {current_value:?}")] #[error("values in call results are not equal: {prev_value:?} != {current_value:?}")]
ValuesNotEqual { prev_value: Value, current_value: Value }, ValuesNotEqual { prev_value: Value, current_value: Value },
@ -73,7 +73,7 @@ pub(crate) enum CallResultError {
} }
#[derive(ThisError, Debug)] #[derive(ThisError, Debug)]
pub(crate) enum FoldResultError { pub enum FoldResultError {
#[error("the first {count} subtrace descriptors lens of fold {fold_result:?} overflows")] #[error("the first {count} subtrace descriptors lens of fold {fold_result:?} overflows")]
SubtraceLenOverflow { fold_result: FoldResult, count: usize }, SubtraceLenOverflow { fold_result: FoldResult, count: usize },

View File

@ -17,12 +17,12 @@
mod fold_lore_resolver; mod fold_lore_resolver;
use super::*; use super::*;
pub(crate) use fold_lore_resolver::*; pub use fold_lore_resolver::*;
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]
pub(crate) struct MergerFoldResult { pub struct MergerFoldResult {
pub(crate) prev_fold_lore: ResolvedFold, pub prev_fold_lore: ResolvedFold,
pub(crate) current_fold_lore: ResolvedFold, pub current_fold_lore: ResolvedFold,
} }
pub(crate) fn try_merge_next_state_as_fold(data_keeper: &mut DataKeeper) -> MergeResult<MergerFoldResult> { pub(crate) fn try_merge_next_state_as_fold(data_keeper: &mut DataKeeper) -> MergeResult<MergerFoldResult> {

View File

@ -15,7 +15,7 @@
*/ */
use super::*; use super::*;
use crate::execution_step::trace_handler::data_keeper::MergeCtx; use crate::data_keeper::MergeCtx;
use air_interpreter_data::FoldSubTraceLore; use air_interpreter_data::FoldSubTraceLore;
use air_interpreter_data::SubTraceDesc; use air_interpreter_data::SubTraceDesc;
@ -23,15 +23,15 @@ use air_interpreter_data::SubTraceDesc;
use std::collections::HashMap; use std::collections::HashMap;
#[derive(Debug, Default, Clone, PartialEq, Eq)] #[derive(Debug, Default, Clone, PartialEq, Eq)]
pub(crate) struct ResolvedFold { pub struct ResolvedFold {
pub(crate) lore: HashMap<usize, ResolvedSubTraceDescs>, pub lore: HashMap<usize, ResolvedSubTraceDescs>,
pub(crate) fold_states_count: usize, pub fold_states_count: usize,
} }
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct ResolvedSubTraceDescs { pub struct ResolvedSubTraceDescs {
pub(crate) before_subtrace: SubTraceDesc, pub before_subtrace: SubTraceDesc,
pub(crate) after_subtrace: SubTraceDesc, pub after_subtrace: SubTraceDesc,
} }
pub(super) fn resolve_fold_lore(fold: &FoldResult, merge_ctx: &MergeCtx) -> MergeResult<ResolvedFold> { pub(super) fn resolve_fold_lore(fold: &FoldResult, merge_ctx: &MergeCtx) -> MergeResult<ResolvedFold> {

View File

@ -20,20 +20,23 @@ mod errors;
mod fold_merger; mod fold_merger;
mod par_merger; mod par_merger;
pub use ap_merger::MergerApResult;
pub use call_merger::MergerCallResult;
pub use fold_merger::MergerFoldResult;
pub use par_merger::MergerParResult;
pub use errors::ApResultError;
pub use errors::CallResultError;
pub use errors::FoldResultError;
pub use errors::MergeError;
pub use fold_merger::ResolvedFold;
pub use fold_merger::ResolvedSubTraceDescs;
pub(super) use ap_merger::try_merge_next_state_as_ap; pub(super) use ap_merger::try_merge_next_state_as_ap;
pub(crate) use ap_merger::MergerApResult;
pub(super) use call_merger::try_merge_next_state_as_call; pub(super) use call_merger::try_merge_next_state_as_call;
pub(crate) use call_merger::MergerCallResult;
pub(crate) use errors::ApResultError;
pub(crate) use errors::CallResultError;
pub(crate) use errors::FoldResultError;
pub(crate) use errors::MergeError;
pub(crate) use fold_merger::try_merge_next_state_as_fold; pub(crate) use fold_merger::try_merge_next_state_as_fold;
pub(crate) use fold_merger::MergerFoldResult;
pub(crate) use fold_merger::ResolvedFold;
pub(crate) use fold_merger::ResolvedSubTraceDescs;
pub(crate) use par_merger::try_merge_next_state_as_par; pub(crate) use par_merger::try_merge_next_state_as_par;
pub(crate) use par_merger::MergerParResult;
type MergeResult<T> = std::result::Result<T, MergeError>; type MergeResult<T> = std::result::Result<T, MergeError>;
@ -44,7 +47,7 @@ use super::DataKeeper;
use air_interpreter_data::*; use air_interpreter_data::*;
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub(crate) enum MergeCtxType { pub enum MergeCtxType {
Current, Current,
Previous, Previous,
} }

View File

@ -18,9 +18,9 @@ use super::*;
use ExecutedState::Par; use ExecutedState::Par;
#[derive(Default, Debug, Copy, Clone)] #[derive(Default, Debug, Copy, Clone)]
pub(crate) struct MergerParResult { pub struct MergerParResult {
pub(crate) prev_par: Option<ParResult>, pub prev_par: Option<ParResult>,
pub(crate) current_par: Option<ParResult>, pub current_par: Option<ParResult>,
} }
pub(crate) fn try_merge_next_state_as_par(data_keeper: &mut DataKeeper) -> MergeResult<MergerParResult> { pub(crate) fn try_merge_next_state_as_par(data_keeper: &mut DataKeeper) -> MergeResult<MergerParResult> {

View File

@ -16,17 +16,17 @@
use super::KeeperError; use super::KeeperError;
use super::ParResult; use super::ParResult;
use crate::execution_step::trace_handler::MergeCtxType; use crate::MergeCtxType;
use crate::execution_step::trace_handler::ResolvedFold; use crate::ResolvedFold;
use thiserror::Error as ThisError; use thiserror::Error as ThisError;
/// Errors arose out of merging previous data with a new. /// Errors arose out of merging previous data with a new.
#[derive(ThisError, Debug)] #[derive(ThisError, Debug)]
pub(crate) enum StateFSMError { pub enum StateFSMError {
/// Error occurred while trying to access or pop elements from an empty par queue. /// Error occurred while trying to access or pop elements from an empty par queue.
#[error("par queue is empty, while par FSM is requested")] #[error("par queue is empty, while par FSM is requested")]
ParQueueIsEmpty(), ParQueueIsEmpty,
/// Errors occurred while trying to access or pop elements from queue, /// Errors occurred while trying to access or pop elements from queue,
/// which contains element of different type. /// which contains element of different type.

View File

@ -15,8 +15,8 @@
*/ */
use super::*; use super::*;
use crate::execution_step::trace_handler::MergeCtxType; use crate::MergeCtxType;
use crate::execution_step::trace_handler::ResolvedFold; use crate::ResolvedFold;
/// This state updater manage to do the same thing as SubTreeStateUpdater in ParFSM, /// This state updater manage to do the same thing as SubTreeStateUpdater in ParFSM,
/// for details please see its detailed comment. /// for details please see its detailed comment.

View File

@ -37,11 +37,11 @@ impl FSMKeeper {
} }
pub(crate) fn last_par(&mut self) -> FSMResult<&mut ParFSM> { pub(crate) fn last_par(&mut self) -> FSMResult<&mut ParFSM> {
self.par_stack.last_mut().ok_or(StateFSMError::ParQueueIsEmpty()) self.par_stack.last_mut().ok_or(StateFSMError::ParQueueIsEmpty)
} }
pub(crate) fn pop_par(&mut self) -> FSMResult<ParFSM> { pub(crate) fn pop_par(&mut self) -> FSMResult<ParFSM> {
self.par_stack.pop().ok_or(StateFSMError::ParQueueIsEmpty()) self.par_stack.pop().ok_or(StateFSMError::ParQueueIsEmpty)
} }
pub(crate) fn fold_mut(&mut self, fold_id: u32) -> FSMResult<&mut FoldFSM> { pub(crate) fn fold_mut(&mut self, fold_id: u32) -> FSMResult<&mut FoldFSM> {

View File

@ -21,8 +21,9 @@ mod par_fsm;
mod state_inserter; mod state_inserter;
mod utils; mod utils;
pub(crate) use errors::StateFSMError; pub use errors::StateFSMError;
pub(crate) use par_fsm::SubtreeType; pub use par_fsm::SubtreeType;
pub(crate) type FSMResult<T> = std::result::Result<T, StateFSMError>; pub(crate) type FSMResult<T> = std::result::Result<T, StateFSMError>;
pub(super) use fold_fsm::FoldFSM; pub(super) use fold_fsm::FoldFSM;

View File

@ -23,9 +23,8 @@ use state_handler::CtxStateHandler;
/// Manages a par state, its state transitioning functions must be called in the following way: /// Manages a par state, its state transitioning functions must be called in the following way:
/// from_left_started /// from_left_started
/// -> left_completed(_with_error) /// -> left_completed
/// -> right_started /// -> right_completed
/// -> right_completed(_with_error)
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]
pub(crate) struct ParFSM { pub(crate) struct ParFSM {
prev_par: ParResult, prev_par: ParResult,
@ -36,7 +35,7 @@ pub(crate) struct ParFSM {
} }
#[derive(Debug, Clone, Copy, Eq, PartialEq)] #[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub(crate) enum SubtreeType { pub enum SubtreeType {
Left, Left,
Right, Right,
} }

View File

@ -15,7 +15,7 @@
*/ */
use super::*; use super::*;
use crate::execution_step::trace_handler::data_keeper::TraceSlider; use crate::data_keeper::TraceSlider;
pub(super) fn compute_new_states( pub(super) fn compute_new_states(
data_keeper: &DataKeeper, data_keeper: &DataKeeper,