Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(hints): add load compiled classes #22

Closed
wants to merge 10 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,8 @@ hex = "0.4.3"
indexmap = "1.9.2"
log = "0.4.19"
num-bigint = "0.4.4"
num-integer = "0.1.45"
num-traits = "0.2.16"
papyrus_storage = { git = "https://github.com/starkware-libs/papyrus.git", branch = "main", features = [
"testing",
] }
reqwest = { version = "0.11.18", features = ["blocking", "json"] }
serde = { version = "1.0.188", features = ["derive"] }
serde_json = "1.0.105"
Expand Down
3 changes: 3 additions & 0 deletions scripts/setup-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,13 @@ starknet-compile-deprecated --no_debug_info tests/contracts/dummy_token.cairo --
starknet-compile-deprecated --no_debug_info tests/contracts/delegate_proxy.cairo --output build/delegate_proxy.json --cairo_path cairo-lang/src
starknet-compile-deprecated --no_debug_info tests/contracts/test_contract2.cairo --output build/test_contract2.json --cairo_path cairo-lang/src



# compile os with debug info
cairo-compile cairo-lang/src/starkware/starknet/core/os/os.cairo --output build/os_debug.json --cairo_path cairo-lang/src

# compile cairo programs
cairo-compile tests/programs/different_output.cairo --output build/different_output.json
cairo-compile tests/programs/fact.cairo --output build/fact.json
cairo-compile tests/programs/hint.cairo --output build/hint.json
cairo-compile tests/programs/load_compiled_classes.cairo --output build/load_compiled_classes.json
6 changes: 6 additions & 0 deletions src/hints/hints_raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ os_input = StarknetOsInput.load(data=program_input)
ids.initial_carried_outputs.messages_to_l1 = segments.add_temp_segment()
ids.initial_carried_outputs.messages_to_l2 = segments.add_temp_segment()"#;

pub const LOAD_COMPILED_CLASS_FACTS: &str = r#"ids.compiled_class_facts = segments.add()
ids.n_compiled_class_facts = len(os_input.compiled_classes)
vm_enter_scope({
'compiled_class_facts': iter(os_input.compiled_classes.items()),
})"#;

