Skip to content
This repository has been archived by the owner on Aug 21, 2024. It is now read-only.

Commit

Permalink
feat!: migrate to new VM, felt type, compiler and starknet-api
Browse files Browse the repository at this point in the history
Signed-off-by: Dori Medini <[email protected]>
  • Loading branch information
dorimedini-starkware committed Jun 4, 2024
1 parent f770f03 commit 4d20f71
Show file tree
Hide file tree
Showing 79 changed files with 1,797 additions and 2,613 deletions.
1,693 changes: 562 additions & 1,131 deletions Cargo.lock

Large diffs are not rendered by default.

23 changes: 12 additions & 11 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
# https://doc.rust-lang.org/cargo/reference/resolver.html#feature-resolver-version-2
resolver = "2"

members = ["crates/blockifier", "crates/native_blockifier"]
#members = ["crates/blockifier", "crates/native_blockifier"]
members = ["crates/blockifier"]

[workspace.package]
version = "0.7.0-dev.1"
version = "0.8.0-dev.0"
edition = "2021"
repository = "https://github.com/starkware-libs/blockifier/"
license = "Apache-2.0"
Expand All @@ -20,12 +21,11 @@ ark-secp256k1 = "0.4.0"
ark-secp256r1 = "0.4.0"
assert_matches = "1.5.0"
cached = "0.44.0"
cairo-felt = "0.9.1"
cairo-lang-casm = "2.6.0"
cairo-lang-runner = "2.6.0"
cairo-lang-starknet-classes = "2.6.0"
cairo-lang-utils = "2.6.0"
cairo-vm = "0.9.2"
cairo-lang-casm = "2.7.0-dev.0"
cairo-lang-runner = "2.7.0-dev.0"
cairo-lang-starknet-classes = "2.7.0-dev.0"
cairo-lang-utils = "2.7.0-dev.0"
cairo-vm = "1.0.0-rc3"
criterion = "0.3"
derive_more = "0.99.17"
glob = "0.3.1"
Expand All @@ -35,8 +35,8 @@ keccak = "0.1.3"
log = "0.4"
num-bigint = "0.4"
num-integer = "0.1.45"
num-traits = "0.2"
num-rational = { version = "0.4", features = ["serde"] }
num-traits = "0.2"
once_cell = "1.19.0"
papyrus_storage = "0.4.0-dev.1"
phf = { version = "0.11", features = ["macros"] }
Expand All @@ -50,19 +50,20 @@ serde = "1.0.184"
serde_json = "1.0.81"
sha3 = "0.10.6"
starknet-crypto = "0.5.1"
starknet_api = "0.12.0-dev.0"
starknet-types-core = { version = "0.1.2", features = ["hash", "prime-bigint"] }
starknet_api = "0.13.0-dev.4"
strum = "0.24.1"
strum_macros = "0.24.3"
tempfile = "3.7.0"
test-case = "2.2.2"
thiserror = "1.0.37"

[workspace.lints.rust]
warnings = "deny"
future-incompatible = "deny"
nonstandard-style = "deny"
rust-2018-idioms = "deny"
unused = "deny"
warnings = "deny"

[workspace.lints.clippy]
as_conversions = "deny"
15 changes: 10 additions & 5 deletions crates/blockifier/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ description = "The transaction-executing component in the Starknet sequencer."
workspace = true

[features]
testing = ["rstest"]
concurrency = []
testing = ["rstest"]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

Expand All @@ -22,7 +22,6 @@ ark-ff.workspace = true
ark-secp256k1.workspace = true
ark-secp256r1.workspace = true
cached.workspace = true
cairo-felt.workspace = true
cairo-lang-casm = { workspace = true, features = ["parity-scale-codec"] }
cairo-lang-runner.workspace = true
cairo-lang-starknet-classes.workspace = true
Expand All @@ -35,15 +34,16 @@ keccak.workspace = true
log.workspace = true
num-bigint.workspace = true
num-integer.workspace = true
num-traits.workspace = true
num-rational.workspace = true
num-traits.workspace = true
once_cell.workspace = true
phf.workspace = true
rstest = { workspace = true, optional = true }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true, features = ["arbitrary_precision"] }
sha3.workspace = true
starknet-crypto.workspace = true
starknet-types-core.workspace = true
starknet_api = { workspace = true, features = ["testing"] }
strum.workspace = true
strum_macros.workspace = true
Expand All @@ -60,6 +60,11 @@ rstest.workspace = true
test-case.workspace = true

[[bench]]
path = "bench/blockifier_bench.rs"
name = "blockifier_bench"
harness = false
name = "blockifier_bench"
path = "bench/blockifier_bench.rs"
required-features = ["testing"]

