chore(trace-handler): sub/-trace len dedicated alias to replace usize [fixes VM-282] (#569)

feat(trace-handler): sub/-trace len dedicated alias to replace usize [fixes VM-282]
This commit is contained in:
raftedproc
2023-05-02 16:32:18 +03:00
committed by GitHub
parent 80486ed6ad
commit b480e018b4
11 changed files with 150 additions and 52 deletions

View File

@ -51,7 +51,7 @@ fn par_len_overflow() {
); );
let error_left_pos_value = 1; let error_left_pos_value = 1;
let error_right_pos_value = u32::MAX; let error_right_pos_value = PosType::MAX;
let trace = vec![ let trace = vec![
executed_state::par(error_left_pos_value, error_right_pos_value), executed_state::par(error_left_pos_value, error_right_pos_value),
executed_state::request_sent_by(vm_peer_id_1), executed_state::request_sent_by(vm_peer_id_1),
@ -82,7 +82,7 @@ fn par_pos_overflow() {
"# "#
); );
let error_pos_value = u32::MAX; let error_pos_value = PosType::MAX;
let trace = vec![ let trace = vec![
executed_state::par(error_pos_value, error_pos_value), executed_state::par(error_pos_value, error_pos_value),
executed_state::request_sent_by(vm_peer_id_1), executed_state::request_sent_by(vm_peer_id_1),
@ -553,7 +553,7 @@ fn fold_pos_overflow() {
let value_pos = 1; let value_pos = 1;
let before_subtrace_pos = 3; let before_subtrace_pos = 3;
let after_subtrace_pos = 4; let after_subtrace_pos = 4;
let wrong_after_subtrace_len = u32::MAX - 1; let wrong_after_subtrace_len = TraceLen::MAX - 1;
let trace = vec![ let trace = vec![
executed_state::par(1, 2), executed_state::par(1, 2),
stream_tracked!(json!([42, 43]), 0, cid_state), stream_tracked!(json!([42, 43]), 0, cid_state),
@ -576,13 +576,102 @@ fn fold_pos_overflow() {
subtrace_len: wrong_after_subtrace_len, subtrace_len: wrong_after_subtrace_len,
}, },
); );
let resolved_fold = ResolvedFold::new( let resolved_fold = ResolvedFold::new(hashmap!(value_pos.into() => fold_lore), wrong_after_subtrace_len + 1);
hashmap![value_pos.into() => fold_lore],
(wrong_after_subtrace_len + 1) as usize,
);
let expected_error = UncatchableError::TraceError { let expected_error = UncatchableError::TraceError {
trace_error: StateFSMError(FoldPosOverflow(resolved_fold, before_subtrace_pos.into(), Previous)), trace_error: StateFSMError(FoldPosOverflow(resolved_fold, before_subtrace_pos.into(), Previous)),
instruction: String::from(String::from("fold $s i")), instruction: String::from(String::from("fold $s i")),
}; };
assert!(check_error(&result, expected_error)); assert!(check_error(&result, expected_error));
} }
#[test]
fn subtrace_len_overflow() {
let vm_peer_id_1 = "vm_peer_id_1";
let mut peer_vm_1 = create_avm(unit_call_service(), vm_peer_id_1);
let script = format!(
r#"
(par
(call "vm_peer_id_1" ("" "") [] $s)
(fold $s i
(call "vm_peer_id_2" ("" "") [] a)
(next i)
)
)
"#
);
let mut cid_state = ExecutionCidState::new();
let value_pos = 1;
let wrong_subtrace_len = TraceLen::MAX;
let trace = vec![
executed_state::par(1, 2),
stream_tracked!(json!([42, 43]), 0, cid_state, peer = vm_peer_id_1),
executed_state::fold(vec![executed_state::subtrace_lore(
value_pos,
subtrace_desc(3, 1),
subtrace_desc(4, wrong_subtrace_len),
)]),
request_sent_by("vm_peer_id_1"),
];
let _wrong_data = raw_data_from_trace(trace, cid_state);
let result = call_vm!(peer_vm_1, <_>::default(), script, _wrong_data, "");
let fold_lore = FoldSubTraceLore {
value_pos: value_pos.into(),
subtraces_desc: vec![
SubTraceDesc {
begin_pos: 3.into(),
subtrace_len: 1,
},
SubTraceDesc {
begin_pos: 4.into(),
subtrace_len: wrong_subtrace_len,
},
],
};
let fold_result = FoldResult { lore: vec![fold_lore] };
let expected_error = UncatchableError::TraceError {
trace_error: MergeError(air_trace_handler::merger::MergeError::IncorrectFoldResult(
FoldResultError::SubtraceLenOverflow { fold_result, count: 0 },
)),
instruction: String::from(String::from("fold $s i")),
};
assert!(check_error(&result, expected_error));
}
#[test]
fn fold_incorrect_subtraces_count() {
let vm_peer_id_1 = "vm_peer_id_1";
let mut peer_vm_1 = create_avm(unit_call_service(), vm_peer_id_1);
let script = format!(
r#"
(par
(call "vm_peer_id_1" ("" "") [] $s)
(fold $s i
(call "vm_peer_id_2" ("" "") [] a)
(next i)
)
)
"#
);
let mut cid_state = ExecutionCidState::new();
let value_pos = 1;
let wrong_subtrace_lore = vec![subtrace_desc(3, 1), subtrace_desc(4, 0), subtrace_desc(4, 0)];
let trace = vec![
executed_state::par(1, 2),
stream_tracked!(json!([42, 43]), 0, cid_state, peer = vm_peer_id_1),
executed_state::fold(vec![FoldSubTraceLore {
value_pos: value_pos.into(),
subtraces_desc: wrong_subtrace_lore.clone(),
}]),
request_sent_by("vm_peer_id_1"),
];
let _wrong_data = raw_data_from_trace(trace, cid_state);
let result = call_vm!(peer_vm_1, <_>::default(), script, _wrong_data, "");
let expected_error = UncatchableError::TraceError {
trace_error: MergeError(air_trace_handler::merger::MergeError::IncorrectFoldResult(
FoldResultError::FoldIncorrectSubtracesCount(wrong_subtrace_lore.len()),
)),
instruction: String::from(String::from("fold $s i")),
};
assert!(check_error(&result, expected_error));
}

View File

@ -16,12 +16,16 @@
use super::ExecutedState; use super::ExecutedState;
use crate::TracePos; use crate::TracePos;
use serde::Deserialize; use serde::Deserialize;
use serde::Serialize; use serde::Serialize;
use std::convert::TryInto;
use std::ops::Deref; use std::ops::Deref;
use std::ops::Index; use std::ops::Index;
use std::ops::IndexMut; use std::ops::IndexMut;
pub type TraceLen = u32;
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(transparent)] #[serde(transparent)]
pub struct ExecutionTrace(Vec<ExecutedState>); pub struct ExecutionTrace(Vec<ExecutedState>);
@ -42,6 +46,13 @@ impl ExecutionTrace {
pub fn push(&mut self, value: ExecutedState) { pub fn push(&mut self, value: ExecutedState) {
self.0.push(value); self.0.push(value);
} }
pub fn trace_states_count(&self) -> TraceLen {
self.0
.len()
.try_into()
.expect("there is an overflow in trace_states_count().")
}
} }
impl Deref for ExecutionTrace { impl Deref for ExecutionTrace {

View File

@ -16,6 +16,7 @@
use super::ExecutedState; use super::ExecutedState;
use crate::TracePos; use crate::TracePos;
use air_interpreter_data::TraceLen;
use thiserror::Error as ThisError; use thiserror::Error as ThisError;
/// Errors arose out while accessing various interpreter data. /// Errors arose out while accessing various interpreter data.
@ -27,9 +28,9 @@ pub enum KeeperError {
but tried to set {requested_subtrace_len} subtrace_len" but tried to set {requested_subtrace_len} subtrace_len"
)] )]
SetSubtraceLenFailed { SetSubtraceLenFailed {
requested_subtrace_len: usize, requested_subtrace_len: TraceLen,
trace_position: TracePos, trace_position: TracePos,
trace_len: usize, trace_len: TraceLen,
}, },
/// Errors occurred when /// Errors occurred when
@ -40,14 +41,14 @@ pub enum KeeperError {
)] )]
SetSubtraceLenAndPosFailed { SetSubtraceLenAndPosFailed {
requested_pos: TracePos, requested_pos: TracePos,
requested_subtrace_len: usize, requested_subtrace_len: TraceLen,
trace_len: usize, trace_len: TraceLen,
}, },
/// Errors occurred when Fold FSM tries to obtain stream generation by value_pos from a trace, /// Errors occurred when Fold FSM tries to obtain stream generation by value_pos from a trace,
/// but this value_pos is bigger than the trace length. /// but this value_pos is bigger than the trace length.
#[error("requested an element at position '{position}', but executed trace contains only '{trace_len}' elements")] #[error("requested an element at position '{position}', but executed trace contains only '{trace_len}' elements")]
NoElementAtPosition { position: TracePos, trace_len: usize }, NoElementAtPosition { position: TracePos, trace_len: TraceLen },
/// Errors occurred when Fold FSM tries to obtain stream generation by value_pos from a trace, /// Errors occurred when Fold FSM tries to obtain stream generation by value_pos from a trace,
/// but such state doesn't belong to values in streams (it doesn't contain a generation). /// but such state doesn't belong to values in streams (it doesn't contain a generation).

