feature(execution-engine): Canon data with CID (#419)

* Use CID values for tetraplets and `canon` vectors.

* Rename `cid_store` to `value_store`

It is consistent with the new `tetraplet_store` and `canon_store`
fields.

* Make canon data more typeful

The `CanonResult` doesn't take a JSON value anymore that is further
deserialized elsewhere, but is a struct that has all data deserialized.

* Typeful `CID` type

The `CID` type has a phantom type paramter defining its value's type.

* Group cid stores and trackers

Group cid stores into `CidInfo` struct, and trackers into `ExecutionCidState` struct.
This commit is contained in:
Ivan Boldyrev
2023-01-09 13:22:57 +07:00
committed by GitHub
parent f73e246a2e
commit 8f587b7803
28 changed files with 727 additions and 105 deletions

View File

@ -1,5 +1,14 @@
## Version 0.6.0
[PR 419](https://github.com/fluencelabs/aquavm/pull/419):
- Rename data's `cid_store` field to `value_store`.
- Canon data is stored with CIDs. Values, tetraplets and canon elements
are stored as CIDs resolved with data's `value_store`, `tetraplet_store`
and `canon_store` fields respectively.
- Group stores in the data into `cid_info: CidInfo` field.
## Version 0.5.0
[PR 401](https://github.com/fluencelabs/aquavm/pull/401):
- Call result values are stored as CIDs in the data trace. These CIDs refer
to a new `cid_store` data's field that maps a CID string to a value.

View File

@ -1,7 +1,7 @@
[package]
name = "air-interpreter-data"
description = "Data format of the AIR interpreter"
version = "0.5.0"
version = "0.6.0"
authors = ["Fluence Labs"]
edition = "2018"
license = "Apache-2.0"
@ -18,7 +18,8 @@ air-utils = { path = "../utils" }
air-parser = { path = "../air-parser" }
# TODO version?
air-interpreter-interface = { path = "../interpreter-interface" }
air-interpreter-cid = { version = "0.1.0", path = "../interpreter-cid" }
air-interpreter-cid = { version = "0.2.0", path = "../interpreter-cid" }
polyplets = { path = "../polyplets" }
serde = {version = "1.0.152", features = ["derive", "rc"]}
serde_json = "1.0.91"

View File

@ -27,16 +27,24 @@ use std::{collections::HashMap, rc::Rc};
/// Stores CID to Value corresponance.
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(transparent)]
pub struct CidStore<Val>(HashMap<Rc<CID>, Rc<Val>>);
pub struct CidStore<Val>(HashMap<Rc<CID<Val>>, Rc<Val>>);
impl<Val> CidStore<Val> {
pub fn new() -> Self {
Self::default()
}
pub fn get(&self, cid: &CID) -> Option<Rc<Val>> {
pub fn get(&self, cid: &CID<Val>) -> Option<Rc<Val>> {
self.0.get(cid).cloned()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn len(&self) -> usize {
self.0.len()
}
}
impl<Val> Default for CidStore<Val> {
@ -47,7 +55,7 @@ impl<Val> Default for CidStore<Val> {
#[derive(Clone, Debug)]
pub struct CidTracker<Val = JValue> {
cids: HashMap<Rc<CID>, Rc<Val>>,
cids: HashMap<Rc<CID<Val>>, Rc<Val>>,
}
impl<Val> CidTracker<Val> {
@ -64,7 +72,7 @@ impl<Val> CidTracker<Val> {
Self { cids }
}
pub fn get(&self, cid: &CID) -> Option<Rc<Val>> {
pub fn get(&self, cid: &CID<Val>) -> Option<Rc<Val>> {
self.cids.get(cid).cloned()
}
}
@ -73,9 +81,9 @@ impl<Val: Serialize> CidTracker<Val> {
pub fn record_value(
&mut self,
value: impl Into<Rc<Val>>,
) -> Result<Rc<CID>, CidCalculationError> {
) -> Result<Rc<CID<Val>>, CidCalculationError> {
let value = value.into();
let cid = Rc::new(value_to_json_cid(&value)?);
let cid = Rc::new(value_to_json_cid(&*value)?);
self.cids.insert(cid.clone(), value);
Ok(cid)
}
@ -96,9 +104,9 @@ impl<Val> From<CidTracker<Val>> for CidStore<Val> {
}
impl<Val> IntoIterator for CidStore<Val> {
type Item = (Rc<CID>, Rc<Val>);
type Item = (Rc<CID<Val>>, Rc<Val>);
type IntoIter = std::collections::hash_map::IntoIter<Rc<CID>, Rc<Val>>;
type IntoIter = std::collections::hash_map::IntoIter<Rc<CID<Val>>, Rc<Val>>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()

View File

@ -21,6 +21,7 @@ use crate::JValue;
use crate::TracePos;
use air_interpreter_cid::CID;
use polyplets::SecurityTetraplet;
use se_de::par_serializer;
use se_de::sender_serializer;
use serde::Deserialize;
@ -60,8 +61,11 @@ pub enum CallResult {
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ValueRef {
Scalar(Rc<CID>),
Stream { cid: Rc<CID>, generation: u32 },
Scalar(Rc<CID<JValue>>),
Stream {
cid: Rc<CID<JValue>>,
generation: u32,
},
}
/// Let's consider an example of trace that could be produces by the following fold:
@ -127,10 +131,18 @@ pub struct ApResult {
}
/// Contains ids of element that were on a stream at the moment of an appropriate canon call.
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct CanonResult {
pub canonicalized_element: JValue,
pub tetraplet: Rc<CID<SecurityTetraplet>>,
pub values: Vec<Rc<CID<CanonCidAggregate>>>,
}
/// The type Canon trace CID refers to.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CanonCidAggregate {
pub value: Rc<CID<serde_json::Value>>,
pub tetraplet: Rc<CID<SecurityTetraplet>>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]

View File

@ -15,6 +15,7 @@
*/
use super::*;
use crate::JValue;
impl ParResult {
pub fn new(left_size: u32, right_size: u32) -> Self {
@ -41,13 +42,13 @@ impl CallResult {
CallResult::RequestSentBy(Sender::PeerIdWithCallId { peer_id, call_id })
}
pub fn executed_scalar(cid: Rc<CID>) -> CallResult {
pub fn executed_scalar(cid: Rc<CID<JValue>>) -> CallResult {
let value = ValueRef::Scalar(cid);
CallResult::Executed(value)
}
pub fn executed_stream(cid: Rc<CID>, generation: u32) -> CallResult {
pub fn executed_stream(cid: Rc<CID<JValue>>, generation: u32) -> CallResult {
let value = ValueRef::Stream { cid, generation };
CallResult::Executed(value)
@ -87,10 +88,11 @@ impl ApResult {
}
impl CanonResult {
pub fn new(canonicalized_element: JValue) -> Self {
Self {
canonicalized_element,
}
pub fn new(
tetraplet: Rc<CID<SecurityTetraplet>>,
values: Vec<Rc<CID<CanonCidAggregate>>>,
) -> Self {
Self { tetraplet, values }
}
}

View File

@ -17,10 +17,12 @@
use super::GlobalStreamGens;
use super::RestrictedStreamGens;
use crate::cid_store::CidStore;
use crate::CanonCidAggregate;
use crate::ExecutionTrace;
use crate::JValue;
use air_utils::measure;
use polyplets::SecurityTetraplet;
use serde::Deserialize;
use serde::Serialize;
@ -57,8 +59,8 @@ pub struct InterpreterData {
/// Version of interpreter produced this data.
pub interpreter_version: semver::Version,
/// Map CID to values
pub cid_store: CidStore<JValue>,
/// CID-to-somethings mappings.
pub cid_info: CidInfo,
}
impl InterpreterData {
@ -70,20 +72,19 @@ impl InterpreterData {
last_call_request_id: 0,
restricted_streams: RestrictedStreamGens::new(),
interpreter_version,
cid_store: <_>::default(),
cid_info: <_>::default(),
}
}
#[allow(clippy::too_many_arguments)]
pub fn from_execution_result(
trace: ExecutionTrace,
streams: GlobalStreamGens,
restricted_streams: RestrictedStreamGens,
cid_store: impl Into<CidStore<JValue>>,
cid_info: CidInfo,
last_call_request_id: u32,
interpreter_version: semver::Version,
) -> Self {
let cid_store = cid_store.into();
Self {
trace,
global_streams: streams,
@ -91,7 +92,7 @@ impl InterpreterData {
last_call_request_id,
restricted_streams,
interpreter_version,
cid_store,
cid_info,
}
}
@ -114,6 +115,18 @@ impl InterpreterData {
}
}
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct CidInfo {
/// Map CID to value
pub value_store: CidStore<JValue>,
/// Map CID to a tetraplet
pub tetraplet_store: CidStore<SecurityTetraplet>,
/// Map CID to a canon value
pub canon_store: CidStore<CanonCidAggregate>,
}
#[cfg(test)]
mod tests {
use super::*;