[[test]]
name = "feature_contracts_compatibility_test"
required-features = ["testing"]
23 changes: 13 additions & 10 deletions crates/blockifier/bench/blockifier_bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ use blockifier::transaction::transaction_execution::Transaction;
use criterion::{criterion_group, criterion_main, Criterion};
use rand::{Rng, SeedableRng};
use starknet_api::core::ContractAddress;
use starknet_api::hash::StarkFelt;
use starknet_api::transaction::{Calldata, Fee, TransactionVersion};
use starknet_api::{calldata, stark_felt};
use starknet_api::{calldata, felt};
use starknet_types_core::felt::Felt;

const N_ACCOUNTS: u16 = 10000;
const CHUNK_SIZE: usize = 10;
const RANDOMIZATION_SEED: u64 = 0;
const CHARGE_FEE: bool = false;
const TRANSACTION_VERSION: TransactionVersion = TransactionVersion(StarkFelt::ONE);
const TRANSACTION_VERSION: TransactionVersion = TransactionVersion(Felt::ONE);

pub fn transfers_benchmark(c: &mut Criterion) {
let account_contract = FeatureContract::AccountWithoutValidations(CairoVersion::Cairo0);
Expand Down Expand Up @@ -105,19 +105,22 @@ fn generate_transfer(
let nonce = nonce_manager.next(sender_address);

let entry_point_selector = selector_from_name(TRANSFER_ENTRY_POINT_NAME);
let contract_address = match TRANSACTION_VERSION {
TransactionVersion::ONE => *chain_info.fee_token_addresses.eth_fee_token_address.0.key(),
TransactionVersion::THREE => *chain_info.fee_token_addresses.strk_fee_token_address.0.key(),
_ => panic!("Unsupported transaction version: {TRANSACTION_VERSION:?}"),
// TODO: Make TransactionVersion an enum and use match here.
let contract_address = if TRANSACTION_VERSION == TransactionVersion::ONE {
*chain_info.fee_token_addresses.eth_fee_token_address.0.key()
} else if TRANSACTION_VERSION == TransactionVersion::THREE {
*chain_info.fee_token_addresses.strk_fee_token_address.0.key()
} else {
panic!("Unsupported transaction version: {TRANSACTION_VERSION:?}")
};

let execute_calldata = calldata![
contract_address, // Contract address.
entry_point_selector.0, // EP selector.
stark_felt!(3_u8), // Calldata length.
felt!(3_u8), // Calldata length.
*recipient_account_address.0.key(), // Calldata: recipient.
stark_felt!(1_u8), // Calldata: lsb amount.
stark_felt!(0_u8) // Calldata: msb amount.
felt!(1_u8), // Calldata: lsb amount.
felt!(0_u8) // Calldata: msb amount.
];

let tx = invoke_tx(invoke_tx_args! {
Expand Down
35 changes: 18 additions & 17 deletions crates/blockifier/src/abi/abi_utils.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
use cairo_felt::Felt252;
use num_integer::Integer;
use sha3::{Digest, Keccak256};
use starknet_api::core::{ContractAddress, EntryPointSelector, L2_ADDRESS_UPPER_BOUND};
use starknet_api::hash::{pedersen_hash, StarkFelt, StarkHash};
use starknet_api::core::{
ContractAddress, EntryPointSelector, PatriciaKey, L2_ADDRESS_UPPER_BOUND,
};
use starknet_api::state::StorageKey;
use starknet_types_core::felt::{Felt, NonZeroFelt};
use starknet_types_core::hash::{Pedersen, StarkHash};

use crate::abi::constants;
use crate::execution::execution_utils::{felt_to_stark_felt, stark_felt_to_felt};

#[cfg(test)]
#[path = "abi_utils_test.rs"]
mod test;

/// A variant of eth-keccak that computes a value that fits in a Starknet field element.
pub fn starknet_keccak(data: &[u8]) -> Felt252 {
pub fn starknet_keccak(data: &[u8]) -> Felt {
let mut hasher = Keccak256::new();
hasher.update(data);
let mut result = hasher.finalize();
let mut result: [u8; 32] = hasher.finalize().into();

// Truncate result to 250 bits.
*result.first_mut().unwrap() &= 3;
Felt252::from_bytes_be(&result)
Felt::from_bytes_be(&result)
}

/// Returns an entry point selector, given its name.
Expand All @@ -31,25 +31,26 @@ pub fn selector_from_name(entry_point_name: &str) -> EntryPointSelector {
// The default entry points selector is not being mapped in the usual way in order to save
// computations in the OS, and to avoid encoding the default entry point names there.
if DEFAULT_ENTRY_POINTS.contains(&entry_point_name) {
EntryPointSelector(StarkHash::from(constants::DEFAULT_ENTRY_POINT_SELECTOR))
EntryPointSelector(Felt::from(constants::DEFAULT_ENTRY_POINT_SELECTOR))
} else {
EntryPointSelector(felt_to_stark_felt(&starknet_keccak(entry_point_name.as_bytes())))
EntryPointSelector(starknet_keccak(entry_point_name.as_bytes()))
}
}

/// Returns the storage address of a Starknet storage variable given its name and arguments.
pub fn get_storage_var_address(storage_var_name: &str, args: &[StarkFelt]) -> StorageKey {
pub fn get_storage_var_address(storage_var_name: &str, args: &[Felt]) -> StorageKey {
let storage_var_name_hash = starknet_keccak(storage_var_name.as_bytes());
let storage_var_name_hash = felt_to_stark_felt(&storage_var_name_hash);

let storage_key_hash =
args.iter().fold(storage_var_name_hash, |res, arg| pedersen_hash(&res, arg));
args.iter().fold(storage_var_name_hash, |res, arg| Pedersen::hash(&res, arg));

let storage_key = stark_felt_to_felt(storage_key_hash)
.mod_floor(&Felt252::from_bytes_be(&L2_ADDRESS_UPPER_BOUND.to_bytes_be()));
let storage_key = storage_key_hash
.mod_floor(&NonZeroFelt::from_raw(Felt::from(*L2_ADDRESS_UPPER_BOUND).to_raw()));

StorageKey::try_from(felt_to_stark_felt(&storage_key))
.expect("Should be within bounds as retrieved mod L2_ADDRESS_UPPER_BOUND.")
StorageKey(
PatriciaKey::try_from(storage_key)
.expect("Should be within bounds as retrieved mod L2_ADDRESS_UPPER_BOUND."),
)
}

/// Returns the storage key inside the fee token corresponding to the first storage cell where the
Expand Down
15 changes: 7 additions & 8 deletions crates/blockifier/src/abi/abi_utils_test.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use cairo_felt::Felt252;
use num_bigint::BigUint;
use starknet_api::core::EntryPointSelector;
use starknet_api::hash::StarkFelt;
use starknet_api::stark_felt;
use starknet_api::felt;
use starknet_types_core::felt::Felt;

use crate::abi::abi_utils::selector_from_name;
use crate::abi::constants as abi_constants;
Expand All @@ -13,7 +12,7 @@ use crate::transaction::constants as transaction_constants;
fn test_selector_from_name() {
// Test default EP.
let expected_default_selector =
EntryPointSelector(stark_felt!(abi_constants::DEFAULT_ENTRY_POINT_SELECTOR));
EntryPointSelector(felt!(abi_constants::DEFAULT_ENTRY_POINT_SELECTOR));
assert_eq!(
selector_from_name(abi_constants::DEFAULT_ENTRY_POINT_NAME),
expected_default_selector
Expand All @@ -26,7 +25,7 @@ fn test_selector_from_name() {
// Test execute EP.
let expected_execute_selector =
"0x15d40a3d6ca2ac30f4031e42be28da9b056fef9bb7357ac5e85627ee876e5ad";
let expected_execute_selector = EntryPointSelector(stark_felt!(expected_execute_selector));
let expected_execute_selector = EntryPointSelector(felt!(expected_execute_selector));
assert_eq!(
selector_from_name(transaction_constants::EXECUTE_ENTRY_POINT_NAME),
expected_execute_selector
Expand All @@ -35,20 +34,20 @@ fn test_selector_from_name() {
// Test empty EP.
let expected_empty_selector =
"0x1d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470";
let expected_empty_selector = EntryPointSelector(stark_felt!(expected_empty_selector));
let expected_empty_selector = EntryPointSelector(felt!(expected_empty_selector));
assert_eq!(selector_from_name(""), expected_empty_selector);
}

#[test]
fn test_value_too_large_for_type() {
// Happy flow.
let n = 1991_u128;
let n_as_felt = Felt252::from(n);
let n_as_felt = Felt::from(n);
felt_to_u128(&n_as_felt).unwrap();

// Value too large for type.
let overflowed_u128: BigUint = BigUint::from(1_u8) << 128;
let overflowed_u128_as_felt = Felt252::from(overflowed_u128);
let overflowed_u128_as_felt = Felt::from(overflowed_u128);
let error = felt_to_u128(&overflowed_u128_as_felt).unwrap_err();
assert_eq!(
format!("{error}"),
Expand Down
4 changes: 2 additions & 2 deletions crates/blockifier/src/abi/constants.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use starknet_api::hash::StarkFelt;
use starknet_api::transaction::TransactionVersion;
use starknet_types_core::felt::Felt;

pub const CONSTRUCTOR_ENTRY_POINT_NAME: &str = "constructor";
pub const DEFAULT_ENTRY_POINT_NAME: &str = "__default__";
pub const DEFAULT_ENTRY_POINT_SELECTOR: u64 = 0;
pub const DEFAULT_L1_ENTRY_POINT_NAME: &str = "__l1_default__";

// The version is considered 0 for L1-Handler transaction hash calculation purposes.
pub const L1_HANDLER_VERSION: TransactionVersion = TransactionVersion(StarkFelt::ZERO);
pub const L1_HANDLER_VERSION: TransactionVersion = TransactionVersion(Felt::ZERO);

// OS-related constants.
pub const L1_TO_L2_MSG_HEADER_SIZE: usize = 5;
Expand Down
24 changes: 9 additions & 15 deletions crates/blockifier/src/abi/sierra_types.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
use cairo_felt::Felt252;
use cairo_vm::types::errors::math_errors::MathError;
use cairo_vm::types::relocatable::Relocatable;
use cairo_vm::vm::errors::memory_errors::MemoryError;
use cairo_vm::vm::vm_core::VirtualMachine;
use num_bigint::{BigUint, ToBigUint};
use num_traits::ToPrimitive;
use starknet_api::core::{ContractAddress, PatriciaKey};
use starknet_api::hash::StarkFelt;
use starknet_api::state::StorageKey;
use starknet_api::StarknetApiError;
use starknet_crypto::FieldElement;
use starknet_types_core::felt::Felt;
use thiserror::Error;

use crate::execution::execution_utils::stark_felt_to_felt;
use crate::state::errors::StateError;
use crate::state::state_api::StateReader;

Expand All @@ -21,7 +18,7 @@ pub type SierraTypeResult<T> = Result<T, SierraTypeError>;
#[derive(Debug, Error)]
pub enum SierraTypeError {
#[error("Felt {val} is too big to convert to '{ty}'.")]
ValueTooLargeForType { val: Felt252, ty: &'static str },
ValueTooLargeForType { val: Felt, ty: &'static str },
#[error(transparent)]
MemoryError(#[from] MemoryError),
#[error(transparent)]
Expand All @@ -43,16 +40,13 @@ pub trait SierraType: Sized {
}

// Utils.
pub fn felt_to_u128(felt: &Felt252) -> Result<u128, SierraTypeError> {
felt.to_u128()
.ok_or_else(|| SierraTypeError::ValueTooLargeForType { val: felt.clone(), ty: "u128" })
pub fn felt_to_u128(felt: &Felt) -> Result<u128, SierraTypeError> {
felt.to_u128().ok_or_else(|| SierraTypeError::ValueTooLargeForType { val: *felt, ty: "u128" })
}

// TODO(barak, 01/10/2023): Move to starknet_api under StorageKey implementation.
pub fn next_storage_key(key: &StorageKey) -> Result<StorageKey, StarknetApiError> {
Ok(StorageKey(PatriciaKey::try_from(StarkFelt::from(
FieldElement::from(*key.0.key()) + FieldElement::ONE,
))?))
Ok(StorageKey(PatriciaKey::try_from(*key.0.key() + Felt::ONE)?))
}

// Implementations.
Expand All @@ -72,18 +66,18 @@ impl SierraU128 {

impl SierraType for SierraU128 {
fn from_memory(vm: &VirtualMachine, ptr: &mut Relocatable) -> SierraTypeResult<Self> {
let val_as_felt = vm.get_integer(*ptr)?;
let felt = vm.get_integer(*ptr)?;
*ptr = (*ptr + 1)?;
Ok(Self { val: felt_to_u128(&val_as_felt)? })
Ok(Self { val: felt_to_u128(&felt)? })
}

fn from_storage(
state: &mut dyn StateReader,
contract_address: &ContractAddress,
key: &StorageKey,
) -> SierraTypeResult<Self> {
let val_as_felt = stark_felt_to_felt(state.get_storage_at(*contract_address, *key)?);
Ok(Self { val: felt_to_u128(&val_as_felt)? })
let felt = state.get_storage_at(*contract_address, *key)?;
Ok(Self { val: felt_to_u128(&felt)? })
}
}

Expand Down
4 changes: 2 additions & 2 deletions crates/blockifier/src/blockifier/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use std::num::NonZeroU128;

use starknet_api::block::{BlockHash, BlockNumber, BlockTimestamp};
use starknet_api::core::ContractAddress;
use starknet_api::hash::StarkFelt;
use starknet_api::state::StorageKey;
use starknet_types_core::felt::Felt;

use crate::abi::constants;
use crate::context::{BlockContext, ChainInfo};
Expand Down Expand Up @@ -90,7 +90,7 @@ pub struct BlockNumberHashPair {
}

impl BlockNumberHashPair {
pub fn new(block_number: u64, block_hash: StarkFelt) -> BlockNumberHashPair {
pub fn new(block_number: u64, block_hash: Felt) -> BlockNumberHashPair {
BlockNumberHashPair { number: BlockNumber(block_number), hash: BlockHash(block_hash) }
}
}
Loading

0 comments on commit 4d20f71

Please sign in to comment.