pub(crate) mod errors;
pub(crate) mod repr;
pub mod verification;
pub use self::repr::InterpreterDataEnvelopeFormat;
pub use self::repr::InterpreterDataEnvelopeRepr;
use crate::CidInfo;
use crate::ExecutionTrace;
use air_interpreter_sede::FromSerialized;
use air_interpreter_sede::Representation;
use air_interpreter_signatures::SignatureStore;
use serde::Deserialize;
use serde::Serialize;
use std::borrow::Cow;
#[derive(Debug, thiserror::Error)]
pub enum DataDeserializationError {
#[error("failed to deserialize envelope: {0}")]
Envelope(rmp_serde::decode::Error),
#[error("failed to deserialize data: {0}")]
Data(crate::rkyv::RkyvDeserializeError),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InterpreterDataEnvelope<'a> {
#[serde(flatten)]
pub versions: Versions,
#[serde(with = "serde_bytes", borrow)]
pub inner_data: Cow<'a, [u8]>,
}
#[derive(
Debug,
Clone,
Default,
::serde::Serialize,
::serde::Deserialize,
::rkyv::Archive,
::rkyv::Serialize,
::rkyv::Deserialize,
)]
#[archive(check_bytes)]
pub struct InterpreterData {
pub trace: ExecutionTrace,
#[serde(default)]
#[serde(rename = "lcid")]
pub last_call_request_id: u32,
pub cid_info: CidInfo,
pub signatures: SignatureStore,
}
impl InterpreterData {
#[tracing::instrument(skip_all, level = "info")]
pub fn try_from_slice(slice: &[u8]) -> Result<Self, DataDeserializationError> {
let mut aligned_data = rkyv::AlignedVec::with_capacity(slice.len());
aligned_data.extend_from_slice(slice);
crate::rkyv::from_aligned_slice(&aligned_data).map_err(DataDeserializationError::Data)
}
#[tracing::instrument(skip_all, level = "info")]
pub fn serialize(&self) -> Result<Vec<u8>, crate::rkyv::RkyvSerializeError> {
crate::rkyv::to_vec(self)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Versions {
#[serde(rename = "version")] pub data_version: semver::Version,
pub interpreter_version: semver::Version,
}
impl InterpreterDataEnvelope<'_> {
pub fn new(interpreter_version: semver::Version) -> Self {
let versions = Versions::new(interpreter_version);
let inner_data = InterpreterData::default()
.serialize()
.expect("shouldn't fail on empty data")
.into();
Self {
versions,
inner_data,
}
}
#[allow(clippy::too_many_arguments)]
pub fn from_execution_result(
trace: ExecutionTrace,
cid_info: CidInfo,
signatures: SignatureStore,
last_call_request_id: u32,
interpreter_version: semver::Version,
) -> Self {
let versions = Versions::new(interpreter_version);
let inner_data = InterpreterData {
trace,
last_call_request_id,
cid_info,
signatures,
};
let inner_data = inner_data
.serialize()
.expect("shouldn't fail on valid data")
.into();
Self {
versions,
inner_data,
}
}
pub fn try_get_versions(slice: &[u8]) -> Result<Versions, DataDeserializationError> {
FromSerialized::deserialize(&InterpreterDataEnvelopeRepr, slice)
.map_err(DataDeserializationError::Envelope)
}
pub fn serialize(
&self,
) -> Result<Vec<u8>, <InterpreterDataEnvelopeRepr as Representation>::SerializeError> {
rmp_serde::to_vec_named(self)
}
}
impl<'data> InterpreterDataEnvelope<'data> {
#[tracing::instrument(skip_all, level = "info")]
pub fn try_from_slice(slice: &'data [u8]) -> Result<Self, DataDeserializationError> {
rmp_serde::from_slice(slice).map_err(DataDeserializationError::Envelope)
}
}
impl Versions {
pub fn new(interpreter_version: semver::Version) -> Self {
Self {
data_version: crate::data_version().clone(),
interpreter_version,
}
}
}