Skip to content

Commit

Permalink
feat: manually specify casm hash for declare
Browse files Browse the repository at this point in the history
Allows advanced users to simply bypass the whole Sierra compilation
process by giving `starkli` a CASM hash directly.
  • Loading branch information
xJonathanLEI committed Jul 4, 2023
1 parent ff4b8c0 commit 3877ff1
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 94 deletions.
87 changes: 87 additions & 0 deletions src/casm.rs
Original file line number Diff line number Diff line change
@@ -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<CompilerVersion>,
#[clap(long, help = "Override Sierra compilation and use CASM hash directly")]
casm_hash: Option<String>,
}

#[derive(Debug)]
pub enum CasmHashSource {
BuiltInCompiler(BuiltInCompiler),
Hash(FieldElement),
}

impl CasmArgs {
pub async fn into_casm_hash_source<N>(self, network_source: N) -> Result<CasmHashSource>
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<FieldElement> {
match self {
Self::BuiltInCompiler(compiler) => compiler.compile(sierra_class),
Self::Hash(hash) => Ok(*hash),
}
}
}
112 changes: 26 additions & 86 deletions src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<CompilerVersion>,
}

#[derive(Debug)]
pub enum Compiler {
BuiltIn(CompilerVersion),
pub struct BuiltInCompiler {
version: CompilerVersion,
}

// TODO: separate known compiler versions with linked versions
Expand All @@ -36,62 +27,9 @@ pub enum CompilerVersion {
V2_0_0,
}

impl CompilerArgs {
pub async fn into_compiler<N>(self, network_source: N) -> Result<Compiler>
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<FieldElement> {
Expand All @@ -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
Expand Down Expand Up @@ -178,3 +112,9 @@ impl Display for CompilerVersion {
}
}
}

impl From<CompilerVersion> for BuiltInCompiler {
fn from(value: CompilerVersion) -> Self {
Self { version: value }
}
}
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::{provider::ProviderArgs, subcommands::*};

mod account;
mod address_book;
mod casm;
mod chain_id;
mod compiler;
mod decode;
Expand Down
27 changes: 19 additions & 8 deletions src/subcommands/declare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use starknet::{

use crate::{
account::{AccountConfig, DeploymentStatus},
compiler::CompilerArgs,
casm::{CasmArgs, CasmHashSource},
signer::SignerArgs,
utils::watch_tx,
ProviderArgs,
Expand All @@ -27,7 +27,7 @@ pub struct Declare {
#[clap(flatten)]
signer: SignerArgs,
#[clap(flatten)]
compiler: CompilerArgs,
casm: CasmArgs,
#[clap(
long,
env = "STARKNET_ACCOUNT",
Expand Down Expand Up @@ -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!(
Expand Down

0 comments on commit 3877ff1

Please sign in to comment.