Skip to content

Commit

Permalink
chore: wrap cairo lang version id for code dedup
Browse files Browse the repository at this point in the history
  • Loading branch information
ArniStarkware committed Aug 8, 2024
1 parent 8b715c0 commit 52cbfd6
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 75 deletions.
134 changes: 102 additions & 32 deletions crates/gateway/src/compiler_version.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
use std::collections::BTreeMap;
use std::fmt;

use cairo_lang_starknet_classes::compiler_version::VersionId as CairoLangVersionId;
use cairo_lang_starknet_classes::contract_class::version_id_from_serialized_sierra_program;
use papyrus_config::dumping::{ser_param, SerializeConfig};
use papyrus_config::{ParamPath, ParamPrivacyInput, SerializedParam};
use serde::de::{MapAccess, Visitor};
use serde::ser::SerializeStruct;
use serde::{Deserialize, Serialize};
use starknet_sierra_compile::utils::sierra_program_as_felts_to_big_uint_as_hex;
use starknet_types_core::felt::Felt;
use thiserror::Error;
use validator::Validate;

#[derive(Debug, Error)]
#[cfg_attr(test, derive(PartialEq))]
Expand All @@ -19,38 +21,98 @@ pub enum VersionIdError {
InvalidVersion { message: String },
}

// TODO(Arni): Share this struct with the Cairo lang crate.
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Validate, PartialEq)]
pub struct VersionId {
pub major: usize,
pub minor: usize,
pub patch: usize,
}

impl VersionId {
pub const MIN: Self = Self { major: 0, minor: 0, patch: 0 };
pub const MAX: Self = Self { major: usize::MAX, minor: usize::MAX, patch: usize::MAX };
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct VersionId(pub CairoLangVersionId);

impl From<&VersionId> for CairoLangVersionId {
fn from(version: &VersionId) -> Self {
CairoLangVersionId { major: version.major, minor: version.minor, patch: version.patch }
impl std::fmt::Display for VersionId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}

impl From<&CairoLangVersionId> for VersionId {
fn from(version: &CairoLangVersionId) -> Self {
VersionId { major: version.major, minor: version.minor, patch: version.patch }
impl<'de> Deserialize<'de> for VersionId {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct VersionIdVisitor;

impl<'de> Visitor<'de> for VersionIdVisitor {
type Value = VersionId;

fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("struct VersionId")
}

fn visit_map<V>(self, mut map: V) -> Result<VersionId, V::Error>
where
V: MapAccess<'de>,
{
let mut major = None;
let mut minor = None;
let mut patch = None;

while let Some(key) = map.next_key()? {
match key {
"major" => {
if major.is_some() {
return Err(serde::de::Error::duplicate_field("major"));
}
major = Some(map.next_value()?);
}
"minor" => {
if minor.is_some() {
return Err(serde::de::Error::duplicate_field("minor"));
}
minor = Some(map.next_value()?);
}
"patch" => {
if patch.is_some() {
return Err(serde::de::Error::duplicate_field("patch"));
}
patch = Some(map.next_value()?);
}
_ => {
return Err(serde::de::Error::unknown_field(key, FIELDS));
}
}
}

let major = major.ok_or_else(|| serde::de::Error::missing_field("major"))?;
let minor = minor.ok_or_else(|| serde::de::Error::missing_field("minor"))?;
let patch = patch.ok_or_else(|| serde::de::Error::missing_field("patch"))?;

Ok(VersionId::new(major, minor, patch))
}
}

const FIELDS: &[&str] = &["major", "minor", "patch"];
deserializer.deserialize_struct("VersionId", FIELDS, VersionIdVisitor)
}
}

impl std::fmt::Display for VersionId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
CairoLangVersionId::from(self).fmt(f)
impl Serialize for VersionId {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut s = serializer.serialize_struct("VersionId", 3)?;
s.serialize_field("major", &self.0.major)?;
s.serialize_field("minor", &self.0.minor)?;
s.serialize_field("patch", &self.0.patch)?;
s.end()
}
}

impl VersionId {
pub const MIN: Self = Self(CairoLangVersionId { major: 0, minor: 0, patch: 0 });
pub const MAX: Self =
Self(CairoLangVersionId { major: usize::MAX, minor: usize::MAX, patch: usize::MAX });

pub fn new(major: usize, minor: usize, patch: usize) -> Self {
Self(CairoLangVersionId { major, minor, patch })
}

pub fn from_sierra_program(sierra_program: &[Felt]) -> Result<Self, VersionIdError> {
let sierra_program_length = sierra_program.len();

Expand All @@ -73,19 +135,27 @@ impl VersionId {
message: format!("Error extracting version ID from Sierra program: {err}"),
})?;

Ok((&version_id).into())
Ok(VersionId(version_id))
}
}

impl PartialOrd for VersionId {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
if self.major != other.major {
return Some(self.major.cmp(&other.major));
// An implementation of partial_cmp for VersionId.
fn partial_cmp(
lhs: &CairoLangVersionId,
rhs: &CairoLangVersionId,
) -> Option<std::cmp::Ordering> {
if lhs.major != rhs.major {
return Some(lhs.major.cmp(&rhs.major));
}
if lhs.minor != rhs.minor {
return Some(lhs.minor.cmp(&rhs.minor));
}
lhs.patch.partial_cmp(&rhs.patch)
}
if self.minor != other.minor {
return Some(self.minor.cmp(&other.minor));
}
self.patch.partial_cmp(&other.patch)

partial_cmp(&self.0, &other.0)
}
}

Expand All @@ -94,19 +164,19 @@ impl SerializeConfig for VersionId {
BTreeMap::from_iter([
ser_param(
"major",
&self.major,
&self.0.major,
"The major version of the configuration.",
ParamPrivacyInput::Public,
),
ser_param(
"minor",
&self.minor,
&self.0.minor,
"The minor version of the configuration.",
ParamPrivacyInput::Public,
),
ser_param(
"patch",
&self.patch,
&self.0.patch,
"The patch version of the configuration.",
ParamPrivacyInput::Public,
),
Expand Down
4 changes: 2 additions & 2 deletions crates/gateway/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ impl Default for StatelessTransactionValidatorConfig {
max_calldata_length: 4000,
max_signature_length: 4000,
max_raw_class_size: 4089446,
min_sierra_version: VersionId { major: 1, minor: 1, patch: 0 },
max_sierra_version: VersionId { major: 1, minor: 5, patch: usize::MAX },
min_sierra_version: VersionId::new(1, 1, 0),
max_sierra_version: VersionId::new(1, 5, usize::MAX),
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion crates/gateway/src/stateless_transaction_validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ impl StatelessTransactionValidator {
) -> StatelessTransactionValidatorResult<()> {
// Any patch version is valid. (i.e. when check version for upper bound, we ignore the Z
// part in a version X.Y.Z).
let max_sierra_version = VersionId { patch: usize::MAX, ..self.config.max_sierra_version };
let mut max_sierra_version = self.config.max_sierra_version;
max_sierra_version.0.patch = usize::MAX;

let sierra_version = VersionId::from_sierra_program(sierra_program)?;
if self.config.min_sierra_version <= sierra_version && sierra_version <= max_sierra_version
Expand Down
Loading

0 comments on commit 52cbfd6

Please sign in to comment.