feat(execution-engine,test-utils,interpreter-data,interpreter-cid)!: Rc into CID (#718)

* Hide `Rc` inside `CID` type, making it cheap to clone.
* Introduce `CidRef` type that abstracts on `CID`'s inner type.

This change makes code cleaner, makes memory more optimal (single allocation vs two allocations) and makes it easier to change CID's internal representation from string to binary.
This commit is contained in:
Ivan Boldyrev 2023-10-16 17:35:42 +04:00 committed by GitHub
parent d2ad221597
commit c2108e0fa0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 137 additions and 126 deletions

View File

@ -23,6 +23,7 @@ use crate::StreamMapKeyError;
use crate::ToErrorCode; use crate::ToErrorCode;
use air_interpreter_cid::CidCalculationError; use air_interpreter_cid::CidCalculationError;
use air_interpreter_cid::CidRef;
use air_interpreter_data::ValueRef; use air_interpreter_data::ValueRef;
use air_trace_handler::GenerationCompactificationError; use air_trace_handler::GenerationCompactificationError;
use air_trace_handler::IntConversionError; use air_trace_handler::IntConversionError;
@ -33,6 +34,8 @@ use strum_macros::EnumDiscriminants;
use strum_macros::EnumIter; use strum_macros::EnumIter;
use thiserror::Error as ThisError; use thiserror::Error as ThisError;
use std::rc::Rc;
/// Uncatchable errors arisen during AIR script execution. Uncatchable here means that these errors /// Uncatchable errors arisen during AIR script execution. Uncatchable here means that these errors
/// couldn't be handled by a xor instruction and their error_code couldn't be used in a match /// couldn't be handled by a xor instruction and their error_code couldn't be used in a match
/// instruction. They are similar to JVM runtime errors and some of them could be caught only /// instruction. They are similar to JVM runtime errors and some of them could be caught only
@ -90,7 +93,7 @@ pub enum UncatchableError {
/// We consider now that every CID should present in the data; /// We consider now that every CID should present in the data;
/// and not having any CID is considered a non-catching error. /// and not having any CID is considered a non-catching error.
#[error("{0} for CID {1:?} not found")] #[error("{0} for CID {1:?} not found")]
ValueForCidNotFound(&'static str, String), ValueForCidNotFound(&'static str, Rc<CidRef>),
/// Errors occurred while insertion of a value inside stream that doesn't have corresponding generation. /// Errors occurred while insertion of a value inside stream that doesn't have corresponding generation.
#[error( #[error(

View File

@ -71,7 +71,7 @@ impl ExecutionCidState {
value: Rc<JValue>, value: Rc<JValue>,
tetraplet: RcSecurityTetraplet, tetraplet: RcSecurityTetraplet,
argument_hash: Rc<str>, argument_hash: Rc<str>,
) -> Result<Rc<CID<ServiceResultCidAggregate>>, UncatchableError> { ) -> Result<CID<ServiceResultCidAggregate>, UncatchableError> {
let value_cid = self.value_tracker.track_value(value)?; let value_cid = self.value_tracker.track_value(value)?;
let tetraplet_cid = self.tetraplet_tracker.track_value(tetraplet)?; let tetraplet_cid = self.tetraplet_tracker.track_value(tetraplet)?;
let service_result_agg = ServiceResultCidAggregate::new(value_cid, argument_hash, tetraplet_cid); let service_result_agg = ServiceResultCidAggregate::new(value_cid, argument_hash, tetraplet_cid);
@ -84,7 +84,7 @@ impl ExecutionCidState {
pub(crate) fn track_canon_value( pub(crate) fn track_canon_value(
&mut self, &mut self,
canon_value: &ValueAggregate, canon_value: &ValueAggregate,
) -> Result<Rc<CID<CanonCidAggregate>>, UncatchableError> { ) -> Result<CID<CanonCidAggregate>, UncatchableError> {
let value_cid = self.value_tracker.track_value(canon_value.get_result().clone())?; let value_cid = self.value_tracker.track_value(canon_value.get_result().clone())?;
let tetraplet = self.tetraplet_tracker.track_value(canon_value.get_tetraplet())?; let tetraplet = self.tetraplet_tracker.track_value(canon_value.get_tetraplet())?;
@ -97,7 +97,7 @@ impl ExecutionCidState {
pub(crate) fn get_value_by_cid(&self, cid: &CID<JValue>) -> Result<Rc<JValue>, UncatchableError> { pub(crate) fn get_value_by_cid(&self, cid: &CID<JValue>) -> Result<Rc<JValue>, UncatchableError> {
self.value_tracker self.value_tracker
.get(cid) .get(cid)
.ok_or_else(|| UncatchableError::ValueForCidNotFound("value", cid.clone().into())) .ok_or_else(|| UncatchableError::ValueForCidNotFound("value", cid.get_inner()))
} }
pub(crate) fn get_tetraplet_by_cid( pub(crate) fn get_tetraplet_by_cid(
@ -106,7 +106,7 @@ impl ExecutionCidState {
) -> Result<RcSecurityTetraplet, UncatchableError> { ) -> Result<RcSecurityTetraplet, UncatchableError> {
self.tetraplet_tracker self.tetraplet_tracker
.get(cid) .get(cid)
.ok_or_else(|| UncatchableError::ValueForCidNotFound("tetraplet", cid.clone().into())) .ok_or_else(|| UncatchableError::ValueForCidNotFound("tetraplet", cid.get_inner()))
} }
pub(crate) fn get_canon_value_by_cid( pub(crate) fn get_canon_value_by_cid(
@ -116,7 +116,7 @@ impl ExecutionCidState {
let canon_aggregate = self let canon_aggregate = self
.canon_element_tracker .canon_element_tracker
.get(cid) .get(cid)
.ok_or_else(|| UncatchableError::ValueForCidNotFound("canon aggregate", cid.clone().into()))?; .ok_or_else(|| UncatchableError::ValueForCidNotFound("canon aggregate", cid.get_inner()))?;
let result = self.get_value_by_cid(&canon_aggregate.value)?; let result = self.get_value_by_cid(&canon_aggregate.value)?;
let tetraplet = self.get_tetraplet_by_cid(&canon_aggregate.tetraplet)?; let tetraplet = self.get_tetraplet_by_cid(&canon_aggregate.tetraplet)?;
@ -135,7 +135,7 @@ impl ExecutionCidState {
) -> Result<Rc<CanonResultCidAggregate>, UncatchableError> { ) -> Result<Rc<CanonResultCidAggregate>, UncatchableError> {
self.canon_result_tracker self.canon_result_tracker
.get(cid) .get(cid)
.ok_or_else(|| UncatchableError::ValueForCidNotFound("canon result aggregate", cid.clone().into())) .ok_or_else(|| UncatchableError::ValueForCidNotFound("canon result aggregate", cid.get_inner()))
} }
pub(crate) fn get_service_result_agg_by_cid( pub(crate) fn get_service_result_agg_by_cid(
@ -144,7 +144,7 @@ impl ExecutionCidState {
) -> Result<Rc<ServiceResultCidAggregate>, UncatchableError> { ) -> Result<Rc<ServiceResultCidAggregate>, UncatchableError> {
self.service_result_agg_tracker self.service_result_agg_tracker
.get(cid) .get(cid)
.ok_or_else(|| UncatchableError::ValueForCidNotFound("service result aggregate", cid.clone().into())) .ok_or_else(|| UncatchableError::ValueForCidNotFound("service result aggregate", cid.get_inner()))
} }
pub(crate) fn resolve_service_info( pub(crate) fn resolve_service_info(

View File

@ -65,9 +65,7 @@ pub(crate) fn populate_context_from_peer_service_result<'i>(
Ok(CallResult::executed_stream_stub(service_result_agg_cid)) Ok(CallResult::executed_stream_stub(service_result_agg_cid))
} }
CallOutputValue::None => { CallOutputValue::None => {
let value_cid = value_to_json_cid(&*executed_result.result) let value_cid = value_to_json_cid(&*executed_result.result).map_err(UncatchableError::from)?;
.map_err(UncatchableError::from)?
.into();
Ok(CallResult::executed_unused(value_cid)) Ok(CallResult::executed_unused(value_cid))
} }

View File

@ -29,6 +29,7 @@ use crate::JValue;
use crate::SecurityTetraplet; use crate::SecurityTetraplet;
use air_interpreter_cid::value_to_json_cid; use air_interpreter_cid::value_to_json_cid;
use air_interpreter_cid::CidRef;
use air_interpreter_data::CallResult; use air_interpreter_data::CallResult;
use air_interpreter_interface::CallRequestParams; use air_interpreter_interface::CallRequestParams;
use air_parser::ast; use air_parser::ast;
@ -102,12 +103,8 @@ impl<'i> ResolvedCall<'i> {
CheckArgsResult::Ok(args) => Some(args), CheckArgsResult::Ok(args) => Some(args),
CheckArgsResult::Joinable(_) => None, CheckArgsResult::Joinable(_) => None,
}; };
let argument_hash: Option<Rc<str>> = checked_args.map(|args| { let argument_hash: Option<Rc<CidRef>> =
value_to_json_cid(&args) checked_args.map(|args| value_to_json_cid(&args).expect("serializer shouldn't fail").get_inner());
.expect("JSON serializer shouldn't fail")
.into_inner()
.into()
});
let state = self.prepare_current_executed_state(raw_call, argument_hash.as_ref(), exec_ctx, trace_ctx)?; let state = self.prepare_current_executed_state(raw_call, argument_hash.as_ref(), exec_ctx, trace_ctx)?;

View File

@ -34,7 +34,6 @@ use air_parser::AirPos;
use air_trace_handler::merger::MergerCanonResult; use air_trace_handler::merger::MergerCanonResult;
use std::borrow::Cow; use std::borrow::Cow;
use std::rc::Rc;
impl<'i> super::ExecutableInstruction<'i> for ast::Canon<'i> { impl<'i> super::ExecutableInstruction<'i> for ast::Canon<'i> {
#[tracing::instrument(level = "debug", skip(exec_ctx, trace_ctx))] #[tracing::instrument(level = "debug", skip(exec_ctx, trace_ctx))]
@ -65,7 +64,7 @@ impl<'i> super::ExecutableInstruction<'i> for ast::Canon<'i> {
fn epilog_closure(canon_stream_name: &str) -> Box<CanonEpilogClosure<'_>> { fn epilog_closure(canon_stream_name: &str) -> Box<CanonEpilogClosure<'_>> {
Box::new( Box::new(
move |canon_stream: CanonStream, move |canon_stream: CanonStream,
canon_result_cid: Rc<CID<CanonResultCidAggregate>>, canon_result_cid: CID<CanonResultCidAggregate>,
exec_ctx: &mut ExecutionCtx<'_>, exec_ctx: &mut ExecutionCtx<'_>,
trace_ctx: &mut TraceHandler| trace_ctx: &mut TraceHandler|
-> ExecutionResult<()> { -> ExecutionResult<()> {

View File

@ -35,7 +35,6 @@ use air_parser::AirPos;
use air_trace_handler::merger::MergerCanonResult; use air_trace_handler::merger::MergerCanonResult;
use std::borrow::Cow; use std::borrow::Cow;
use std::rc::Rc;
impl<'i> super::ExecutableInstruction<'i> for ast::CanonMap<'i> { impl<'i> super::ExecutableInstruction<'i> for ast::CanonMap<'i> {
#[tracing::instrument(level = "debug", skip(exec_ctx, trace_ctx))] #[tracing::instrument(level = "debug", skip(exec_ctx, trace_ctx))]
@ -65,7 +64,7 @@ impl<'i> super::ExecutableInstruction<'i> for ast::CanonMap<'i> {
fn epilog_closure<'closure, 'name: 'closure>(canon_stream_map_name: &'name str) -> Box<CanonEpilogClosure<'closure>> { fn epilog_closure<'closure, 'name: 'closure>(canon_stream_map_name: &'name str) -> Box<CanonEpilogClosure<'closure>> {
Box::new( Box::new(
move |canon_stream: CanonStream, move |canon_stream: CanonStream,
canon_result_cid: Rc<CID<CanonResultCidAggregate>>, canon_result_cid: CID<CanonResultCidAggregate>,
exec_ctx: &mut ExecutionCtx<'_>, exec_ctx: &mut ExecutionCtx<'_>,
trace_ctx: &mut TraceHandler| trace_ctx: &mut TraceHandler|
-> ExecutionResult<()> { -> ExecutionResult<()> {

View File

@ -68,7 +68,7 @@ impl<'i> super::ExecutableInstruction<'i> for ast::CanonStreamMapScalar<'i> {
fn epilog_closure<'closure, 'name: 'closure>(scalar_name: &'name str) -> Box<CanonEpilogClosure<'closure>> { fn epilog_closure<'closure, 'name: 'closure>(scalar_name: &'name str) -> Box<CanonEpilogClosure<'closure>> {
Box::new( Box::new(
move |canon_stream: CanonStream, move |canon_stream: CanonStream,
canon_result_cid: Rc<CID<CanonResultCidAggregate>>, canon_result_cid: CID<CanonResultCidAggregate>,
exec_ctx: &mut ExecutionCtx<'_>, exec_ctx: &mut ExecutionCtx<'_>,
trace_ctx: &mut TraceHandler| trace_ctx: &mut TraceHandler|
-> ExecutionResult<()> { -> ExecutionResult<()> {

View File

@ -27,9 +27,7 @@ use air_interpreter_data::CanonResultCidAggregate;
use air_parser::ast::ResolvableToPeerIdVariable; use air_parser::ast::ResolvableToPeerIdVariable;
use polyplets::SecurityTetraplet; use polyplets::SecurityTetraplet;
use std::rc::Rc; pub(crate) type CanonEpilogClosure<'closure> = dyn Fn(CanonStream, CID<CanonResultCidAggregate>, &mut ExecutionCtx<'_>, &mut TraceHandler) -> ExecutionResult<()>
pub(crate) type CanonEpilogClosure<'closure> = dyn Fn(CanonStream, Rc<CID<CanonResultCidAggregate>>, &mut ExecutionCtx<'_>, &mut TraceHandler) -> ExecutionResult<()>
+ 'closure; + 'closure;
pub(crate) type CreateCanonStreamClosure<'closure> = dyn Fn(&mut ExecutionCtx<'_>, String) -> CanonStream + 'closure; pub(crate) type CreateCanonStreamClosure<'closure> = dyn Fn(&mut ExecutionCtx<'_>, String) -> CanonStream + 'closure;
@ -78,7 +76,7 @@ pub(crate) fn handle_canon_request_sent_by(
pub(crate) fn handle_canon_executed( pub(crate) fn handle_canon_executed(
peer_id_var: &ResolvableToPeerIdVariable<'_>, peer_id_var: &ResolvableToPeerIdVariable<'_>,
epilog: &CanonEpilogClosure<'_>, epilog: &CanonEpilogClosure<'_>,
canon_result_cid: Rc<CID<CanonResultCidAggregate>>, canon_result_cid: CID<CanonResultCidAggregate>,
exec_ctx: &mut ExecutionCtx<'_>, exec_ctx: &mut ExecutionCtx<'_>,
trace_ctx: &mut TraceHandler, trace_ctx: &mut TraceHandler,
) -> ExecutionResult<()> { ) -> ExecutionResult<()> {
@ -143,7 +141,7 @@ fn create_canon_stream_for_first_time(
fn populate_seen_cid_context( fn populate_seen_cid_context(
exec_ctx: &mut ExecutionCtx<'_>, exec_ctx: &mut ExecutionCtx<'_>,
peer_id: &str, peer_id: &str,
canon_result_cid: &Rc<CID<CanonResultCidAggregate>>, canon_result_cid: &CID<CanonResultCidAggregate>,
) { ) {
exec_ctx.record_canon_cid(peer_id, canon_result_cid) exec_ctx.record_canon_cid(peer_id, canon_result_cid)
} }
@ -151,7 +149,7 @@ fn populate_seen_cid_context(
fn populate_unseen_cid_context( fn populate_unseen_cid_context(
exec_ctx: &mut ExecutionCtx<'_>, exec_ctx: &mut ExecutionCtx<'_>,
canon_stream: &CanonStream, canon_stream: &CanonStream,
) -> ExecutionResult<Rc<CID<CanonResultCidAggregate>>> { ) -> ExecutionResult<CID<CanonResultCidAggregate>> {
let value_cids = canon_stream let value_cids = canon_stream
.iter() .iter()
.map(|canon_value| exec_ctx.cid_state.track_canon_value(canon_value)) .map(|canon_value| exec_ctx.cid_state.track_canon_value(canon_value))

View File

@ -103,11 +103,11 @@ impl fmt::Display for CanonStream {
#[derive(Debug, Clone, Deserialize, Serialize)] #[derive(Debug, Clone, Deserialize, Serialize)]
pub struct CanonStreamWithProvenance { pub struct CanonStreamWithProvenance {
pub(crate) canon_stream: CanonStream, pub(crate) canon_stream: CanonStream,
pub(crate) cid: Rc<CID<CanonResultCidAggregate>>, pub(crate) cid: CID<CanonResultCidAggregate>,
} }
impl CanonStreamWithProvenance { impl CanonStreamWithProvenance {
pub(crate) fn new(canon_stream: CanonStream, cid: Rc<CID<CanonResultCidAggregate>>) -> Self { pub(crate) fn new(canon_stream: CanonStream, cid: CID<CanonResultCidAggregate>) -> Self {
Self { canon_stream, cid } Self { canon_stream, cid }
} }
} }

View File

@ -112,11 +112,11 @@ impl fmt::Display for CanonStreamMap<'_> {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct CanonStreamMapWithProvenance<'a> { pub struct CanonStreamMapWithProvenance<'a> {
pub(crate) canon_stream_map: CanonStreamMap<'a>, pub(crate) canon_stream_map: CanonStreamMap<'a>,
pub(crate) cid: Rc<CID<CanonResultCidAggregate>>, pub(crate) cid: CID<CanonResultCidAggregate>,
} }
impl<'a> CanonStreamMapWithProvenance<'a> { impl<'a> CanonStreamMapWithProvenance<'a> {
pub(crate) fn new(canon_stream_map: CanonStreamMap<'a>, cid: Rc<CID<CanonResultCidAggregate>>) -> Self { pub(crate) fn new(canon_stream_map: CanonStreamMap<'a>, cid: CID<CanonResultCidAggregate>) -> Self {
Self { canon_stream_map, cid } Self { canon_stream_map, cid }
} }
} }

View File

@ -45,14 +45,14 @@ pub enum ValueAggregate {
result: ServiceResultAggregate, result: ServiceResultAggregate,
// the original call result CID; not changed on lambda application // the original call result CID; not changed on lambda application
#[serde(rename = "cid")] #[serde(rename = "cid")]
provenance_cid: Rc<CID<ServiceResultCidAggregate>>, provenance_cid: CID<ServiceResultCidAggregate>,
}, },
Canon { Canon {
#[serde(flatten)] #[serde(flatten)]
result: CanonResultAggregate, result: CanonResultAggregate,
// the original canon CID; not changed on lambda application // the original canon CID; not changed on lambda application
#[serde(rename = "cid")] #[serde(rename = "cid")]
provenance_cid: Rc<CID<CanonResultCidAggregate>>, provenance_cid: CID<CanonResultCidAggregate>,
}, },
} }
@ -109,7 +109,7 @@ impl ValueAggregate {
pub(crate) fn from_service_result( pub(crate) fn from_service_result(
service_result: ServiceResultAggregate, service_result: ServiceResultAggregate,
service_result_agg_cid: Rc<CID<ServiceResultCidAggregate>>, service_result_agg_cid: CID<ServiceResultCidAggregate>,
) -> Self { ) -> Self {
Self::ServiceResult { Self::ServiceResult {
result: service_result, result: service_result,
@ -119,7 +119,7 @@ impl ValueAggregate {
pub(crate) fn from_canon_result( pub(crate) fn from_canon_result(
canon_result: CanonResultAggregate, canon_result: CanonResultAggregate,
canon_result_agg_cid: Rc<CID<CanonResultCidAggregate>>, canon_result_agg_cid: CID<CanonResultCidAggregate>,
) -> Self { ) -> Self {
Self::Canon { Self::Canon {
result: canon_result, result: canon_result,

View File

@ -538,7 +538,7 @@ mod test {
let trace = ExecutionTrace::from(vec![]); let trace = ExecutionTrace::from(vec![]);
let mut trace_ctx = TraceHandler::from_trace(trace.clone(), trace); let mut trace_ctx = TraceHandler::from_trace(trace.clone(), trace);
let canon_result = CanonResult::executed(Rc::new(CID::new("fake canon CID"))); let canon_result = CanonResult::executed(CID::new("fake canon CID"));
trace_ctx.meet_canon_end(canon_result.clone()); trace_ctx.meet_canon_end(canon_result.clone());
trace_ctx.meet_canon_end(canon_result.clone()); trace_ctx.meet_canon_end(canon_result.clone());
trace_ctx.meet_canon_end(canon_result); trace_ctx.meet_canon_end(canon_result);

View File

@ -239,7 +239,7 @@ mod test {
let trace = ExecutionTrace::from(vec![]); let trace = ExecutionTrace::from(vec![]);
let mut trace_ctx = TraceHandler::from_trace(trace.clone(), trace); let mut trace_ctx = TraceHandler::from_trace(trace.clone(), trace);
let canon_result = CanonResult::executed(Rc::new(CID::new("fake canon CID"))); let canon_result = CanonResult::executed(CID::new("fake canon CID"));
trace_ctx.meet_canon_end(canon_result.clone()); trace_ctx.meet_canon_end(canon_result.clone());
trace_ctx.meet_canon_end(canon_result.clone()); trace_ctx.meet_canon_end(canon_result.clone());
trace_ctx.meet_canon_end(canon_result); trace_ctx.meet_canon_end(canon_result);

View File

@ -230,7 +230,7 @@ fn test_canon_value_not_found() {
cid_state.value_tracker = CidTracker::<_>::new(); cid_state.value_tracker = CidTracker::<_>::new();
let cur_data = raw_data_from_trace_with_canon(trace, cid_state); let cur_data = raw_data_from_trace_with_canon(trace, cid_state);
let result = call_vm!(vm, <_>::default(), air_script, vec![], cur_data); let result = call_vm!(vm, <_>::default(), air_script, vec![], cur_data);
let expected_error = ValueForCidNotFound("value", String::from(missing_cid)); let expected_error = ValueForCidNotFound("value", missing_cid.into());
assert!(check_error(&result, expected_error)); assert!(check_error(&result, expected_error));
} }
@ -281,7 +281,7 @@ fn test_canon_root_tetraplet_not_found() {
let cur_data = raw_data_from_trace_with_canon(trace, cid_state); let cur_data = raw_data_from_trace_with_canon(trace, cid_state);
let result = call_vm!(vm, <_>::default(), air_script, vec![], cur_data); let result = call_vm!(vm, <_>::default(), air_script, vec![], cur_data);
let expected_error = ValueForCidNotFound("tetraplet", String::from(missing_cid)); let expected_error = ValueForCidNotFound("tetraplet", missing_cid.into());
assert!(check_error(&result, expected_error)); assert!(check_error(&result, expected_error));
} }
@ -337,7 +337,7 @@ fn test_canon_tetraplet_not_found() {
let cur_data = raw_data_from_trace_with_canon(trace, cid_state); let cur_data = raw_data_from_trace_with_canon(trace, cid_state);
let result = call_vm!(vm, <_>::default(), air_script, vec![], cur_data); let result = call_vm!(vm, <_>::default(), air_script, vec![], cur_data);
let expected_error = ValueForCidNotFound("tetraplet", String::from(missing_cid)); let expected_error = ValueForCidNotFound("tetraplet", missing_cid.into());
assert!(check_error(&result, expected_error), "{}", result.error_message); assert!(check_error(&result, expected_error), "{}", result.error_message);
} }
@ -383,6 +383,6 @@ fn test_canon_agg_not_found() {
let cur_data = raw_data_from_trace_with_canon(trace, cid_state); let cur_data = raw_data_from_trace_with_canon(trace, cid_state);
let result = call_vm!(vm, <_>::default(), air_script, vec![], cur_data); let result = call_vm!(vm, <_>::default(), air_script, vec![], cur_data);
let expected_error = ValueForCidNotFound("canon aggregate", String::from(missing_cid)); let expected_error = ValueForCidNotFound("canon aggregate", missing_cid.into());
assert!(check_error(&result, expected_error)); assert!(check_error(&result, expected_error));
} }

View File

@ -42,7 +42,7 @@ fn test_missing_cid() {
let cur_data = raw_data_from_trace(trace, cid_state); let cur_data = raw_data_from_trace(trace, cid_state);
let result = call_vm!(vm, <_>::default(), air_script, vec![], cur_data); let result = call_vm!(vm, <_>::default(), air_script, vec![], cur_data);
let missing_cid = String::from("bagaaierajmqwu6mhm7iw5mxxy647ri6yznuwjxfm72u4u5a5zdasfid4xwiq"); let missing_cid = "bagaaierajmqwu6mhm7iw5mxxy647ri6yznuwjxfm72u4u5a5zdasfid4xwiq".into();
let expected_error = ValueForCidNotFound("service result aggregate", missing_cid); let expected_error = ValueForCidNotFound("service result aggregate", missing_cid);
assert!(check_error(&result, expected_error), "{:?}", result); assert!(check_error(&result, expected_error), "{:?}", result);
} }

View File

@ -15,11 +15,14 @@
*/ */
use air::{ExecutionCidState, PreparationError}; use air::{ExecutionCidState, PreparationError};
use air_interpreter_cid::CidRef;
use air_interpreter_signatures::{PeerCidTracker, PublicKey, SignatureStore}; use air_interpreter_signatures::{PeerCidTracker, PublicKey, SignatureStore};
use air_test_utils::key_utils::derive_dummy_keypair; use air_test_utils::key_utils::derive_dummy_keypair;
use air_test_utils::prelude::*; use air_test_utils::prelude::*;
use semver::Version; use semver::Version;
use std::rc::Rc;
/// This testing modules assert AquaVM resistance to various attacks. /// This testing modules assert AquaVM resistance to various attacks.
/// ///
/// CID store manipulations are checked in the `corruption` module. /// CID store manipulations are checked in the `corruption` module.
@ -447,7 +450,7 @@ fn test_attack_replay() {
"3eSuF5uvjQvmvSC6vu5Kmb8bJcswXhNUcqsSG9USEad1oNgnpAcBNm2maM4Tyk3BsLYnwdwNEj4KiJ4pqence7XF".to_owned(), "3eSuF5uvjQvmvSC6vu5Kmb8bJcswXhNUcqsSG9USEad1oNgnpAcBNm2maM4Tyk3BsLYnwdwNEj4KiJ4pqence7XF".to_owned(),
"6m3zmtymxDL56KBpNgKqc7QiGRuWuxr82bG2q7dF5xCD".to_owned(), "6m3zmtymxDL56KBpNgKqc7QiGRuWuxr82bG2q7dF5xCD".to_owned(),
); );
let cids: Vec<Box<str>> = vec!["bagaaieraazcwm4lxybe4pwlisvcgpv4mii63nxouogvf4ihkmz762mnhea7a".into()]; let cids: Vec<Rc<CidRef>> = vec!["bagaaieraazcwm4lxybe4pwlisvcgpv4mii63nxouogvf4ihkmz762mnhea7a".into()];
let expected = PreparationError::DataSignatureCheckError(verification::DataVerifierError::SignatureMismatch { let expected = PreparationError::DataSignatureCheckError(verification::DataVerifierError::SignatureMismatch {
error: nested_error.into(), error: nested_error.into(),
cids, cids,

View File

@ -94,7 +94,7 @@ fn test_attack_replace_value() {
&res, &res,
PreparationError::CidStoreVerificationError(CidStoreVerificationError::MismatchError { PreparationError::CidStoreVerificationError(CidStoreVerificationError::MismatchError {
type_name: "serde_json::value::Value", type_name: "serde_json::value::Value",
cid_repr: "bagaaierabjifaczkgq2745dsq57lelki2r5cfduunmfzsgvxiavi2ahwwmwq".to_owned(), cid_repr: "bagaaierabjifaczkgq2745dsq57lelki2r5cfduunmfzsgvxiavi2ahwwmwq".into(),
}) })
); );
} }
@ -167,7 +167,7 @@ fn test_attack_replace_tetraplet() {
&res, &res,
PreparationError::CidStoreVerificationError(CidStoreVerificationError::MismatchError { PreparationError::CidStoreVerificationError(CidStoreVerificationError::MismatchError {
type_name: "marine_call_parameters::SecurityTetraplet", type_name: "marine_call_parameters::SecurityTetraplet",
cid_repr: "bagaaierapisclqfeq36psuo6uxiazvcash32pndayqlwxrqchii2ykxerfba".to_owned(), cid_repr: "bagaaierapisclqfeq36psuo6uxiazvcash32pndayqlwxrqchii2ykxerfba".into(),
}) })
); );
} }
@ -196,7 +196,7 @@ fn test_attack_replace_call_result() {
let mut mallory_cid_state = ExecutionCidState::new(); let mut mallory_cid_state = ExecutionCidState::new();
let alice_trace_1 = scalar_tracked!("alice", &mut mallory_cid_state, peer = &alice_peer_id); let alice_trace_1 = scalar_tracked!("alice", &mut mallory_cid_state, peer = &alice_peer_id);
let alice_trace_1_cid = (*extract_service_result_cid(&alice_trace_1)).clone().into_inner(); let alice_trace_1_cid = extract_service_result_cid(&alice_trace_1).get_inner();
let mallory_trace = vec![ let mallory_trace = vec![
alice_trace_1, alice_trace_1,
@ -210,7 +210,7 @@ fn test_attack_replace_call_result() {
.unwrap() .unwrap()
.iter_mut() .iter_mut()
{ {
if *cid == alice_trace_1_cid { if &*cid == &*alice_trace_1_cid {
service_cid_val["argument_hash"] = "42".into(); service_cid_val["argument_hash"] = "42".into();
cnt += 1; cnt += 1;
} }
@ -247,7 +247,7 @@ fn test_attack_replace_call_result() {
&res, &res,
PreparationError::CidStoreVerificationError(CidStoreVerificationError::MismatchError { PreparationError::CidStoreVerificationError(CidStoreVerificationError::MismatchError {
type_name: "air_interpreter_data::executed_state::ServiceResultCidAggregate", type_name: "air_interpreter_data::executed_state::ServiceResultCidAggregate",
cid_repr: "bagaaierarbji6ebokx3pantdp6xg2l57bhdj7pmlydwe2wnbd6fdkatg7xka".to_owned(), cid_repr: "bagaaierarbji6ebokx3pantdp6xg2l57bhdj7pmlydwe2wnbd6fdkatg7xka".into(),
}) })
); );
} }
@ -334,7 +334,7 @@ fn test_attack_replace_canon_value() {
&res, &res,
PreparationError::CidStoreVerificationError(CidStoreVerificationError::MismatchError { PreparationError::CidStoreVerificationError(CidStoreVerificationError::MismatchError {
type_name: "air_interpreter_data::executed_state::CanonCidAggregate", type_name: "air_interpreter_data::executed_state::CanonCidAggregate",
cid_repr: "bagaaierayrb7yu6tvdofr3d7tvuzx7fb3uve27rqty4ckzy7ox66oicuhjjq".to_owned(), cid_repr: "bagaaierayrb7yu6tvdofr3d7tvuzx7fb3uve27rqty4ckzy7ox66oicuhjjq".into(),
}) })
); );
} }
@ -430,7 +430,7 @@ fn test_attack_replace_canon_result_values() {
&res, &res,
PreparationError::CidStoreVerificationError(CidStoreVerificationError::MismatchError { PreparationError::CidStoreVerificationError(CidStoreVerificationError::MismatchError {
type_name: "air_interpreter_data::executed_state::CanonResultCidAggregate", type_name: "air_interpreter_data::executed_state::CanonResultCidAggregate",
cid_repr: "bagaaieratezrhuyz2eprlmiidxywv6ir2tmswlxycad37noykg3p5oxhs5tq".to_owned(), cid_repr: "bagaaieratezrhuyz2eprlmiidxywv6ir2tmswlxycad37noykg3p5oxhs5tq".into(),
}) })
); );
} }
@ -530,7 +530,7 @@ fn test_attack_replace_canon_result_tetraplet() {
&res, &res,
PreparationError::CidStoreVerificationError(CidStoreVerificationError::MismatchError { PreparationError::CidStoreVerificationError(CidStoreVerificationError::MismatchError {
type_name: "air_interpreter_data::executed_state::CanonResultCidAggregate", type_name: "air_interpreter_data::executed_state::CanonResultCidAggregate",
cid_repr: "bagaaieratezrhuyz2eprlmiidxywv6ir2tmswlxycad37noykg3p5oxhs5tq".to_owned(), cid_repr: "bagaaieratezrhuyz2eprlmiidxywv6ir2tmswlxycad37noykg3p5oxhs5tq".into(),
}) })
); );
} }

View File

@ -126,7 +126,7 @@ fn value_for_cid_not_found() {
let data = raw_data_from_trace(wrong_trace, <_>::default()); let data = raw_data_from_trace(wrong_trace, <_>::default());
let result = peer_vm_1.call(script, "", data, <_>::default()).unwrap(); let result = peer_vm_1.call(script, "", data, <_>::default()).unwrap();
let missing_cid = String::from("bagaaierax2kxw256denmh2rmtot4cnuvz7wrf6e2l7jnxhtv3qb6xvqj2vhq"); let missing_cid = "bagaaierax2kxw256denmh2rmtot4cnuvz7wrf6e2l7jnxhtv3qb6xvqj2vhq".into();
let expected_error = ValueForCidNotFound("service result aggregate", missing_cid); let expected_error = ValueForCidNotFound("service result aggregate", missing_cid);
assert!(check_error(&result, expected_error)); assert!(check_error(&result, expected_error));
} }

View File

@ -32,18 +32,37 @@ use serde::Serialize;
use std::fmt; use std::fmt;
use std::io::BufWriter; use std::io::BufWriter;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::rc::Rc;
/// Should-be-opaque type for the inner representation of CID.
/// It has to be serializable and Borsh-serializable, as well as implement `Debug`, `Eq`, `Ord`, `Hash` and similar
/// basic traits. It is also can be unsized.
// You should be able to replace it with [u8], and most of the code will just work.
pub type CidRef = str;
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(transparent)] #[serde(transparent)]
pub struct CID<T: ?Sized>(String, #[serde(skip)] PhantomData<*const T>); pub struct CID<T: ?Sized>(Rc<CidRef>, #[serde(skip)] PhantomData<*const T>);
impl<T: ?Sized> CID<T> { impl<T: ?Sized> CID<T> {
pub fn new(cid: impl Into<String>) -> Self { pub fn new(cid: impl Into<Rc<CidRef>>) -> Self {
Self(cid.into(), PhantomData) Self(cid.into(), PhantomData)
} }
pub fn into_inner(self) -> String { pub fn get_inner(&self) -> Rc<CidRef> {
self.0 self.0.clone()
}
}
impl<T: ?Sized> std::convert::AsRef<CidRef> for CID<T> {
fn as_ref(&self) -> &CidRef {
&self.0
}
}
impl<T: ?Sized> std::borrow::Borrow<CidRef> for CID<T> {
fn borrow(&self) -> &CidRef {
&self.0
} }
} }
@ -74,12 +93,6 @@ impl<Val> std::hash::Hash for CID<Val> {
} }
} }
impl<T: ?Sized> From<CID<T>> for String {
fn from(value: CID<T>) -> Self {
value.0
}
}
// TODO we might refactor this to `SerializationFormat` trait // TODO we might refactor this to `SerializationFormat` trait
// that both transform data to binary/text form (be it JSON, CBOR or something else) // that both transform data to binary/text form (be it JSON, CBOR or something else)
// and produces CID too // and produces CID too

View File

@ -18,6 +18,7 @@ use crate::JValue;
use air_interpreter_cid::value_to_json_cid; use air_interpreter_cid::value_to_json_cid;
use air_interpreter_cid::CidCalculationError; use air_interpreter_cid::CidCalculationError;
use air_interpreter_cid::CidRef;
use air_interpreter_cid::CID; use air_interpreter_cid::CID;
use serde::Deserialize; use serde::Deserialize;
use serde::Serialize; use serde::Serialize;
@ -28,7 +29,7 @@ use std::{collections::HashMap, rc::Rc};
/// Stores CID to Value corresponance. /// Stores CID to Value corresponance.
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(transparent)] #[serde(transparent)]
pub struct CidStore<Val>(HashMap<Rc<CID<Val>>, Rc<Val>>); pub struct CidStore<Val>(HashMap<CID<Val>, Rc<Val>>);
impl<Val> CidStore<Val> { impl<Val> CidStore<Val> {
pub fn new() -> Self { pub fn new() -> Self {
@ -47,21 +48,21 @@ impl<Val> CidStore<Val> {
self.0.len() self.0.len()
} }
pub fn iter(&self) -> impl Iterator<Item = (&Rc<CID<Val>>, &Rc<Val>)> { pub fn iter(&self) -> impl Iterator<Item = (&CID<Val>, &Rc<Val>)> {
self.0.iter() self.0.iter()
} }
pub fn check_reference<Src>( pub fn check_reference<Src>(
&self, &self,
_source_cid: &CID<Src>, _source_cid: &CID<Src>,
target_cid: &Rc<CID<Val>>, target_cid: &CID<Val>,
) -> Result<(), CidStoreVerificationError> { ) -> Result<(), CidStoreVerificationError> {
self.0 self.0
.get(target_cid) .get(target_cid)
.ok_or_else(|| CidStoreVerificationError::MissingReference { .ok_or_else(|| CidStoreVerificationError::MissingReference {
source_type_name: std::any::type_name::<Src>(), source_type_name: std::any::type_name::<Src>(),
target_type_name: std::any::type_name::<Val>(), target_type_name: std::any::type_name::<Val>(),
target_cid_repr: (**target_cid).clone().into_inner(), target_cid_repr: target_cid.get_inner(),
})?; })?;
Ok(()) Ok(())
} }
@ -71,10 +72,10 @@ impl<Val: Serialize> CidStore<Val> {
pub fn verify(&self) -> Result<(), CidStoreVerificationError> { pub fn verify(&self) -> Result<(), CidStoreVerificationError> {
for (cid, value) in &self.0 { for (cid, value) in &self.0 {
let expected_cid = value_to_json_cid::<Val>(value)?; let expected_cid = value_to_json_cid::<Val>(value)?;
if expected_cid != **cid { if expected_cid != *cid {
return Err(CidStoreVerificationError::MismatchError { return Err(CidStoreVerificationError::MismatchError {
type_name: std::any::type_name::<Val>(), type_name: std::any::type_name::<Val>(),
cid_repr: (**cid).clone().into_inner(), cid_repr: (*cid).get_inner(),
}); });
} }
} }
@ -91,14 +92,14 @@ pub enum CidStoreVerificationError {
MismatchError { MismatchError {
// nb: type_name is std::any::type_name() result that may be inconsistent between the Rust compiler versions // nb: type_name is std::any::type_name() result that may be inconsistent between the Rust compiler versions
type_name: &'static str, type_name: &'static str,
cid_repr: String, cid_repr: Rc<CidRef>,
}, },
#[error("Reference CID {target_cid_repr:?} from type {source_type_name:?} to {target_type_name:?} was not found")] #[error("Reference CID {target_cid_repr:?} from type {source_type_name:?} to {target_type_name:?} was not found")]
MissingReference { MissingReference {
source_type_name: &'static str, source_type_name: &'static str,
target_type_name: &'static str, target_type_name: &'static str,
target_cid_repr: String, target_cid_repr: Rc<CidRef>,
}, },
} }
@ -110,7 +111,7 @@ impl<Val> Default for CidStore<Val> {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct CidTracker<Val = JValue> { pub struct CidTracker<Val = JValue> {
cids: HashMap<Rc<CID<Val>>, Rc<Val>>, cids: HashMap<CID<Val>, Rc<Val>>,
} }
impl<Val> CidTracker<Val> { impl<Val> CidTracker<Val> {
@ -136,9 +137,9 @@ impl<Val: Serialize> CidTracker<Val> {
pub fn track_value( pub fn track_value(
&mut self, &mut self,
value: impl Into<Rc<Val>>, value: impl Into<Rc<Val>>,
) -> Result<Rc<CID<Val>>, CidCalculationError> { ) -> Result<CID<Val>, CidCalculationError> {
let value = value.into(); let value = value.into();
let cid = Rc::new(value_to_json_cid(&*value)?); let cid = value_to_json_cid(&*value)?;
self.cids.insert(cid.clone(), value); self.cids.insert(cid.clone(), value);
Ok(cid) Ok(cid)
} }
@ -159,9 +160,9 @@ impl<Val> From<CidTracker<Val>> for CidStore<Val> {
} }
impl<Val> IntoIterator for CidStore<Val> { impl<Val> IntoIterator for CidStore<Val> {
type Item = (Rc<CID<Val>>, Rc<Val>); type Item = (CID<Val>, Rc<Val>);
type IntoIter = std::collections::hash_map::IntoIter<Rc<CID<Val>>, Rc<Val>>; type IntoIter = std::collections::hash_map::IntoIter<CID<Val>, Rc<Val>>;
fn into_iter(self) -> Self::IntoIter { fn into_iter(self) -> Self::IntoIter {
self.0.into_iter() self.0.into_iter()

View File

@ -55,7 +55,7 @@ pub enum CallResult {
/// The call returned a service error. /// The call returned a service error.
/// ///
/// The `JValue` has to be a two element array `[i32, String]`. /// The `JValue` has to be a two element array `[i32, String]`.
Failed(Rc<CID<ServiceResultCidAggregate>>), Failed(CID<ServiceResultCidAggregate>),
} }
/* /*
@ -76,21 +76,21 @@ pub enum CallResult {
* is not stored into the `value_store`: * is not stored into the `value_store`:
* *
* ``` * ```
* Unused(Rc<CID<JValue>>) ---> X * Unused(CID<JValue>) ---> X
* ``` * ```
*/ */
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub enum ValueRef { pub enum ValueRef {
/// The call value is stored to a scalar variable. /// The call value is stored to a scalar variable.
Scalar(Rc<CID<ServiceResultCidAggregate>>), Scalar(CID<ServiceResultCidAggregate>),
/// The call value is stored to a stream variable. /// The call value is stored to a stream variable.
Stream { Stream {
cid: Rc<CID<ServiceResultCidAggregate>>, cid: CID<ServiceResultCidAggregate>,
generation: GenerationIdx, generation: GenerationIdx,
}, },
/// The call value is not stored. /// The call value is not stored.
Unused(Rc<CID<JValue>>), Unused(CID<JValue>),
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
@ -114,11 +114,11 @@ impl CallServiceFailed {
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
/// A proof of service result execution result. /// A proof of service result execution result.
pub struct ServiceResultCidAggregate { pub struct ServiceResultCidAggregate {
pub value_cid: Rc<CID<JValue>>, pub value_cid: CID<JValue>,
/// Hash of the call arguments. /// Hash of the call arguments.
pub argument_hash: Rc<str>, pub argument_hash: Rc<str>,
/// The tetraplet of the call result. /// The tetraplet of the call result.
pub tetraplet_cid: Rc<CID<SecurityTetraplet>>, pub tetraplet_cid: CID<SecurityTetraplet>,
} }
/// Let's consider an example of trace that could be produces by the following fold: /// Let's consider an example of trace that could be produces by the following fold:
@ -190,21 +190,21 @@ pub enum CanonResult {
/// Request was sent to a target node by node with such public key and it shouldn't be called again. /// Request was sent to a target node by node with such public key and it shouldn't be called again.
#[serde(rename = "sent_by")] #[serde(rename = "sent_by")]
RequestSentBy(Rc<String>), RequestSentBy(Rc<String>),
Executed(Rc<CID<CanonResultCidAggregate>>), Executed(CID<CanonResultCidAggregate>),
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub struct CanonResultCidAggregate { pub struct CanonResultCidAggregate {
pub tetraplet: Rc<CID<SecurityTetraplet>>, pub tetraplet: CID<SecurityTetraplet>,
pub values: Vec<Rc<CID<CanonCidAggregate>>>, pub values: Vec<CID<CanonCidAggregate>>,
} }
/// The type Canon trace CID refers to. /// The type Canon trace CID refers to.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CanonCidAggregate { pub struct CanonCidAggregate {
pub value: Rc<CID<serde_json::Value>>, pub value: CID<serde_json::Value>,
pub tetraplet: Rc<CID<SecurityTetraplet>>, pub tetraplet: CID<SecurityTetraplet>,
pub provenance: Provenance, pub provenance: Provenance,
} }
@ -214,11 +214,11 @@ pub enum Provenance {
Literal, Literal,
ServiceResult { ServiceResult {
// the original call result CID; not changed on lambda application // the original call result CID; not changed on lambda application
cid: Rc<CID<ServiceResultCidAggregate>>, cid: CID<ServiceResultCidAggregate>,
}, },
Canon { Canon {
// the original canon CID; not changed on lambda application // the original canon CID; not changed on lambda application
cid: Rc<CID<CanonResultCidAggregate>>, cid: CID<CanonResultCidAggregate>,
}, },
} }

View File

@ -43,25 +43,25 @@ impl CallResult {
Self::Executed(value_ref) Self::Executed(value_ref)
} }
pub fn executed_scalar(service_result_agg_cid: Rc<CID<ServiceResultCidAggregate>>) -> Self { pub fn executed_scalar(service_result_agg_cid: CID<ServiceResultCidAggregate>) -> Self {
Self::executed_service_result(ValueRef::Scalar(service_result_agg_cid)) Self::executed_service_result(ValueRef::Scalar(service_result_agg_cid))
} }
pub fn executed_stream_stub(cid: Rc<CID<ServiceResultCidAggregate>>) -> CallResult { pub fn executed_stream_stub(cid: CID<ServiceResultCidAggregate>) -> CallResult {
let generation = GenerationIdx::stub(); let generation = GenerationIdx::stub();
let value = ValueRef::Stream { cid, generation }; let value = ValueRef::Stream { cid, generation };
CallResult::Executed(value) CallResult::Executed(value)
} }
pub fn executed_unused(value_cid: Rc<CID<JValue>>) -> CallResult { pub fn executed_unused(value_cid: CID<JValue>) -> CallResult {
Self::executed_service_result(ValueRef::Unused(value_cid)) Self::executed_service_result(ValueRef::Unused(value_cid))
} }
pub fn failed(service_result_agg_cid: Rc<CID<ServiceResultCidAggregate>>) -> CallResult { pub fn failed(service_result_agg_cid: CID<ServiceResultCidAggregate>) -> CallResult {
CallResult::Failed(service_result_agg_cid) CallResult::Failed(service_result_agg_cid)
} }
pub fn get_cid(&self) -> Option<&Rc<CID<ServiceResultCidAggregate>>> { pub fn get_cid(&self) -> Option<&CID<ServiceResultCidAggregate>> {
match self { match self {
CallResult::RequestSentBy(_) => None, CallResult::RequestSentBy(_) => None,
CallResult::Executed(executed) => executed.get_cid(), CallResult::Executed(executed) => executed.get_cid(),
@ -105,7 +105,7 @@ impl ApResult {
} }
impl CanonResult { impl CanonResult {
pub fn executed(cid: Rc<CID<CanonResultCidAggregate>>) -> Self { pub fn executed(cid: CID<CanonResultCidAggregate>) -> Self {
CanonResult::Executed(cid) CanonResult::Executed(cid)
} }
@ -115,18 +115,15 @@ impl CanonResult {
} }
impl CanonResultCidAggregate { impl CanonResultCidAggregate {
pub fn new( pub fn new(tetraplet: CID<SecurityTetraplet>, values: Vec<CID<CanonCidAggregate>>) -> Self {
tetraplet: Rc<CID<SecurityTetraplet>>,
values: Vec<Rc<CID<CanonCidAggregate>>>,
) -> Self {
Self { tetraplet, values } Self { tetraplet, values }
} }
} }
impl CanonCidAggregate { impl CanonCidAggregate {
pub fn new( pub fn new(
value: Rc<CID<serde_json::Value>>, value: CID<serde_json::Value>,
tetraplet: Rc<CID<SecurityTetraplet>>, tetraplet: CID<SecurityTetraplet>,
provenance: Provenance, provenance: Provenance,
) -> Self { ) -> Self {
Self { Self {
@ -139,9 +136,9 @@ impl CanonCidAggregate {
impl ServiceResultCidAggregate { impl ServiceResultCidAggregate {
pub fn new( pub fn new(
value_cid: Rc<CID<JValue>>, value_cid: CID<JValue>,
argument_hash: Rc<str>, argument_hash: Rc<str>,
tetraplet_cid: Rc<CID<SecurityTetraplet>>, tetraplet_cid: CID<SecurityTetraplet>,
) -> Self { ) -> Self {
Self { Self {
value_cid, value_cid,
@ -158,12 +155,12 @@ impl Provenance {
} }
#[inline] #[inline]
pub fn service_result(cid: Rc<CID<ServiceResultCidAggregate>>) -> Self { pub fn service_result(cid: CID<ServiceResultCidAggregate>) -> Self {
Self::ServiceResult { cid } Self::ServiceResult { cid }
} }
#[inline] #[inline]
pub fn canon(cid: Rc<CID<CanonResultCidAggregate>>) -> Self { pub fn canon(cid: CID<CanonResultCidAggregate>) -> Self {
Self::Canon { cid } Self::Canon { cid }
} }
} }
@ -211,7 +208,7 @@ impl std::fmt::Display for ExecutedState {
} }
impl ValueRef { impl ValueRef {
pub(crate) fn get_cid(&self) -> Option<&Rc<CID<ServiceResultCidAggregate>>> { pub(crate) fn get_cid(&self) -> Option<&CID<ServiceResultCidAggregate>> {
match self { match self {
ValueRef::Scalar(cid) => Some(cid), ValueRef::Scalar(cid) => Some(cid),
ValueRef::Stream { cid, .. } => Some(cid), ValueRef::Stream { cid, .. } => Some(cid),

View File

@ -14,6 +14,9 @@
* limitations under the License. * limitations under the License.
*/ */
use std::rc::Rc;
use air_interpreter_cid::CidRef;
use thiserror::Error as ThisError; use thiserror::Error as ThisError;
#[derive(Debug, ThisError)] #[derive(Debug, ThisError)]
pub enum DataVerifierError { pub enum DataVerifierError {
@ -29,7 +32,7 @@ pub enum DataVerifierError {
#[error("signature mismatch for {peer_id:?}: {error:?}, values: CIDS: {cids:?}")] #[error("signature mismatch for {peer_id:?}: {error:?}, values: CIDS: {cids:?}")]
SignatureMismatch { SignatureMismatch {
error: Box<fluence_keypair::error::VerificationError>, error: Box<fluence_keypair::error::VerificationError>,
cids: Vec<Box<str>>, cids: Vec<Rc<CidRef>>,
peer_id: String, peer_id: String,
}, },
@ -38,7 +41,7 @@ pub enum DataVerifierError {
)] )]
MergeMismatch { MergeMismatch {
peer_id: String, peer_id: String,
larger_cids: Vec<Box<str>>, larger_cids: Vec<Rc<CidRef>>,
smaller_cids: Vec<Box<str>>, smaller_cids: Vec<Rc<CidRef>>,
}, },
} }

View File

@ -21,7 +21,7 @@ use crate::ExecutedState;
use crate::ExecutionTrace; use crate::ExecutionTrace;
use crate::InterpreterData; use crate::InterpreterData;
use air_interpreter_cid::CID; use air_interpreter_cid::{CidRef, CID};
use air_interpreter_signatures::PublicKey; use air_interpreter_signatures::PublicKey;
use air_interpreter_signatures::Signature; use air_interpreter_signatures::Signature;
use air_interpreter_signatures::SignatureStore; use air_interpreter_signatures::SignatureStore;
@ -179,11 +179,11 @@ fn collect_peers_cids_from_trace<'data>(
fn try_push_cid<T>( fn try_push_cid<T>(
grouped_cids: &mut HashMap<Box<str>, PeerInfo<'_>>, grouped_cids: &mut HashMap<Box<str>, PeerInfo<'_>>,
peer_pk: &str, peer_pk: &str,
cid: &Rc<CID<T>>, cid: &CID<T>,
) -> Result<(), DataVerifierError> { ) -> Result<(), DataVerifierError> {
match grouped_cids.get_mut(peer_pk) { match grouped_cids.get_mut(peer_pk) {
Some(peer_info) => { Some(peer_info) => {
peer_info.cids.push((**cid).clone().into_inner().into()); peer_info.cids.push(cid.get_inner());
Ok(()) Ok(())
} }
None => Err(DataVerifierError::PeerIdNotFound(peer_pk.into())), None => Err(DataVerifierError::PeerIdNotFound(peer_pk.into())),
@ -214,7 +214,7 @@ fn check_cid_multiset_invariant(
} }
} }
fn to_count_map(cids: &Vec<Box<str>>) -> HashMap<&str, usize> { fn to_count_map(cids: &Vec<Rc<CidRef>>) -> HashMap<&str, usize> {
let mut count_map = HashMap::<_, usize>::new(); let mut count_map = HashMap::<_, usize>::new();
for cid in cids { for cid in cids {
// the counter can't overflow, the memory will overflow first // the counter can't overflow, the memory will overflow first
@ -244,7 +244,7 @@ struct PeerInfo<'data> {
/// A peer's signature. /// A peer's signature.
signature: &'data Signature, signature: &'data Signature,
/// Sorted vector of CIDs that belong to the peer. /// Sorted vector of CIDs that belong to the peer.
cids: Vec<Box<str>>, cids: Vec<Rc<CidRef>>,
} }
impl<'data> PeerInfo<'data> { impl<'data> PeerInfo<'data> {

View File

@ -15,6 +15,6 @@ air-interpreter-cid = { version = "0.4.0", path = "../interpreter-cid" }
fluence-keypair = { version = "0.10.1", default-features = false } fluence-keypair = { version = "0.10.1", default-features = false }
bs58 = "0.5.0" bs58 = "0.5.0"
borsh = "0.10.3" borsh = { version = "0.10.3", features = ["rc"]}
borsh-derive = "0.10.3" borsh-derive = "0.10.3"
serde = { version = "1.0.164", features = ["derive"] } serde = { version = "1.0.164", features = ["derive"] }

View File

@ -16,7 +16,7 @@
use crate::SaltedData; use crate::SaltedData;
use air_interpreter_cid::CID; use air_interpreter_cid::{CidRef, CID};
use fluence_keypair::error::SigningError; use fluence_keypair::error::SigningError;
use fluence_keypair::KeyPair; use fluence_keypair::KeyPair;
@ -26,7 +26,7 @@ use std::rc::Rc;
#[derive(Debug)] #[derive(Debug)]
pub struct PeerCidTracker { pub struct PeerCidTracker {
current_peer_id: Rc<String>, current_peer_id: Rc<String>,
cids: Vec<Box<str>>, cids: Vec<Rc<CidRef>>,
} }
impl PeerCidTracker { impl PeerCidTracker {
@ -39,7 +39,7 @@ impl PeerCidTracker {
pub fn register<T>(&mut self, peer: &str, cid: &CID<T>) { pub fn register<T>(&mut self, peer: &str, cid: &CID<T>) {
if peer == *self.current_peer_id { if peer == *self.current_peer_id {
self.cids.push(cid.clone().into_inner().into()) self.cids.push(cid.get_inner())
} }
} }
@ -53,7 +53,7 @@ impl PeerCidTracker {
} }
fn sign_cids( fn sign_cids(
mut cids: Vec<Box<str>>, mut cids: Vec<Rc<CidRef>>,
salt: &str, salt: &str,
keypair: &KeyPair, keypair: &KeyPair,
) -> Result<crate::Signature, SigningError> { ) -> Result<crate::Signature, SigningError> {

View File

@ -46,7 +46,7 @@ use std::rc::Rc;
pub fn simple_value_aggregate_cid( pub fn simple_value_aggregate_cid(
result: impl Into<serde_json::Value>, result: impl Into<serde_json::Value>,
cid_state: &mut ExecutionCidState, cid_state: &mut ExecutionCidState,
) -> Rc<CID<ServiceResultCidAggregate>> { ) -> CID<ServiceResultCidAggregate> {
let value_cid = cid_state let value_cid = cid_state
.value_tracker .value_tracker
.track_value(Rc::new(result.into())) .track_value(Rc::new(result.into()))
@ -72,7 +72,7 @@ pub fn value_aggregate_cid(
tetraplet: SecurityTetraplet, tetraplet: SecurityTetraplet,
args: Vec<serde_json::Value>, args: Vec<serde_json::Value>,
cid_state: &mut ExecutionCidState, cid_state: &mut ExecutionCidState,
) -> Rc<CID<ServiceResultCidAggregate>> { ) -> CID<ServiceResultCidAggregate> {
let value_cid = cid_state let value_cid = cid_state
.value_tracker .value_tracker
.track_value(Rc::new(result.into())) .track_value(Rc::new(result.into()))
@ -83,7 +83,7 @@ pub fn value_aggregate_cid(
.unwrap(); .unwrap();
let arguments = serde_json::Value::Array(args); let arguments = serde_json::Value::Array(args);
let argument_hash = value_to_json_cid(&arguments).unwrap().into_inner().into(); let argument_hash = value_to_json_cid(&arguments).unwrap().get_inner();
let service_result_agg = ServiceResultCidAggregate { let service_result_agg = ServiceResultCidAggregate {
value_cid, value_cid,
@ -344,7 +344,7 @@ impl ExecutedCallBuilder {
pub fn unused(self) -> ExecutedState { pub fn unused(self) -> ExecutedState {
let value_cid = value_to_json_cid(&self.result).unwrap(); let value_cid = value_to_json_cid(&self.result).unwrap();
let value = ValueRef::Unused(value_cid.into()); let value = ValueRef::Unused(value_cid);
ExecutedState::Call(CallResult::Executed(value)) ExecutedState::Call(CallResult::Executed(value))
} }
@ -389,7 +389,7 @@ impl ExecutedCallBuilder {
pub fn extract_service_result_cid( pub fn extract_service_result_cid(
stream_exec_state: &ExecutedState, stream_exec_state: &ExecutedState,
) -> Rc<CID<ServiceResultCidAggregate>> { ) -> CID<ServiceResultCidAggregate> {
match stream_exec_state { match stream_exec_state {
ExecutedState::Call(CallResult::Executed(ValueRef::Stream { cid, .. })) => cid.clone(), ExecutedState::Call(CallResult::Executed(ValueRef::Stream { cid, .. })) => cid.clone(),
ExecutedState::Call(CallResult::Executed(ValueRef::Scalar(cid))) => cid.clone(), ExecutedState::Call(CallResult::Executed(ValueRef::Scalar(cid))) => cid.clone(),
@ -397,7 +397,7 @@ pub fn extract_service_result_cid(
} }
} }
pub fn extract_canon_result_cid(canon_state: &ExecutedState) -> Rc<CID<CanonResultCidAggregate>> { pub fn extract_canon_result_cid(canon_state: &ExecutedState) -> CID<CanonResultCidAggregate> {
match canon_state { match canon_state {
ExecutedState::Canon(CanonResult::Executed(cid)) => cid.clone(), ExecutedState::Canon(CanonResult::Executed(cid)) => cid.clone(),
_ => panic!("the function is intended for executed canon only"), _ => panic!("the function is intended for executed canon only"),