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

More hints #44

Merged
merged 11 commits into from
Oct 25, 2023
Merged
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Rust artifacts
Cargo.lock
target/
.idea
.vscode

# Snos artifacts
build/*
Expand Down
10 changes: 3 additions & 7 deletions scripts/setup-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@

CAIRO_VER="0.12.2"

if ! command -v cairo-compile > /dev/null
then
if ! command -v cairo-compile >/dev/null; then
echo "please start cairo($CAIRO_VER) dev environment"
exit 1
fi

if ! command -v starknet-compile-deprecated > /dev/null
then
if ! command -v starknet-compile-deprecated >/dev/null; then
echo "please start cairo($CAIRO_VER) dev environment"
exit 1
fi
Expand All @@ -19,7 +17,7 @@ git submodule update --init

FETCHED_CAIRO_VER="$(cat cairo-lang/src/starkware/cairo/lang/VERSION)"

if [ "$CAIRO_VER" != "$FETCHED_CAIRO_VER" ]; then
if [ "$CAIRO_VER" != "$FETCHED_CAIRO_VER" ]; then
echo "incorrect cairo ver($FETCHED_CAIRO_VAR) expecting $CAIROVER"
exit 1
fi
Expand All @@ -29,7 +27,6 @@ echo -e "setting up cairo dependencies...\n"
cp tests/dependencies/test_contract_interface.cairo cairo-lang/src/starkware/starknet/core/test_contract/
cp tests/dependencies/deprecated_syscalls.cairo cairo-lang/src/starkware/starknet/core/test_contract/


# setup token_for_testing path
mkdir -p cairo-lang/src/starkware/starknet/std_contracts/ERC20
cp tests/dependencies/ERC20.cairo cairo-lang/src/starkware/starknet/std_contracts/ERC20/
Expand All @@ -38,7 +35,6 @@ cp tests/dependencies/permitted.cairo cairo-lang/src/starkware/starknet/std_cont
mkdir -p cairo-lang/src/starkware/starknet/std_contracts/upgradability_proxy
cp tests/dependencies/initializable.cairo cairo-lang/src/starkware/starknet/std_contracts/upgradability_proxy


# compile cairo programs
echo -e "compmiling cairo programs...\n"
mkdir -p build/programs
Expand Down
11 changes: 11 additions & 0 deletions src/hints/hints_raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,14 @@ pub const LOAD_NEXT_TX: &str = "tx = next(transactions)\ntx_type_bytes = \
pub const LOAD_CONTRACT_ADDRESS: &str = "from starkware.starknet.business_logic.transaction.objects import \
InternalL1Handler\nids.contract_address = (\ntx.contract_address if \
isinstance(tx, InternalL1Handler) else tx.sender_address\n)";

pub const PREPARE_CONSTRUCTOR_EXECUTION: &str = "ids.contract_address_salt = tx.contract_address_salt\nids.class_hash \
= tx.class_hash\nids.constructor_calldata_size = \
len(tx.constructor_calldata)\nids.constructor_calldata = \
segments.gen_arg(arg=tx.constructor_calldata)";

pub const TRANSACTION_VERSION: &str = "memory[ap] = to_felt_or_relocatable(tx.version)";

pub const ASSERT_TRANSACTION_HASH: &str =
"assert ids.transaction_hash == tx.hash_value, (\n \"Computed transaction_hash is inconsistent with the hash \
in the transaction. \"\n f\"Computed hash = {ids.transaction_hash}, Expected hash = {tx.hash_value}.\")";
106 changes: 103 additions & 3 deletions src/hints/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ pub mod hints_raw;
use std::any::Any;
use std::collections::HashMap;
use std::rc::Rc;
use std::slice::Iter;
use std::vec::IntoIter;

use cairo_vm::felt::Felt252;
use cairo_vm::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::{
Expand All @@ -20,6 +20,9 @@ use cairo_vm::vm::errors::hint_errors::HintError;
use cairo_vm::vm::vm_core::VirtualMachine;

use crate::config::DEFAULT_INPUT_PATH;
use crate::hints::hints_raw::{
ASSERT_TRANSACTION_HASH, LOAD_NEXT_TX, PREPARE_CONSTRUCTOR_EXECUTION, TRANSACTION_VERSION,
};
use crate::io::{InternalTransaction, StarknetOsInput};

pub fn sn_hint_processor() -> BuiltinHintProcessor {
Expand Down Expand Up @@ -71,6 +74,21 @@ pub fn sn_hint_processor() -> BuiltinHintProcessor {
let transactions_len_hint = HintFunc(Box::new(transactions_len));
hint_processor.add_hint(String::from(hints_raw::TRANSACTIONS_LEN), Rc::new(transactions_len_hint));

let enter_syscall_scopes_hint = HintFunc(Box::new(enter_syscall_scopes));
hint_processor.add_hint(String::from(hints_raw::ENTER_SYSCALL_SCOPES), Rc::new(enter_syscall_scopes_hint));

let load_next_tx_hint = HintFunc(Box::new(load_next_tx));
hint_processor.add_hint(String::from(LOAD_NEXT_TX), Rc::new(load_next_tx_hint));

let prepare_constructor_execution_hint = HintFunc(Box::new(prepare_constructor_execution));
hint_processor.add_hint(String::from(PREPARE_CONSTRUCTOR_EXECUTION), Rc::new(prepare_constructor_execution_hint));

let transaction_version_hint = HintFunc(Box::new(transaction_version));
hint_processor.add_hint(String::from(TRANSACTION_VERSION), Rc::new(transaction_version_hint));

let assert_transaction_hash_hint = HintFunc(Box::new(assert_transaction_hash));
hint_processor.add_hint(String::from(ASSERT_TRANSACTION_HASH), Rc::new(assert_transaction_hash_hint));

hint_processor
}

Expand Down Expand Up @@ -242,7 +260,7 @@ pub fn enter_syscall_scopes(
_constants: &HashMap<String, Felt252>,
) -> Result<(), HintError> {
let os_input = exec_scopes.get::<StarknetOsInput>("os_input").unwrap();
let transactions: Box<dyn Any> = Box::new([os_input.transactions.into_iter()].into_iter());
let transactions: Box<dyn Any> = Box::new(os_input.transactions.into_iter());
exec_scopes.enter_scope(HashMap::from_iter([(String::from("transactions"), transactions)]));
Ok(())
}
Expand All @@ -259,9 +277,91 @@ pub fn load_next_tx(
ap_tracking: &ApTracking,
_constants: &HashMap<String, Felt252>,
) -> Result<(), HintError> {
let mut transactions = exec_scopes.get::<Iter<InternalTransaction>>("transactions")?;
let mut transactions = exec_scopes.get::<IntoIter<InternalTransaction>>("transactions")?;
// Safe to unwrap because the remaining number of txs is checked in the cairo code.
let tx = transactions.next().unwrap();
exec_scopes.insert_value("transactions", transactions);
exec_scopes.insert_value("tx", tx.clone());
insert_value_from_var_name("tx_type", Felt252::from_bytes_be(tx.r#type.as_bytes()), vm, ids_data, ap_tracking)
}

/// Implements hint:
///
/// ids.contract_address_salt = tx.contract_address_salt
/// ids.class_hash = tx.class_hash
/// ids.constructor_calldata_size = len(tx.constructor_calldata)
/// ids.constructor_calldata = segments.gen_arg(arg=tx.constructor_calldata)
pub fn prepare_constructor_execution(
vm: &mut VirtualMachine,
exec_scopes: &mut ExecutionScopes,
ids_data: &HashMap<String, HintReference>,
ap_tracking: &ApTracking,
_constants: &HashMap<String, Felt252>,
) -> Result<(), HintError> {
let tx = exec_scopes.get::<InternalTransaction>("tx")?;
insert_value_from_var_name(
"contract_address_salt",
tx.contract_address_salt.expect("`contract_address_salt` must be present"),
vm,
ids_data,
ap_tracking,
)?;
insert_value_from_var_name(
"class_hash",
// using `contract_hash` instead of `class_hash` as the that's how the
// input.json is structured
tx.contract_hash.expect("`contract_hash` must be present"),
vm,
ids_data,
ap_tracking,
)?;

let constructor_calldata_size = match &tx.constructor_calldata {
None => 0,
Some(calldata) => calldata.len(),
};
insert_value_from_var_name("constructor_calldata_size", constructor_calldata_size, vm, ids_data, ap_tracking)?;

let constructor_calldata = tx.constructor_calldata.unwrap_or_default().iter().map(|felt| felt.into()).collect();
let constructor_calldata_base = vm.add_memory_segment();
vm.load_data(constructor_calldata_base, &constructor_calldata)?;
insert_value_from_var_name("constructor_calldata", constructor_calldata_base, vm, ids_data, ap_tracking)
}

/// Implements hint:
///
/// memory[ap] = to_felt_or_relocatable(tx.version)
pub fn transaction_version(
vm: &mut VirtualMachine,
exec_scopes: &mut ExecutionScopes,
_ids_data: &HashMap<String, HintReference>,
_ap_tracking: &ApTracking,
_constants: &HashMap<String, Felt252>,
) -> Result<(), HintError> {
let tx = exec_scopes.get::<InternalTransaction>("tx")?;
insert_value_into_ap(vm, tx.version.expect("Transaction version should be set"))
}

/// Implements hint:
///
/// assert ids.transaction_hash == tx.hash_value, (
/// "Computed transaction_hash is inconsistent with the hash in the transaction. "
/// f"Computed hash = {ids.transaction_hash}, Expected hash = {tx.hash_value}.")
pub fn assert_transaction_hash(
vm: &mut VirtualMachine,
exec_scopes: &mut ExecutionScopes,
ids_data: &HashMap<String, HintReference>,
ap_tracking: &ApTracking,
_constants: &HashMap<String, Felt252>,
) -> Result<(), HintError> {
let tx = exec_scopes.get::<InternalTransaction>("tx")?;
let transaction_hash = get_integer_from_var_name("transaction_hash", vm, ids_data, ap_tracking)?.into_owned();

assert_eq!(
tx.hash_value, transaction_hash,
"Computed transaction_hash is inconsistent with the hash in the transaction. Computed hash = {}, Expected \
hash = {}.",
transaction_hash, tx.hash_value
);
Ok(())
}