pub const _VM_ENTER_SCOPE: &str = "
# This hint shouldn't be whitelisted.
vm_enter_scope(dict(
Expand Down
68 changes: 64 additions & 4 deletions src/hints/mod.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
use std::any::Any;
use std::collections::HashMap;

use cairo_vm::felt::Felt252;
use cairo_vm::hint_processor::builtin_hint_processor::hint_utils::get_ptr_from_var_name;
use cairo_vm::hint_processor::builtin_hint_processor::hint_utils::{
get_ptr_from_var_name, insert_value_from_var_name,
};
use cairo_vm::hint_processor::hint_processor_definition::HintReference;
mod hints_raw;

use crate::io::StarknetOsInput;
use cairo_vm::serde::deserialize_program::ApTracking;
use cairo_vm::types::exec_scope::ExecutionScopes;
use cairo_vm::types::relocatable::MaybeRelocatable;
use cairo_vm::vm::{errors::hint_errors::HintError, vm_core::VirtualMachine};

use std::rc::Rc;

use cairo_vm::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::{
BuiltinHintProcessor, HintFunc,
};

pub mod hints_raw;

pub fn sn_hint_processor() -> BuiltinHintProcessor {
let mut hint_processor = BuiltinHintProcessor::new_empty();

Expand All @@ -35,14 +42,16 @@ ids.initial_carried_outputs.messages_to_l2 = segments.add_temp_segment() %}
*/
pub fn starknet_os_input(
vm: &mut VirtualMachine,
_exec_scopes: &mut ExecutionScopes,
exec_scopes: &mut ExecutionScopes,
ids_data: &HashMap<String, HintReference>,
ap_tracking: &ApTracking,
_constants: &HashMap<String, Felt252>,
) -> Result<(), HintError> {
println!("Running hint {:?} {:?}", ids_data, _exec_scopes);
println!("Running hint {:?} {:?}", ids_data, exec_scopes);

// Deserialize the program_input
let os_input = Box::new(StarknetOsInput::load("tests/common/os_input.json"));
exec_scopes.assign_or_update_variable("os_input", os_input);

let initial_carried_outputs_ptr =
get_ptr_from_var_name("initial_carried_outputs", vm, ids_data, ap_tracking)?;
Expand All @@ -59,3 +68,54 @@ pub fn starknet_os_input(

Ok(())
}

/*
Implements hint:
%{
ids.compiled_class_facts = segments.add()
ids.n_compiled_class_facts = len(os_input.compiled_classes)
vm_enter_scope({
'compiled_class_facts': iter(os_input.compiled_classes.items()),
})
%}
*/
pub fn load_compiled_class_facts(
vm: &mut VirtualMachine,
exec_scopes: &mut ExecutionScopes,
ids_data: &HashMap<String, HintReference>,
ap_tracking: &ApTracking,
_constants: &HashMap<String, Felt252>,
) -> Result<(), HintError> {
// ids.compiled_class_facts = segments.add()
insert_value_from_var_name(
"compiled_class_facts",
vm.add_memory_segment(),
vm,
ids_data,
ap_tracking,
)?;
// Access the value of os_input which was loaded in a previous hint like that
// %{ os_input = ... %}
// Can't directly get os_input.compiled_classes so we need to get the whole os_input
let compiled_class_facts = exec_scopes
.get_ref::<StarknetOsInput>("os_input")?
.compiled_classes()
.clone();
// ids.n_compiled_class_facts = len(os_input.compiled_classes)
insert_value_from_var_name(
"n_compiled_class_facts",
MaybeRelocatable::Int(Felt252::new(compiled_class_facts.len())),
vm,
ids_data,
ap_tracking,
)?;
// vm_enter_scope({
// 'compiled_class_facts': iter(os_input.compiled_classes.items()),
// })
let boxed_compiled_classes: Box<dyn Any> = Box::new(compiled_class_facts.into_iter());
exec_scopes.enter_scope(HashMap::from_iter(vec![(
"compiled_class_facts".to_string(),
boxed_compiled_classes,
)]));
Ok(())
}
138 changes: 129 additions & 9 deletions src/io.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,49 @@
use std::collections::HashMap;

use cairo_felt::Felt252;
use serde::{Deserialize, Serialize};

use cairo_vm::serde::deserialize_program::deserialize_felt_hex;
use num_traits::Num;
use serde::Deserializer;
use starknet_api::deprecated_contract_class::ContractClass as DeprecatedContractClass;
use starknet_api::transaction::{MessageToL1, MessageToL2};
use std::fs;
use std::path;

use crate::{
business_logic::transaction::types::InternalTransaction, config::StarknetGeneralConfig,
state::ContractState, storage::starknet::CommitmentInfo,
};
use crate::config::StarknetGeneralConfig;

type CommitmentFacts = HashMap<Felt252, Vec<Felt252>>;

#[derive(Debug, Serialize, Deserialize)]
#[allow(unused)]
struct StarknetOsInput {
pub struct StarknetOsInput {
contract_state_commitment_info: CommitmentInfo,
contract_class_commitment_info: CommitmentInfo,
deprecated_compiled_classes: HashMap<Felt252, Felt252>, // TODO: Add contract_class module
compiled_classes: HashMap<Felt252, Felt252>, // TODO: Add contract_class module
contracts: HashMap<Felt252, ContractState>,
#[serde(deserialize_with = "parse_deprecated_classes")]
deprecated_compiled_classes: HashMap<Felt252, DeprecatedContractClass>, // TODO: Add contract_class module
#[serde(deserialize_with = "deserialize_felt_map")]
compiled_classes: HashMap<Felt252, Felt252>, // TODO: Add contract_class module
// contracts: HashMap<Felt252, ContractState>,
#[serde(deserialize_with = "deserialize_felt_map")]
class_hash_to_compiled_class_hash: HashMap<Felt252, Felt252>,
general_config: StarknetGeneralConfig,
transactions: Vec<InternalTransaction>,
// transactions: Vec<InternalTransaction>,
#[serde(deserialize_with = "deserialize_felt_hex")]
block_hash: Felt252,
}
impl StarknetOsInput {
pub fn compiled_classes(&self) -> &HashMap<Felt252, Felt252> {
&self.compiled_classes
}
}

impl StarknetOsInput {
pub fn load(path: &str) -> Self {
let raw_input = fs::read_to_string(path::PathBuf::from(path)).unwrap();
serde_json::from_str(&raw_input).unwrap()
}
}

pub struct StarknetOsOutput {
/// The state commitment before this block.
Expand All @@ -38,3 +61,100 @@ pub struct StarknetOsOutput {
/// List of messages from L1 handled in this block
pub messages_to_l2: Vec<MessageToL2>,
}

#[derive(Debug, Default, Serialize, Deserialize)]
pub struct CommitmentInfo {
#[serde(deserialize_with = "deserialize_felt_hex")]
pub previous_root: Felt252,
#[serde(deserialize_with = "deserialize_felt_hex")]
pub updated_root: Felt252,
pub(crate) tree_height: usize,
#[serde(deserialize_with = "deserialize_felt_facts")]
pub(crate) commitment_facts: CommitmentFacts,
}

pub fn deserialize_felt_facts<'de, D: Deserializer<'de>>(
deserializer: D,
) -> Result<CommitmentFacts, D::Error> {
let mut ret_map = CommitmentFacts::new();
let buf_map: HashMap<String, Vec<String>> = HashMap::deserialize(deserializer)?;
for (fact, commitments) in buf_map.into_iter() {
let fact = fact.strip_prefix("0x").unwrap();
ret_map.insert(
Felt252::from_str_radix(fact, 16).unwrap(),
commitments
.into_iter()
.map(|commit| {
Felt252::from_str_radix(commit.strip_prefix("0x").unwrap(), 16).unwrap()
})
.collect(),
);
}

Ok(ret_map)
}

pub fn parse_deprecated_classes<'de, D: Deserializer<'de>>(
deserializer: D,
) -> Result<HashMap<Felt252, DeprecatedContractClass>, D::Error> {
let mut ret_map: HashMap<Felt252, DeprecatedContractClass> = HashMap::new();
let buf: HashMap<String, String> = HashMap::deserialize(deserializer)?;
for (k, v) in buf.into_iter() {
let class_hash = Felt252::from_str_radix(k.strip_prefix("0x").unwrap(), 16).unwrap();
let raw_class = fs::read_to_string(path::PathBuf::from(v)).unwrap();
let class = serde_json::from_str(&raw_class).unwrap();
ret_map.insert(class_hash, class);
}

Ok(ret_map)
}

pub fn deserialize_felt_map<'de, D: Deserializer<'de>>(
deserializer: D,
) -> Result<HashMap<Felt252, Felt252>, D::Error> {
let mut ret_map = HashMap::new();
let buf_map: HashMap<String, String> = HashMap::deserialize(deserializer)?;
for (k, v) in buf_map.into_iter() {
let k = k.strip_prefix("0x").unwrap();
let v = v.strip_prefix("0x").unwrap();
ret_map.insert(
Felt252::from_str_radix(k, 16).unwrap(),
Felt252::from_str_radix(v, 16).unwrap(),
);
}

Ok(ret_map)
}

#[cfg(test)]
mod tests {
use super::*;

pub const TESTING_BLOCK_HASH: &str =
"59b01ba262c999f2617412ffbba780f80b0103d928cbce1aecbaa50de90abda";

#[test]
fn parse_os_input() {
let input = StarknetOsInput::load("tests/common/os_input.json");
assert_eq!(
Felt252::from_str_radix(TESTING_BLOCK_HASH, 16).unwrap(),
input.block_hash
);
assert_eq!(
Felt252::from_str_radix(
"473010ec333f16b84334f9924912d7a13ce8296b0809c2091563ddfb63011d",
16
)
.unwrap(),
input.contract_state_commitment_info.previous_root
);
assert_eq!(
Felt252::from_str_radix(
"482c9ce8a99afddc9777ff048520fcbfab6c0389f51584016c80a2e94ab8ca7",
16
)
.unwrap(),
input.contract_state_commitment_info.updated_root
);
}
}
1 change: 0 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ pub mod hints;
pub mod io;
pub mod sharp;
pub mod state;
pub mod storage;
pub mod utils;

use error::SnOsError;
Expand Down
Loading
Loading