Skip to content

Commit

Permalink
Move sierra version into program serialization. (#2219)
Browse files Browse the repository at this point in the history
  • Loading branch information
gilbens-starkware committed Feb 21, 2023
1 parent 57aa81d commit c38fd76
Show file tree
Hide file tree
Showing 12 changed files with 80 additions and 62 deletions.
2 changes: 1 addition & 1 deletion crates/cairo-lang-starknet/src/allowed_libfuncs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ pub fn validate_compatible_sierra_version(
) -> Result<(), AllowedLibfuncsError> {
let list_name = list_selector.to_string();
let allowed_libfuncs = lookup_allowed_libfuncs_list(list_selector)?;
let sierra_program = sierra_from_felts(&contract.sierra_program)
let (_, sierra_program) = sierra_from_felts(&contract.sierra_program)
.map_err(|_| AllowedLibfuncsError::SierraProgramError)?;
for libfunc in sierra_program.libfunc_declarations.iter() {
if !allowed_libfuncs.allowed_libfuncs.contains(&libfunc.long_id.generic_id) {
Expand Down
2 changes: 1 addition & 1 deletion crates/cairo-lang-starknet/src/casm_contract_class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ impl CasmContractClass {
)
.unwrap();

let program = sierra_from_felts(&contract_class.sierra_program)?;
let (_, program) = sierra_from_felts(&contract_class.sierra_program)?;

let entrypoint_ids = chain!(
&contract_class.entry_points_by_type.constructor,
Expand Down
15 changes: 10 additions & 5 deletions crates/cairo-lang-starknet/src/contract_class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use crate::contract::{
use crate::db::StarknetRootDatabaseBuilderEx;
use crate::felt_serde::sierra_to_felts;
use crate::plugin::consts::{CONSTRUCTOR_MODULE, EXTERNAL_MODULE};
use crate::sierra_version::{self, VersionId};
use crate::sierra_version::{self};

#[cfg(test)]
#[path = "contract_class_test.rs"]
Expand All @@ -46,11 +46,13 @@ pub enum StarknetCompilationError {
pub struct ContractClass {
pub sierra_program: Vec<BigIntAsHex>,
pub sierra_program_debug_info: Option<cairo_lang_sierra::debug_info::DebugInfo>,
/// The sierra version used in compilation.
pub sierra_version: VersionId,
pub contract_class_version: String,
pub entry_points_by_type: ContractEntryPoints,
pub abi: Option<Contract>,
}

const DEFAULT_CONTRACT_CLASS_VERSION: &str = "0.1.0";

#[derive(Default, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct ContractEntryPoints {
#[serde(rename = "EXTERNAL")]
Expand Down Expand Up @@ -163,11 +165,14 @@ fn compile_contract_with_prepared_and_checked_db(
constructor: get_entry_points(db, &constructor_functions, &replacer)?,
};
let contract_class = ContractClass {
sierra_program: sierra_to_felts(&sierra_program)?,
sierra_program: sierra_to_felts(
sierra_version::VersionId::current_version_id(),
&sierra_program,
)?,
sierra_program_debug_info: Some(cairo_lang_sierra::debug_info::DebugInfo::extract(
&sierra_program,
)),
sierra_version: sierra_version::CURRENT_VERSION_ID,
contract_class_version: DEFAULT_CONTRACT_CLASS_VERSION.to_string(),
entry_points_by_type,
abi: Some(Contract::from_trait(db, get_abi(db, contract)?).with_context(|| "ABI error")?),
};
Expand Down
19 changes: 11 additions & 8 deletions crates/cairo-lang-starknet/src/contract_class_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ use num_bigint::BigUint;
use pretty_assertions::assert_eq;
use test_case::test_case;

use crate::contract_class::{ContractClass, ContractEntryPoint, ContractEntryPoints};
use crate::contract_class::{
ContractClass, ContractEntryPoint, ContractEntryPoints, DEFAULT_CONTRACT_CLASS_VERSION,
};
use crate::felt_serde::sierra_from_felts;
use crate::sierra_version;
use crate::test_utils::{get_example_file_path, get_test_contract};
Expand All @@ -16,7 +18,7 @@ fn test_serialization() {
let contract = ContractClass {
sierra_program: vec![],
sierra_program_debug_info: None,
sierra_version: sierra_version::CURRENT_VERSION_ID,
contract_class_version: DEFAULT_CONTRACT_CLASS_VERSION.to_string(),
entry_points_by_type: ContractEntryPoints {
external,
l1_handler: vec![],
Expand All @@ -34,11 +36,7 @@ fn test_serialization() {
{
"sierra_program": [],
"sierra_program_debug_info": null,
"sierra_version": {
"major": 0,
"minor": 1,
"patch": 0
},
"contract_class_version": "0.1.0",
"entry_points_by_type": {
"EXTERNAL": [
{
Expand Down Expand Up @@ -78,7 +76,12 @@ fn test_compile_path(example_file_name: &str) {
serde_json::to_string_pretty(&contract).unwrap() + "\n",
);

let mut sierra_program = sierra_from_felts(&contract.sierra_program).unwrap();
let (version_id, mut sierra_program) = sierra_from_felts(&contract.sierra_program).unwrap();
assert_eq!(
version_id,
sierra_version::VersionId::current_version_id(),
"Serialized Sierra version should be the current version."
);
contract.sierra_program_debug_info.unwrap().populate(&mut sierra_program);

// There is a separate file for the sierra code as it is hard to review inside the json.
Expand Down
40 changes: 35 additions & 5 deletions crates/cairo-lang-starknet/src/felt_serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use thiserror::Error;

use crate::casm_contract_class::BigIntAsHex;
use crate::contract::starknet_keccak;
use crate::sierra_version::VersionId;

#[cfg(test)]
#[path = "felt_serde_test.rs"]
Expand All @@ -39,18 +40,25 @@ pub enum FeltSerdeError {
OutOfOrderUserFunctionDeclarationsForSerialization,
#[error("Invalid function declaration for serialization.")]
FunctionArgumentsMismatchInSerialization,
#[error("The sierra version is too long and can not fit within a felt.")]
VersionIdTooLongForSerialization,
}

/// Serializes a Sierra program into a vector of felts.
pub fn sierra_to_felts(program: &Program) -> Result<Vec<BigIntAsHex>, FeltSerdeError> {
pub fn sierra_to_felts(
sierra_version: VersionId,
program: &Program,
) -> Result<Vec<BigIntAsHex>, FeltSerdeError> {
let mut serialized = vec![];
sierra_version.serialize(&mut serialized)?;
program.serialize(&mut serialized)?;
Ok(serialized)
}

/// Deserializes a Sierra program from a slice of felts.
pub fn sierra_from_felts(felts: &[BigIntAsHex]) -> Result<Program, FeltSerdeError> {
Ok(Program::deserialize(felts)?.0)
pub fn sierra_from_felts(felts: &[BigIntAsHex]) -> Result<(VersionId, Program), FeltSerdeError> {
let (version_id, program_part) = VersionId::deserialize(felts)?;
Ok((version_id, Program::deserialize(program_part)?.0))
}

/// Trait for serializing and deserializing into a felt vector.
Expand Down Expand Up @@ -139,7 +147,7 @@ impl FeltSerde for StatementIdx {
}

// Impls for generic ids.
const LONG_ID_BOUND: usize = 31;
const SHORT_STRING_BOUND: usize = 31;
lazy_static! {
/// A set of all the supported long generic ids.
static ref LONG_IDS: OrderedHashSet<&'static str> = {
Expand All @@ -157,7 +165,7 @@ macro_rules! generic_id_serde {
impl FeltSerde for $Obj {
fn serialize(&self, output: &mut Vec<BigIntAsHex>) -> Result<(), FeltSerdeError> {
output.push(BigIntAsHex {
value: if self.0.len() <= LONG_ID_BOUND {
value: if self.0.len() <= SHORT_STRING_BOUND {
BigUint::from_bytes_be(self.0.as_bytes())
} else {
if !LONG_IDS.contains(self.0.as_str()) {
Expand Down Expand Up @@ -481,3 +489,25 @@ impl FeltSerde for BranchTarget {
))
}
}

impl FeltSerde for VersionId {
fn serialize(&self, output: &mut Vec<BigIntAsHex>) -> Result<(), FeltSerdeError> {
if self.version.len() < SHORT_STRING_BOUND {
output.push(BigIntAsHex { value: BigUint::from_bytes_be(self.version.as_bytes()) });
Ok(())
} else {
Err(FeltSerdeError::VersionIdTooLongForSerialization)
}
}
fn deserialize(input: &[BigIntAsHex]) -> Result<(Self, &[BigIntAsHex]), FeltSerdeError> {
let head = input
.first()
.and_then(|id| {
std::str::from_utf8(&id.value.to_bytes_be())
.ok()
.map(|s| Self { version: s.into() })
})
.ok_or(FeltSerdeError::InvalidInputForDeserialization)?;
Ok((head, &input[1..]))
}
}
10 changes: 7 additions & 3 deletions crates/cairo-lang-starknet/src/felt_serde_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use cairo_lang_sierra_generator::replace_ids::SierraIdReplacer;
use test_case::test_case;

use super::{sierra_from_felts, sierra_to_felts};
use crate::sierra_version;
use crate::test_utils::get_example_file_path;

#[test_case("test_contract")]
Expand All @@ -20,8 +21,11 @@ fn test_felt_serde(example_file_name: &str) {
let replacer = CanonicalReplacer::from_program(&sierra);
let sierra = replacer.apply(&sierra);
pretty_assertions::assert_eq!(
sierra_from_felts(&sierra_to_felts(&sierra).expect("Serialization failed."))
.expect("Deserialization failed."),
sierra
sierra_from_felts(
&sierra_to_felts(sierra_version::VersionId::current_version_id(), &sierra)
.expect("Serialization failed.")
)
.expect("Deserialization failed."),
(sierra_version::VersionId::current_version_id(), sierra)
);
}
19 changes: 5 additions & 14 deletions crates/cairo-lang-starknet/src/sierra_version.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,10 @@
use std::fmt::{Display, Formatter};

use serde::{Deserialize, Serialize};

#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, PartialEq, Eq)]
pub struct VersionId {
major: usize,
minor: usize,
patch: usize,
pub version: String,
}

impl Display for VersionId {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}.{}.{}", self.major, self.minor, self.patch)
impl VersionId {
pub fn current_version_id() -> Self {
Self { version: "0.1.0".into() }
}
}

/// The version id to use when compiling into ContractClass.
pub const CURRENT_VERSION_ID: VersionId = VersionId { major: 0, minor: 1, patch: 0 };
7 changes: 2 additions & 5 deletions crates/cairo-lang-starknet/test_data/account.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"sierra_program": [
"0x302e312e30",
"0x0",
"0x0",
"0x0",
Expand All @@ -10,11 +11,7 @@
"libfunc_names": [],
"user_func_names": []
},
"sierra_version": {
"major": 0,
"minor": 1,
"patch": 0
},
"contract_class_version": "0.1.0",
"entry_points_by_type": {
"EXTERNAL": [],
"L1_HANDLER": [],
Expand Down
7 changes: 2 additions & 5 deletions crates/cairo-lang-starknet/test_data/erc20.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"sierra_program": [
"0x302e312e30",
"0x34",
"0x52616e6765436865636b",
"0x0",
Expand Down Expand Up @@ -38122,11 +38123,7 @@
]
]
},
"sierra_version": {
"major": 0,
"minor": 1,
"patch": 0
},
"contract_class_version": "0.1.0",
"entry_points_by_type": {
"EXTERNAL": [
{
Expand Down
7 changes: 2 additions & 5 deletions crates/cairo-lang-starknet/test_data/hello_starknet.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"sierra_program": [
"0x302e312e30",
"0x15",
"0x52616e6765436865636b",
"0x0",
Expand Down Expand Up @@ -4021,11 +4022,7 @@
]
]
},
"sierra_version": {
"major": 0,
"minor": 1,
"patch": 0
},
"contract_class_version": "0.1.0",
"entry_points_by_type": {
"EXTERNAL": [
{
Expand Down
7 changes: 2 additions & 5 deletions crates/cairo-lang-starknet/test_data/minimal_contract.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"sierra_program": [
"0x302e312e30",
"0xd",
"0x52616e6765436865636b",
"0x0",
Expand Down Expand Up @@ -1185,11 +1186,7 @@
]
]
},
"sierra_version": {
"major": 0,
"minor": 1,
"patch": 0
},
"contract_class_version": "0.1.0",
"entry_points_by_type": {
"EXTERNAL": [
{
Expand Down
7 changes: 2 additions & 5 deletions crates/cairo-lang-starknet/test_data/test_contract.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"sierra_program": [
"0x302e312e30",
"0x1e",
"0x52616e6765436865636b",
"0x0",
Expand Down Expand Up @@ -7219,11 +7220,7 @@
]
]
},
"sierra_version": {
"major": 0,
"minor": 1,
"patch": 0
},
"contract_class_version": "0.1.0",
"entry_points_by_type": {
"EXTERNAL": [
{
Expand Down

0 comments on commit c38fd76

Please sign in to comment.