From 3877ff166f690c25d83a362806d11bef9e5a9605 Mon Sep 17 00:00:00 2001 From: Jonathan LEI Date: Tue, 4 Jul 2023 14:06:24 +0000 Subject: [PATCH] feat: manually specify casm hash for declare Allows advanced users to simply bypass the whole Sierra compilation process by giving `starkli` a CASM hash directly. --- src/casm.rs | 87 ++++++++++++++++++++++++++++ src/compiler.rs | 112 +++++++++---------------------------- src/main.rs | 1 + src/subcommands/declare.rs | 27 ++++++--- 4 files changed, 133 insertions(+), 94 deletions(-) create mode 100644 src/casm.rs diff --git a/src/casm.rs b/src/casm.rs new file mode 100644 index 0000000..9f58a77 --- /dev/null +++ b/src/casm.rs @@ -0,0 +1,87 @@ +use anyhow::Result; +use clap::Parser; +use colored::Colorize; +use starknet::core::types::{contract::SierraClass, FieldElement}; + +use crate::{ + compiler::{BuiltInCompiler, CompilerVersion}, + network::{Network, NetworkSource}, +}; + +#[derive(Debug, Clone, Parser)] +pub struct CasmArgs { + #[clap(long, help = "Statically-linked Sierra compiler version")] + compiler_version: Option, + #[clap(long, help = "Override Sierra compilation and use CASM hash directly")] + casm_hash: Option, +} + +#[derive(Debug)] +pub enum CasmHashSource { + BuiltInCompiler(BuiltInCompiler), + Hash(FieldElement), +} + +impl CasmArgs { + pub async fn into_casm_hash_source(self, network_source: N) -> Result + where + N: NetworkSource, + { + match (self.compiler_version, self.casm_hash) { + (Some(compiler_version), None) => { + Ok(CasmHashSource::BuiltInCompiler(compiler_version.into())) + } + (None, Some(casm_hash)) => Ok(CasmHashSource::Hash(casm_hash.parse()?)), + // Tries to detect compiler version if nothing provided + (None, None) => { + eprintln!( + "Sierra compiler version not specified. \ + Attempting to automatically decide version to use..." + ); + + let network = network_source.get_network().await?; + match network { + Some(network) => { + let auto_version = match network { + Network::Mainnet => CompilerVersion::V1_1_0, + Network::Goerli1 | Network::Goerli2 | Network::Integration => { + CompilerVersion::V2_0_0 + } + }; + + eprintln!( + "Network detected: {}. \ + Using the default compiler version for this network: {}. \ + Use the --compiler-version flag to choose a different version.", + format!("{}", network).bright_yellow(), + format!("{}", auto_version).bright_yellow() + ); + + Ok(CasmHashSource::BuiltInCompiler(auto_version.into())) + } + None => { + let default_version: CompilerVersion = Default::default(); + + eprintln!( + "Unknown network. Falling back to the default compiler version {}. \ + Use the --compiler-version flag to choose a different version.", + format!("{}", default_version).bright_yellow() + ); + + Ok(CasmHashSource::BuiltInCompiler(default_version.into())) + } + } + } + _ => Err(anyhow::anyhow!("invalid casm hash options")), + } + } +} + +impl CasmHashSource { + pub fn get_casm_hash(&self, sierra_class: &SierraClass) -> Result { + match self { + Self::BuiltInCompiler(compiler) => compiler.compile(sierra_class), + Self::Hash(hash) => Ok(*hash), + } + } +} diff --git a/src/compiler.rs b/src/compiler.rs index 6fad6ce..b16d883 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -9,24 +9,15 @@ use cairo_starknet_2_0_0::{ casm_contract_class::CasmContractClass as Cairo200CasmClass, contract_class::ContractClass as Cairo200Class, }; -use clap::{builder::PossibleValue, Parser, ValueEnum}; -use colored::Colorize; +use clap::{builder::PossibleValue, ValueEnum}; use starknet::core::types::{ contract::{CompiledClass, SierraClass}, FieldElement, }; -use crate::network::{Network, NetworkSource}; - -#[derive(Debug, Clone, Parser)] -pub struct CompilerArgs { - #[clap(long, help = "Statically-linked Sierra compiler version")] - compiler_version: Option, -} - #[derive(Debug)] -pub enum Compiler { - BuiltIn(CompilerVersion), +pub struct BuiltInCompiler { + version: CompilerVersion, } // TODO: separate known compiler versions with linked versions @@ -36,62 +27,9 @@ pub enum CompilerVersion { V2_0_0, } -impl CompilerArgs { - pub async fn into_compiler(self, network_source: N) -> Result - where - N: NetworkSource, - { - match self.compiler_version { - // Always use the version directly if manually specified - Some(version) => Ok(Compiler::BuiltIn(version)), - None => { - eprintln!( - "Sierra compiler version not specified. \ - Attempting to automatically decide version to use..." - ); - - let network = network_source.get_network().await?; - match network { - Some(network) => { - let auto_version = match network { - Network::Mainnet => CompilerVersion::V1_1_0, - Network::Goerli1 | Network::Goerli2 | Network::Integration => { - CompilerVersion::V2_0_0 - } - }; - - eprintln!( - "Network detected: {}. \ - Using the default compiler version for this network: {}. \ - Use the --compiler-version flag to choose a different version.", - format!("{}", network).bright_yellow(), - format!("{}", auto_version).bright_yellow() - ); - - Ok(Compiler::BuiltIn(auto_version)) - } - None => { - let default_version: CompilerVersion = Default::default(); - - eprintln!( - "Unknown network. Falling back to the default compiler version {}. \ - Use the --compiler-version flag to choose a different version.", - format!("{}", default_version).bright_yellow() - ); - - Ok(Compiler::BuiltIn(default_version)) - } - } - } - } - } -} - -impl Compiler { +impl BuiltInCompiler { pub fn version(&self) -> CompilerVersion { - match self { - Compiler::BuiltIn(version) => *version, - } + self.version } pub fn compile(&self, class: &SierraClass) -> Result { @@ -103,31 +41,27 @@ impl Compiler { let sierra_class_json = serde_json::to_string(&class)?; - let casm_class_json = match self { - Self::BuiltIn(version) => match version { - CompilerVersion::V1_1_0 => { - // TODO: directly convert type without going through JSON - let contract_class: Cairo110Class = serde_json::from_str(&sierra_class_json)?; + let casm_class_json = match self.version { + CompilerVersion::V1_1_0 => { + // TODO: directly convert type without going through JSON + let contract_class: Cairo110Class = serde_json::from_str(&sierra_class_json)?; - // TODO: implement the `validate_compatible_sierra_version` call + // TODO: implement the `validate_compatible_sierra_version` call - let casm_contract = - Cairo110CasmClass::from_contract_class(contract_class, false)?; + let casm_contract = Cairo110CasmClass::from_contract_class(contract_class, false)?; - serde_json::to_string(&casm_contract)? - } - CompilerVersion::V2_0_0 => { - // TODO: directly convert type without going through JSON - let contract_class: Cairo200Class = serde_json::from_str(&sierra_class_json)?; + serde_json::to_string(&casm_contract)? + } + CompilerVersion::V2_0_0 => { + // TODO: directly convert type without going through JSON + let contract_class: Cairo200Class = serde_json::from_str(&sierra_class_json)?; - // TODO: implement the `validate_compatible_sierra_version` call + // TODO: implement the `validate_compatible_sierra_version` call - let casm_contract = - Cairo200CasmClass::from_contract_class(contract_class, false)?; + let casm_contract = Cairo200CasmClass::from_contract_class(contract_class, false)?; - serde_json::to_string(&casm_contract)? - } - }, + serde_json::to_string(&casm_contract)? + } }; // TODO: directly convert type without going through JSON @@ -178,3 +112,9 @@ impl Display for CompilerVersion { } } } + +impl From for BuiltInCompiler { + fn from(value: CompilerVersion) -> Self { + Self { version: value } + } +} diff --git a/src/main.rs b/src/main.rs index 5c5256d..653c906 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,6 +6,7 @@ use crate::{provider::ProviderArgs, subcommands::*}; mod account; mod address_book; +mod casm; mod chain_id; mod compiler; mod decode; diff --git a/src/subcommands/declare.rs b/src/subcommands/declare.rs index d8f636f..7855c39 100644 --- a/src/subcommands/declare.rs +++ b/src/subcommands/declare.rs @@ -14,7 +14,7 @@ use starknet::{ use crate::{ account::{AccountConfig, DeploymentStatus}, - compiler::CompilerArgs, + casm::{CasmArgs, CasmHashSource}, signer::SignerArgs, utils::watch_tx, ProviderArgs, @@ -27,7 +27,7 @@ pub struct Declare { #[clap(flatten)] signer: SignerArgs, #[clap(flatten)] - compiler: CompilerArgs, + casm: CasmArgs, #[clap( long, env = "STARKNET_ACCOUNT", @@ -80,20 +80,31 @@ impl Declare { // Declaring Cairo 1 class let class_hash = class.class_hash()?; - let compiler = self.compiler.into_compiler(&provider).await?; + let casm_source = self.casm.into_casm_hash_source(&provider).await?; if !self.estimate_only { eprintln!( "Declaring Cairo 1 class: {}", format!("{:#064x}", class_hash).bright_yellow() ); - eprintln!( - "Compiling Sierra class to CASM with compiler version {}...", - format!("{}", compiler.version()).bright_yellow() - ); + + match &casm_source { + CasmHashSource::BuiltInCompiler(compiler) => { + eprintln!( + "Compiling Sierra class to CASM with compiler version {}...", + format!("{}", compiler.version()).bright_yellow() + ); + } + CasmHashSource::Hash(hash) => { + eprintln!( + "Using the provided CASM hash: {}...", + format!("{:#064x}", hash).bright_yellow() + ); + } + } } - let casm_class_hash = compiler.compile(&class)?; + let casm_class_hash = casm_source.get_casm_hash(&class)?; if !self.estimate_only { eprintln!(