mirror of
https://github.com/fluencelabs/aquavm
synced 2025-06-27 13:41:32 +00:00
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:
@ -51,7 +51,7 @@ fn par_len_overflow() {
|
||||
);
|
||||
|
||||
let error_left_pos_value = 1;
|
||||
let error_right_pos_value = u32::MAX;
|
||||
let error_right_pos_value = PosType::MAX;
|
||||
let trace = vec![
|
||||
executed_state::par(error_left_pos_value, error_right_pos_value),
|
||||
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![
|
||||
executed_state::par(error_pos_value, error_pos_value),
|
||||
executed_state::request_sent_by(vm_peer_id_1),
|
||||
@ -553,7 +553,7 @@ fn fold_pos_overflow() {
|
||||
let value_pos = 1;
|
||||
let before_subtrace_pos = 3;
|
||||
let after_subtrace_pos = 4;
|
||||
let wrong_after_subtrace_len = u32::MAX - 1;
|
||||
let wrong_after_subtrace_len = TraceLen::MAX - 1;
|
||||
let trace = vec![
|
||||
executed_state::par(1, 2),
|
||||
stream_tracked!(json!([42, 43]), 0, cid_state),
|
||||
@ -576,13 +576,102 @@ fn fold_pos_overflow() {
|
||||
subtrace_len: wrong_after_subtrace_len,
|
||||
},
|
||||
);
|
||||
let resolved_fold = ResolvedFold::new(
|
||||
hashmap![value_pos.into() => fold_lore],
|
||||
(wrong_after_subtrace_len + 1) as usize,
|
||||
);
|
||||
let resolved_fold = ResolvedFold::new(hashmap!(value_pos.into() => fold_lore), wrong_after_subtrace_len + 1);
|
||||
let expected_error = UncatchableError::TraceError {
|
||||
trace_error: StateFSMError(FoldPosOverflow(resolved_fold, before_subtrace_pos.into(), Previous)),
|
||||
instruction: String::from(String::from("fold $s i")),
|
||||
};
|
||||
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));
|
||||
}
|
||||
|
@ -16,12 +16,16 @@
|
||||
|
||||
use super::ExecutedState;
|
||||
use crate::TracePos;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use std::convert::TryInto;
|
||||
use std::ops::Deref;
|
||||
use std::ops::Index;
|
||||
use std::ops::IndexMut;
|
||||
|
||||
pub type TraceLen = u32;
|
||||
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct ExecutionTrace(Vec<ExecutedState>);
|
||||
@ -42,6 +46,13 @@ impl ExecutionTrace {
|
||||
pub fn push(&mut self, value: ExecutedState) {
|
||||
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 {
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
use super::ExecutedState;
|
||||
use crate::TracePos;
|
||||
use air_interpreter_data::TraceLen;
|
||||
use thiserror::Error as ThisError;
|
||||
|
||||
/// Errors arose out while accessing various interpreter data.
|
||||
@ -27,9 +28,9 @@ pub enum KeeperError {
|
||||
but tried to set {requested_subtrace_len} subtrace_len"
|
||||
)]
|
||||
SetSubtraceLenFailed {
|
||||
requested_subtrace_len: usize,
|
||||
requested_subtrace_len: TraceLen,
|
||||
trace_position: TracePos,
|
||||
trace_len: usize,
|
||||
trace_len: TraceLen,
|
||||
},
|
||||
|
||||
/// Errors occurred when
|
||||
@ -40,14 +41,14 @@ pub enum KeeperError {
|
||||
)]
|
||||
SetSubtraceLenAndPosFailed {
|
||||
requested_pos: TracePos,
|
||||
requested_subtrace_len: usize,
|
||||
trace_len: usize,
|
||||
requested_subtrace_len: TraceLen,
|
||||
trace_len: TraceLen,
|
||||
},
|
||||
|
||||
/// 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.
|
||||
#[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,
|
||||
/// but such state doesn't belong to values in streams (it doesn't contain a generation).
|
||||
|
@ -21,8 +21,6 @@ use crate::TracePos;
|
||||
|
||||
use bimap::BiHashMap;
|
||||
|
||||
use std::convert::TryInto;
|
||||
|
||||
/// Keeps all necessary data for merging.
|
||||
#[derive(Debug, Default, PartialEq)]
|
||||
pub(crate) struct DataKeeper {
|
||||
@ -52,7 +50,7 @@ impl DataKeeper {
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -14,12 +14,16 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use air_interpreter_data::TraceLen;
|
||||
|
||||
use super::ExecutedState;
|
||||
use super::ExecutionTrace;
|
||||
use super::KeeperError::*;
|
||||
use super::KeeperResult;
|
||||
use crate::TracePos;
|
||||
|
||||
type SeenElements = u32;
|
||||
|
||||
/// This slider is intended to slide on a subtrace inside provided trace. This subtrace
|
||||
/// is identified by position and len.
|
||||
// TODO: check for overflow
|
||||
@ -32,16 +36,16 @@ pub struct TraceSlider {
|
||||
position: TracePos,
|
||||
|
||||
/// Length of a current subtrace.
|
||||
subtrace_len: usize,
|
||||
subtrace_len: TraceLen,
|
||||
|
||||
/// Count of seen elements since the last position update.
|
||||
seen_elements: usize,
|
||||
seen_elements: SeenElements,
|
||||
}
|
||||
|
||||
impl TraceSlider {
|
||||
pub(crate) fn new(trace: impl Into<ExecutionTrace>) -> Self {
|
||||
let trace = trace.into();
|
||||
let subtrace_len = trace.len();
|
||||
let subtrace_len = trace.trace_states_count();
|
||||
|
||||
Self {
|
||||
trace,
|
||||
@ -54,7 +58,7 @@ impl TraceSlider {
|
||||
/// and None otherwise.
|
||||
#[allow(clippy::suspicious_operation_groupings)]
|
||||
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;
|
||||
}
|
||||
|
||||
@ -64,14 +68,13 @@ impl TraceSlider {
|
||||
Some(result)
|
||||
}
|
||||
|
||||
pub(crate) fn set_position_and_len(&mut self, position: TracePos, subtrace_len: usize) -> KeeperResult<()> {
|
||||
let pos: usize = position.into();
|
||||
pub(crate) fn set_position_and_len(&mut self, position: TracePos, subtrace_len: TraceLen) -> KeeperResult<()> {
|
||||
// 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 {
|
||||
requested_pos: position,
|
||||
requested_subtrace_len: subtrace_len,
|
||||
trace_len: self.trace.len(),
|
||||
trace_len: self.trace.trace_states_count(),
|
||||
});
|
||||
}
|
||||
|
||||
@ -82,13 +85,13 @@ impl TraceSlider {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn set_subtrace_len(&mut self, subtrace_len: usize) -> KeeperResult<()> {
|
||||
let trace_remainder = self.trace.len() - usize::from(self.position);
|
||||
pub(crate) fn set_subtrace_len(&mut self, subtrace_len: TraceLen) -> KeeperResult<()> {
|
||||
let trace_remainder: TraceLen = (TracePos::from(self.trace_len()) - self.position).into();
|
||||
if trace_remainder < subtrace_len {
|
||||
return Err(SetSubtraceLenFailed {
|
||||
requested_subtrace_len: subtrace_len,
|
||||
trace_position: self.position,
|
||||
trace_len: self.trace.len(),
|
||||
trace_len: self.trace.trace_states_count(),
|
||||
});
|
||||
}
|
||||
|
||||
@ -102,7 +105,8 @@ impl TraceSlider {
|
||||
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
|
||||
}
|
||||
|
||||
@ -111,7 +115,7 @@ impl TraceSlider {
|
||||
self.trace.get(position)
|
||||
}
|
||||
|
||||
pub(super) fn trace_len(&self) -> usize {
|
||||
self.trace.len()
|
||||
pub(super) fn trace_len(&self) -> TraceLen {
|
||||
self.trace.trace_states_count()
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ impl TraceHandler {
|
||||
&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 current_len = self.data_keeper.current_slider().subtrace_len();
|
||||
|
||||
|
@ -23,10 +23,12 @@ use air_interpreter_data::TracePos;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub type FoldStatesCount = u32;
|
||||
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq)]
|
||||
pub struct ResolvedFold {
|
||||
pub lore: HashMap<TracePos, ResolvedSubTraceDescs>,
|
||||
pub fold_states_count: usize,
|
||||
pub fold_states_count: FoldStatesCount,
|
||||
}
|
||||
|
||||
#[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,
|
||||
// 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 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_pos = 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;
|
||||
// this checks for overflow both cum_before_len and cum_after_len
|
||||
fold_states_count = fold_states_count
|
||||
.checked_add(before_len as usize)
|
||||
.and_then(|v| v.checked_add(after_len as usize))
|
||||
.checked_add(before_len)
|
||||
.and_then(|v| v.checked_add(after_len))
|
||||
.ok_or_else(|| FoldResultError::SubtraceLenOverflow {
|
||||
fold_result: fold.clone(),
|
||||
count: subtrace_id,
|
||||
@ -155,7 +157,7 @@ fn check_subtrace_lore(subtrace_lore: &FoldSubTraceLore) -> MergeResult<()> {
|
||||
}
|
||||
|
||||
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 {
|
||||
lore,
|
||||
fold_states_count,
|
||||
|
@ -20,10 +20,9 @@ use crate::merger::MergeCtxType;
|
||||
use crate::ResolvedFold;
|
||||
use crate::TracePos;
|
||||
|
||||
use air_interpreter_data::TraceLen;
|
||||
use thiserror::Error as ThisError;
|
||||
|
||||
use std::num::TryFromIntError;
|
||||
|
||||
/// Errors arose out of merging previous data with a new.
|
||||
#[derive(ThisError, Debug)]
|
||||
pub enum StateFSMError {
|
||||
@ -46,16 +45,12 @@ pub enum StateFSMError {
|
||||
|
||||
/// 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}'")]
|
||||
ParLenUnderflow(ParResult, usize, MergeCtxType),
|
||||
ParLenUnderflow(ParResult, TraceLen, MergeCtxType),
|
||||
|
||||
/// 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}'")]
|
||||
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.
|
||||
#[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),
|
||||
|
@ -20,8 +20,6 @@ use crate::ResolvedFold;
|
||||
|
||||
use num_traits::ops::checked::CheckedAdd;
|
||||
|
||||
use std::convert::TryFrom;
|
||||
|
||||
/// This state updater manage to do the same thing as CtxStateHandler in ParFSM,
|
||||
/// for details please see its detailed comment.
|
||||
#[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 fold_states_count = TracePos::try_from(fold.fold_states_count)
|
||||
.map_err(|e| StateFSMError::FoldStatesCountOverflow(e, fold.clone(), ctx_type))?;
|
||||
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))?;
|
||||
|
||||
let current_len = ctx.slider.subtrace_len();
|
||||
|
@ -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>());
|
||||
let new_subtrace_len = match subgraph_type {
|
||||
SubgraphType::Left => par_subgraph_len as usize,
|
||||
SubgraphType::Left => par_subgraph_len,
|
||||
SubgraphType::Right => slider
|
||||
.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))?,
|
||||
};
|
||||
|
||||
|
@ -14,6 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use air_interpreter_data::TraceLen;
|
||||
|
||||
use super::DataKeeper;
|
||||
use super::FSMResult;
|
||||
use super::MergeCtx;
|
||||
@ -22,7 +24,7 @@ use crate::TracePos;
|
||||
#[derive(Debug, Default, Clone, Copy)]
|
||||
pub(super) struct CtxState {
|
||||
pub(super) pos: TracePos,
|
||||
pub(super) subtrace_len: usize,
|
||||
pub(super) subtrace_len: TraceLen,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy)]
|
||||
@ -32,7 +34,7 @@ pub(super) struct CtxStatesPair {
|
||||
}
|
||||
|
||||
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 }
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user