-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* WIP: Compiling raw sierra * update the interface * remove outdated todo * wip * update compilation * add sierra v1.5.0 raw compilation test * change sierra v1.5.0 raw file * unify duplicated code * review suggestions * remove unnecessary SierraArtifact, apply review suggestions * aftermerge cleaning * add command description --------- Co-authored-by: war-in <[email protected]>
- Loading branch information
Showing
23 changed files
with
378 additions
and
121 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
use anyhow::{Context, Result}; | ||
use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; | ||
use cairo_lang_starknet_classes::contract_class::ContractClass; | ||
use cairo_lang_starknet_sierra_0_1_0::casm_contract_class::CasmContractClass as CasmContractClassSierraV0; | ||
use cairo_lang_starknet_sierra_0_1_0::contract_class::ContractClass as ContractClassSierraV0; | ||
use cairo_lang_starknet_sierra_1_0_0::casm_contract_class::CasmContractClass as CasmContractClassSierraV1; | ||
use cairo_lang_starknet_sierra_1_0_0::contract_class::ContractClass as ContractClassSierraV1; | ||
use clap::Args; | ||
use serde_json::Value; | ||
use std::path::PathBuf; | ||
|
||
#[derive(Args)] | ||
pub struct CompileContract { | ||
/// Path to the sierra json file, which should have | ||
/// `sierra_program` and `entry_points_by_type` fields | ||
#[arg(short, long)] | ||
pub sierra_path: PathBuf, | ||
|
||
/// Path to where casm json file will be saved. | ||
/// It will be serialized cairo_lang_starknet::casm_contract_class::CasmContractClass | ||
#[arg(short, long)] | ||
pub output_path: Option<PathBuf>, | ||
} | ||
|
||
pub fn compile(mut sierra_json: Value) -> Result<Value> { | ||
sierra_json["abi"] = Value::Null; | ||
sierra_json["sierra_program_debug_info"] = Value::Null; | ||
sierra_json["contract_class_version"] = Value::String(String::new()); | ||
|
||
macro_rules! compile_contract { | ||
($sierra_type:ty, $casm_type:ty) => {{ | ||
let sierra_class = serde_json::from_value::<$sierra_type>(sierra_json.clone()).unwrap(); | ||
let casm_class = <$casm_type>::from_contract_class(sierra_class, true).unwrap(); | ||
return Ok(serde_json::to_value(&casm_class)?); | ||
}}; | ||
} | ||
|
||
let sierra_version = parse_sierra_version(&sierra_json)?; | ||
match sierra_version.as_slice() { | ||
[1, 2..=5, ..] => { | ||
let sierra_class: ContractClass = serde_json::from_value(sierra_json.clone()).unwrap(); | ||
let casm_class = | ||
CasmContractClass::from_contract_class(sierra_class, true, usize::MAX).unwrap(); | ||
Ok(serde_json::to_value(casm_class)?) | ||
} | ||
[1, 0..=1, 0] => compile_contract!(ContractClassSierraV1, CasmContractClassSierraV1), | ||
[0, ..] => compile_contract!(ContractClassSierraV0, CasmContractClassSierraV0), | ||
_ => { | ||
anyhow::bail!( | ||
"Unable to compile Sierra to Casm. No matching ContractClass or CasmContractClass found for version " | ||
.to_string() + &sierra_version.iter().map(|&num| num.to_string()).collect::<Vec<String>>().join("."), | ||
) | ||
} | ||
} | ||
} | ||
|
||
/// Extracts sierra version from the program | ||
/// It will not be possible to convert sierra 0.1.0 version because it keeps its version only in the first felt252 | ||
/// (as a shortstring) while other versions keep it on the first 3 (major, minor, patch) | ||
/// That's why it fallbacks to 0 when converting from Value to u8 | ||
fn parse_sierra_version(sierra_json: &Value) -> Result<Vec<u8>> { | ||
let parsed_values: Vec<u8> = sierra_json["sierra_program"] | ||
.as_array() | ||
.context("Unable to read sierra_program. Make sure it is an array of felts")? | ||
.iter() | ||
.take(3) | ||
.map(|x| u8::from_str_radix(&x.as_str().unwrap()[2..], 16).unwrap_or_default()) | ||
.collect(); | ||
|
||
Ok(parsed_values) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
use anyhow::{Context, Result}; | ||
use cairo_lang_sierra::program::Program; | ||
use cairo_lang_sierra_to_casm::compiler::{CairoProgramDebugInfo, SierraToCasmConfig}; | ||
use cairo_lang_sierra_to_casm::metadata::{calc_metadata, MetadataComputationConfig}; | ||
use clap::Args; | ||
use serde_json::{json, Value}; | ||
use std::path::PathBuf; | ||
|
||
#[derive(Args)] | ||
pub struct CompileRaw { | ||
/// Path to the sierra program json file, which should have | ||
/// `type_declarations`, `libfunc_declarations`, `statements` and `funcs` fields | ||
#[arg(short, long)] | ||
pub sierra_path: PathBuf, | ||
|
||
/// Path to where compilation result json file will be saved. | ||
/// It will consist of `assembled_cairo_program` and `debug_info` fields | ||
#[arg(short, long)] | ||
pub output_path: Option<PathBuf>, | ||
} | ||
|
||
pub fn compile(sierra_program: Value) -> Result<Value> { | ||
let sierra_program: Program = serde_json::from_value(sierra_program) | ||
.context("Unable to deserialize Sierra program. Make sure it is in a correct format")?; | ||
let metadata_config = MetadataComputationConfig::default(); | ||
let metadata = calc_metadata(&sierra_program, metadata_config)?; | ||
|
||
let cairo_program = cairo_lang_sierra_to_casm::compiler::compile( | ||
&sierra_program, | ||
&metadata, | ||
SierraToCasmConfig { | ||
gas_usage_check: true, | ||
max_bytecode_size: usize::MAX, | ||
}, | ||
)?; | ||
let assembled_cairo_program = cairo_program.assemble(); | ||
|
||
Ok(json!({ | ||
"assembled_cairo_program": { | ||
"bytecode": serde_json::to_value(assembled_cairo_program.bytecode)?, | ||
"hints": serde_json::to_value(assembled_cairo_program.hints)? | ||
}, | ||
"debug_info": serde_json::to_value(serialize_cairo_program_debug_info(&cairo_program.debug_info))? | ||
})) | ||
} | ||
|
||
fn serialize_cairo_program_debug_info(debug_info: &CairoProgramDebugInfo) -> Vec<(usize, usize)> { | ||
debug_info | ||
.sierra_statement_info | ||
.iter() | ||
.map(|statement_debug_info| { | ||
( | ||
statement_debug_info.code_offset, | ||
statement_debug_info.instruction_idx, | ||
) | ||
}) | ||
.collect() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
pub mod compile_contract; | ||
pub mod compile_raw; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,58 +1 @@ | ||
use anyhow::{Context, Result}; | ||
use serde_json::Value; | ||
|
||
use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; | ||
use cairo_lang_starknet_classes::contract_class::ContractClass; | ||
use cairo_lang_starknet_sierra_0_1_0::casm_contract_class::CasmContractClass as CasmContractClassSierraV0; | ||
use cairo_lang_starknet_sierra_0_1_0::contract_class::ContractClass as ContractClassSierraV0; | ||
use cairo_lang_starknet_sierra_1_0_0::casm_contract_class::CasmContractClass as CasmContractClassSierraV1; | ||
use cairo_lang_starknet_sierra_1_0_0::contract_class::ContractClass as ContractClassSierraV1; | ||
|
||
/// `sierra_json` should be a json containing `sierra_program` and `entry_points_by_type` | ||
pub fn compile(mut sierra_json: Value) -> Result<Value> { | ||
sierra_json["abi"] = Value::Null; | ||
sierra_json["sierra_program_debug_info"] = Value::Null; | ||
sierra_json["contract_class_version"] = Value::String(String::new()); | ||
|
||
macro_rules! compile_contract { | ||
($sierra_type:ty, $casm_type:ty) => {{ | ||
let sierra_class = serde_json::from_value::<$sierra_type>(sierra_json.clone()).unwrap(); | ||
let casm_class = <$casm_type>::from_contract_class(sierra_class, true).unwrap(); | ||
return Ok(serde_json::to_value(&casm_class)?); | ||
}}; | ||
} | ||
|
||
let sierra_version = parse_sierra_version(&sierra_json)?; | ||
match sierra_version.as_slice() { | ||
[1, 2..=5, ..] => { | ||
let sierra_class: ContractClass = serde_json::from_value(sierra_json.clone()).unwrap(); | ||
let casm_class = | ||
CasmContractClass::from_contract_class(sierra_class, true, usize::MAX).unwrap(); | ||
Ok(serde_json::to_value(casm_class)?) | ||
} | ||
[1, 0..=1, 0] => compile_contract!(ContractClassSierraV1, CasmContractClassSierraV1), | ||
[0, ..] => compile_contract!(ContractClassSierraV0, CasmContractClassSierraV0), | ||
_ => { | ||
anyhow::bail!( | ||
"Unable to compile Sierra to Casm. No matching ContractClass or CasmContractClass found for version " | ||
.to_string() + &sierra_version.iter().map(|&num| num.to_string()).collect::<Vec<String>>().join("."), | ||
) | ||
} | ||
} | ||
} | ||
|
||
/// Extracts sierra version from the program | ||
/// It will not be possible to convert sierra 0.1.0 version because it keeps its version only in the first felt252 | ||
/// (as a shortstring) while other versions keep it on the first 3 (major, minor, patch) | ||
/// That's why it fallbacks to 0 when converting from Value to u8 | ||
fn parse_sierra_version(sierra_json: &Value) -> Result<Vec<u8>> { | ||
let parsed_values: Vec<u8> = sierra_json["sierra_program"] | ||
.as_array() | ||
.context("Unable to read sierra_program. Make sure it is an array of felts")? | ||
.iter() | ||
.take(3) | ||
.map(|x| u8::from_str_radix(&x.as_str().unwrap()[2..], 16).unwrap_or_default()) | ||
.collect(); | ||
|
||
Ok(parsed_values) | ||
} | ||
pub mod commands; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Oops, something went wrong.