View File

@ -21,8 +21,6 @@ use crate::TracePos;
use bimap::BiHashMap; use bimap::BiHashMap;
use std::convert::TryInto;
/// Keeps all necessary data for merging. /// Keeps all necessary data for merging.
#[derive(Debug, Default, PartialEq)] #[derive(Debug, Default, PartialEq)]
pub(crate) struct DataKeeper { pub(crate) struct DataKeeper {
@ -52,7 +50,7 @@ impl DataKeeper {
} }
pub(crate) fn result_trace_next_pos(&self) -> TracePos { pub(crate) fn result_trace_next_pos(&self) -> TracePos {
self.result_trace.len().try_into().expect("try_into() TracePos failed.") self.result_trace.trace_states_count().into()
} }
pub(crate) fn prev_slider(&self) -> &TraceSlider { pub(crate) fn prev_slider(&self) -> &TraceSlider {

View File

@ -14,12 +14,16 @@
* limitations under the License. * limitations under the License.
*/ */
use air_interpreter_data::TraceLen;
use super::ExecutedState; use super::ExecutedState;
use super::ExecutionTrace; use super::ExecutionTrace;
use super::KeeperError::*; use super::KeeperError::*;
use super::KeeperResult; use super::KeeperResult;
use crate::TracePos; use crate::TracePos;
type SeenElements = u32;
/// This slider is intended to slide on a subtrace inside provided trace. This subtrace /// This slider is intended to slide on a subtrace inside provided trace. This subtrace
/// is identified by position and len. /// is identified by position and len.
// TODO: check for overflow // TODO: check for overflow
@ -32,16 +36,16 @@ pub struct TraceSlider {
position: TracePos, position: TracePos,
/// Length of a current subtrace. /// Length of a current subtrace.
subtrace_len: usize, subtrace_len: TraceLen,
/// Count of seen elements since the last position update. /// Count of seen elements since the last position update.
seen_elements: usize, seen_elements: SeenElements,
} }
impl TraceSlider { impl TraceSlider {
pub(crate) fn new(trace: impl Into<ExecutionTrace>) -> Self { pub(crate) fn new(trace: impl Into<ExecutionTrace>) -> Self {
let trace = trace.into(); let trace = trace.into();
let subtrace_len = trace.len(); let subtrace_len = trace.trace_states_count();
Self { Self {
trace, trace,
@ -54,7 +58,7 @@ impl TraceSlider {
/// and None otherwise. /// and None otherwise.
#[allow(clippy::suspicious_operation_groupings)] #[allow(clippy::suspicious_operation_groupings)]
pub(crate) fn next_state(&mut self) -> Option<ExecutedState> { pub(crate) fn next_state(&mut self) -> Option<ExecutedState> {
if self.seen_elements >= self.subtrace_len || usize::from(self.position) >= self.trace.len() { if self.seen_elements >= self.subtrace_len || self.position >= self.trace.trace_states_count().into() {
return None; return None;
} }
@ -64,14 +68,13 @@ impl TraceSlider {
Some(result) Some(result)
} }
pub(crate) fn set_position_and_len(&mut self, position: TracePos, subtrace_len: usize) -> KeeperResult<()> { pub(crate) fn set_position_and_len(&mut self, position: TracePos, subtrace_len: TraceLen) -> KeeperResult<()> {
let pos: usize = position.into();
// it's possible to set empty subtrace_len and inconsistent position // it's possible to set empty subtrace_len and inconsistent position
if subtrace_len != 0 && pos + subtrace_len > self.trace.len() { if subtrace_len != 0 && position + subtrace_len > self.trace.trace_states_count().into() {
return Err(SetSubtraceLenAndPosFailed { return Err(SetSubtraceLenAndPosFailed {
requested_pos: position, requested_pos: position,
requested_subtrace_len: subtrace_len, requested_subtrace_len: subtrace_len,
trace_len: self.trace.len(), trace_len: self.trace.trace_states_count(),
}); });
} }
@ -82,13 +85,13 @@ impl TraceSlider {
Ok(()) Ok(())
} }
pub(crate) fn set_subtrace_len(&mut self, subtrace_len: usize) -> KeeperResult<()> { pub(crate) fn set_subtrace_len(&mut self, subtrace_len: TraceLen) -> KeeperResult<()> {
let trace_remainder = self.trace.len() - usize::from(self.position); let trace_remainder: TraceLen = (TracePos::from(self.trace_len()) - self.position).into();
if trace_remainder < subtrace_len { if trace_remainder < subtrace_len {
return Err(SetSubtraceLenFailed { return Err(SetSubtraceLenFailed {
requested_subtrace_len: subtrace_len, requested_subtrace_len: subtrace_len,
trace_position: self.position, trace_position: self.position,
trace_len: self.trace.len(), trace_len: self.trace.trace_states_count(),
}); });
} }
@ -102,7 +105,8 @@ impl TraceSlider {
self.position self.position
} }
pub(crate) fn subtrace_len(&self) -> usize { pub(crate) fn subtrace_len(&self) -> TraceLen {
debug_assert!(self.subtrace_len >= self.seen_elements);
self.subtrace_len - self.seen_elements self.subtrace_len - self.seen_elements
} }
@ -111,7 +115,7 @@ impl TraceSlider {
self.trace.get(position) self.trace.get(position)
} }
pub(super) fn trace_len(&self) -> usize { pub(super) fn trace_len(&self) -> TraceLen {
self.trace.len() self.trace.trace_states_count()
} }
} }

View File

@ -53,7 +53,7 @@ impl TraceHandler {
&self.data_keeper.result_trace &self.data_keeper.result_trace
} }
pub fn subgraph_sizes(&self) -> (usize, usize) { pub fn subgraph_sizes(&self) -> (TraceLen, TraceLen) {
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();

View File

@ -23,10 +23,12 @@ use air_interpreter_data::TracePos;
use std::collections::HashMap; use std::collections::HashMap;
pub type FoldStatesCount = u32;
#[derive(Debug, Default, Clone, PartialEq, Eq)] #[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct ResolvedFold { pub struct ResolvedFold {
pub lore: HashMap<TracePos, ResolvedSubTraceDescs>, pub lore: HashMap<TracePos, ResolvedSubTraceDescs>,
pub fold_states_count: usize, pub fold_states_count: FoldStatesCount,
} }
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
@ -78,10 +80,10 @@ pub(super) fn resolve_fold_lore(fold: &FoldResult, merge_ctx: &MergeCtx) -> Merg
// TODO: in future it's possible to change a format of a Fold state to one behaves like Par, // TODO: in future it's possible to change a format of a Fold state to one behaves like Par,
// because this function adds some overhead // because this function adds some overhead
fn compute_lens_convolution(fold: &FoldResult, merge_ctx: &MergeCtx) -> MergeResult<(usize, Vec<LoresLen>)> { fn compute_lens_convolution(fold: &FoldResult, merge_ctx: &MergeCtx) -> MergeResult<(FoldStatesCount, Vec<LoresLen>)> {
let subtraces_count = fold.lore.len(); let subtraces_count = fold.lore.len();
let mut lens = Vec::with_capacity(subtraces_count); let mut lens = Vec::with_capacity(subtraces_count);
let mut fold_states_count: usize = 0; let mut fold_states_count: FoldStatesCount = 0;
let mut last_seen_generation = GenerationIdx::from(0); let mut last_seen_generation = GenerationIdx::from(0);
let mut last_seen_generation_pos = 0; let mut last_seen_generation_pos = 0;
let mut cum_after_len = 0; let mut cum_after_len = 0;
@ -106,8 +108,8 @@ fn compute_lens_convolution(fold: &FoldResult, merge_ctx: &MergeCtx) -> MergeRes
let after_len = subtrace_lore.subtraces_desc[1].subtrace_len; let after_len = subtrace_lore.subtraces_desc[1].subtrace_len;
// this checks for overflow both cum_before_len and cum_after_len // this checks for overflow both cum_before_len and cum_after_len
fold_states_count = fold_states_count fold_states_count = fold_states_count
.checked_add(before_len as usize) .checked_add(before_len)
.and_then(|v| v.checked_add(after_len as usize)) .and_then(|v| v.checked_add(after_len))
.ok_or_else(|| FoldResultError::SubtraceLenOverflow { .ok_or_else(|| FoldResultError::SubtraceLenOverflow {
fold_result: fold.clone(), fold_result: fold.clone(),
count: subtrace_id, count: subtrace_id,
@ -155,7 +157,7 @@ fn check_subtrace_lore(subtrace_lore: &FoldSubTraceLore) -> MergeResult<()> {
} }
impl ResolvedFold { impl ResolvedFold {
pub fn new(lore: HashMap<TracePos, ResolvedSubTraceDescs>, fold_states_count: usize) -> Self { pub fn new(lore: HashMap<TracePos, ResolvedSubTraceDescs>, fold_states_count: FoldStatesCount) -> Self {
Self { Self {
lore, lore,
fold_states_count, fold_states_count,

View File

@ -20,10 +20,9 @@ use crate::merger::MergeCtxType;
use crate::ResolvedFold; use crate::ResolvedFold;
use crate::TracePos; use crate::TracePos;
use air_interpreter_data::TraceLen;
use thiserror::Error as ThisError; use thiserror::Error as ThisError;
use std::num::TryFromIntError;
/// 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 enum StateFSMError { pub enum StateFSMError {
@ -46,16 +45,12 @@ pub enum StateFSMError {
/// Errors occurred when ParResult.0 + ParResult.1 value is bigger than current subgraph size. /// Errors occurred when ParResult.0 + ParResult.1 value is bigger than current subgraph size.
#[error("underflow is occurred while calculating the new position of a {2} slider for resolved par {0:?} and current subtrace len {1}'")] #[error("underflow is occurred while calculating the new position of a {2} slider for resolved par {0:?} and current subtrace len {1}'")]
ParLenUnderflow(ParResult, usize, MergeCtxType), ParLenUnderflow(ParResult, TraceLen, MergeCtxType),
/// Errors occurred when {0}.fold_states_count + {1} overflows. /// Errors occurred when {0}.fold_states_count + {1} overflows.
#[error("overflow is occurred while calculating the new position of a {2} slider for resolved fold {0:?} and current position {1}'")] #[error("overflow is occurred while calculating the new position of a {2} slider for resolved fold {0:?} and current position {1}'")]
FoldPosOverflow(ResolvedFold, TracePos, MergeCtxType), FoldPosOverflow(ResolvedFold, TracePos, MergeCtxType),
/// Errors occurred when {0}.fold_states_count + {1} overflows.
#[error("error: {0:?} converting fold states count into suitable representation for resolved fold {1:?} and current position {2}'")]
FoldStatesCountOverflow(TryFromIntError, ResolvedFold, MergeCtxType),
/// Errors occurred when {1} - 1{0}.fold_states_count underflows. /// Errors occurred when {1} - 1{0}.fold_states_count underflows.
#[error("underflow is occurred while calculating the new position of a {2} slider for resolved fold {0:?} and current subtrace len {1}'")] #[error("underflow is occurred while calculating the new position of a {2} slider for resolved fold {0:?} and current subtrace len {1}'")]
FoldLenUnderflow(ResolvedFold, TracePos, MergeCtxType), FoldLenUnderflow(ResolvedFold, TracePos, MergeCtxType),

View File

@ -20,8 +20,6 @@ use crate::ResolvedFold;
use num_traits::ops::checked::CheckedAdd; use num_traits::ops::checked::CheckedAdd;
use std::convert::TryFrom;
/// This state updater manage to do the same thing as CtxStateHandler in ParFSM, /// This state updater manage to do the same thing as CtxStateHandler in ParFSM,
/// for details please see its detailed comment. /// for details please see its detailed comment.
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]
@ -55,10 +53,8 @@ fn compute_new_state(fold: &ResolvedFold, data_keeper: &DataKeeper, ctx_type: Me
}; };
let current_position = ctx.slider.position(); let current_position = ctx.slider.position();
let fold_states_count = TracePos::try_from(fold.fold_states_count)
.map_err(|e| StateFSMError::FoldStatesCountOverflow(e, fold.clone(), ctx_type))?;
let pos = current_position let pos = current_position
.checked_add(&fold_states_count) .checked_add(&fold.fold_states_count.into())
.ok_or_else(|| StateFSMError::FoldPosOverflow(fold.clone(), current_position, ctx_type))?; .ok_or_else(|| StateFSMError::FoldPosOverflow(fold.clone(), current_position, ctx_type))?;
let current_len = ctx.slider.subtrace_len(); let current_len = ctx.slider.subtrace_len();

View File

@ -45,10 +45,10 @@ fn compute_new_state(par_result: ParResult, subgraph_type: SubgraphType, slider:
assert!(std::mem::size_of_val(&par_subgraph_len) <= std::mem::size_of::<usize>()); assert!(std::mem::size_of_val(&par_subgraph_len) <= std::mem::size_of::<usize>());
let new_subtrace_len = match subgraph_type { let new_subtrace_len = match subgraph_type {
SubgraphType::Left => par_subgraph_len as usize, SubgraphType::Left => par_subgraph_len,
SubgraphType::Right => slider SubgraphType::Right => slider
.subtrace_len() .subtrace_len()
.checked_sub(par_subgraph_len as usize) .checked_sub(par_subgraph_len)
.ok_or_else(|| StateFSMError::ParLenUnderflow(par_result, slider.subtrace_len(), MergeCtxType::Current))?, .ok_or_else(|| StateFSMError::ParLenUnderflow(par_result, slider.subtrace_len(), MergeCtxType::Current))?,
}; };

View File

@ -14,6 +14,8 @@
* limitations under the License. * limitations under the License.
*/ */
use air_interpreter_data::TraceLen;
use super::DataKeeper; use super::DataKeeper;
use super::FSMResult; use super::FSMResult;
use super::MergeCtx; use super::MergeCtx;
@ -22,7 +24,7 @@ use crate::TracePos;
#[derive(Debug, Default, Clone, Copy)] #[derive(Debug, Default, Clone, Copy)]
pub(super) struct CtxState { pub(super) struct CtxState {
pub(super) pos: TracePos, pub(super) pos: TracePos,
pub(super) subtrace_len: usize, pub(super) subtrace_len: TraceLen,
} }
#[derive(Debug, Default, Clone, Copy)] #[derive(Debug, Default, Clone, Copy)]
@ -32,7 +34,7 @@ pub(super) struct CtxStatesPair {
} }
impl CtxState { impl CtxState {
pub(super) fn new(pos: TracePos, subtrace_len: usize) -> Self { pub(super) fn new(pos: TracePos, subtrace_len: TraceLen) -> Self {
Self { pos, subtrace_len } Self { pos, subtrace_len }
} }