Skip to content

Commit

Permalink
implement blockifier
Browse files Browse the repository at this point in the history
  • Loading branch information
greged93 committed Sep 20, 2023
1 parent 8118faa commit 33f68b2
Show file tree
Hide file tree
Showing 4 changed files with 237 additions and 0 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ chrono = { version = "0.4.26", features = ["serde"] }
ctor = "0.2.4"
dotenv = "0.15.0"
eyre = "0.6.8"
lazy_static = "1.4.0"
regex = "1.9.3"
reqwest = { version = "0.11.20", features = ["gzip"] }
rstest = "0.18.1"
Expand Down
3 changes: 3 additions & 0 deletions crates/sequencer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@ starknet_api = { workspace = true }

# Other
rustc-hash = "1.1.0"

[dev-dependencies]
lazy_static = { workspace = true }
232 changes: 232 additions & 0 deletions crates/sequencer/src/state.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
use blockifier::state::cached_state::CommitmentStateDiff;
use blockifier::state::errors::StateError;
use blockifier::state::state_api::{
State as BlockifierState, StateReader as BlockifierStateReader, StateResult,
};
use blockifier::{
execution::contract_class::ContractClass, state::cached_state::ContractStorageKey,
};
use rustc_hash::FxHashMap;
use starknet_api::core::CompiledClassHash;
use starknet_api::state::StorageKey;
use starknet_api::{
core::{ClassHash, ContractAddress, Nonce},
hash::StarkFelt,
Expand All @@ -22,3 +28,229 @@ pub struct State {
pub storage: FxHashMap<ContractStorageKey, StarkFelt>,
pub nonces: FxHashMap<ContractAddress, Nonce>,
}

impl BlockifierState for State {
fn set_storage_at(
&mut self,
contract_address: ContractAddress,
key: StorageKey,
value: StarkFelt,
) {
self.storage.insert((contract_address, key), value);
}

fn increment_nonce(&mut self, contract_address: ContractAddress) -> StateResult<()> {
let current_nonce = self
.nonces
.get(&contract_address)
.cloned()
.unwrap_or_default();

let mut current_nonce: u64 = current_nonce.0.try_into()?;
current_nonce += 1;

self.nonces
.insert(contract_address, Nonce(StarkFelt::from(current_nonce)));

Ok(())
}

fn set_class_hash_at(
&mut self,
contract_address: ContractAddress,
class_hash: ClassHash,
) -> StateResult<()> {
self.contracts.insert(contract_address, class_hash);
Ok(())
}

fn set_contract_class(
&mut self,
class_hash: &ClassHash,
contract_class: ContractClass,
) -> StateResult<()> {
self.classes.insert(class_hash.to_owned(), contract_class);
Ok(())
}

fn set_compiled_class_hash(
&mut self,
class_hash: ClassHash,
compiled_class_hash: CompiledClassHash,
) -> StateResult<()> {
self.compiled_classes
.insert(class_hash, compiled_class_hash);
Ok(())
}

fn to_state_diff(&self) -> CommitmentStateDiff {
unreachable!("to_state_diff should not be called in the sequencer")
}
}

impl BlockifierStateReader for State {
/// Default: 0 for an uninitialized contract address.
fn get_storage_at(
&mut self,
contract_address: ContractAddress,
key: StorageKey,
) -> StateResult<StarkFelt> {
Ok(self
.storage
.get(&(contract_address, key))
.cloned()
.unwrap_or_default())
}

/// Default: 0 for an uninitialized contract address.
fn get_nonce_at(&mut self, contract_address: ContractAddress) -> StateResult<Nonce> {
Ok(self
.nonces
.get(&contract_address)
.cloned()
.unwrap_or_default())
}

/// Default: 0 (uninitialized class hash) for an uninitialized contract address.
fn get_class_hash_at(&mut self, contract_address: ContractAddress) -> StateResult<ClassHash> {
Ok(self
.contracts
.get(&contract_address)
.cloned()
.unwrap_or_default())
}

/// Errors if the compiled class hash is not declared.
fn get_compiled_contract_class(
&mut self,
class_hash: &ClassHash,
) -> StateResult<ContractClass> {
self.classes
.get(class_hash)
.cloned()
.ok_or_else(|| StateError::UndeclaredClassHash(class_hash.to_owned()))
}

/// Errors if the class hash is not declared.
fn get_compiled_class_hash(&mut self, class_hash: ClassHash) -> StateResult<CompiledClassHash> {
self.compiled_classes
.get(&class_hash)
.cloned()
.ok_or_else(|| StateError::UndeclaredClassHash(class_hash))
}
}

#[cfg(test)]
mod tests {
use blockifier::execution::contract_class::ContractClassV0;
use starknet_api::core::PatriciaKey;

use super::*;
lazy_static::lazy_static! {
static ref ONE_FELT: StarkFelt = StarkFelt::from(1u8);
static ref ONE_PATRICIA: PatriciaKey = TryInto::<PatriciaKey>::try_into(*ONE_FELT).unwrap();
static ref ONE_HASH: ClassHash = ClassHash(*ONE_FELT);
static ref ONE_COMPILED_HASH: CompiledClassHash = CompiledClassHash(*ONE_FELT);
static ref TEST_ADDRESS: ContractAddress = ContractAddress(*ONE_PATRICIA);
}

#[test]
fn test_storage() {
// Given
let mut state = State::default();

// When
state.set_storage_at(*TEST_ADDRESS, StorageKey(*ONE_PATRICIA), *ONE_FELT);

// Then
let expected = *ONE_FELT;
let actual = state
.get_storage_at(*TEST_ADDRESS, StorageKey(*ONE_PATRICIA))
.unwrap();
assert_eq!(expected, actual);
}

#[test]
fn test_nonce() {
// Given
let mut state = State::default();

// When
state.increment_nonce(*TEST_ADDRESS).unwrap();

// Then
let expected = Nonce(*ONE_FELT);
let actual = state.get_nonce_at(*TEST_ADDRESS).unwrap();
assert_eq!(expected, actual);
}

#[test]
fn test_class_hash() {
// Given
let mut state = State::default();

// When
state.set_class_hash_at(*TEST_ADDRESS, *ONE_HASH).unwrap();

// Then
let expected = *ONE_HASH;
let actual = state.get_class_hash_at(*TEST_ADDRESS).unwrap();
assert_eq!(expected, actual);
}

#[test]
fn test_contract_class() {
// Given
let mut state = State::default();

// When
state
.set_contract_class(&ONE_HASH, ContractClass::V0(ContractClassV0::default()))
.unwrap();

// Then
let expected = ContractClass::V0(ContractClassV0::default());
let actual = state.get_compiled_contract_class(&ONE_HASH).unwrap();
assert_eq!(expected, actual);
}

#[test]
#[should_panic(
expected = "UndeclaredClassHash(ClassHash(StarkFelt(\"0x0000000000000000000000000000000000000000000000000000000000000001\")))"
)]
fn test_uninitialized_contract_class() {
// Given
let mut state = State::default();

// When
state.get_compiled_contract_class(&ONE_HASH).unwrap();
}

#[test]
fn test_compiled_class_hash() {
// Given
let mut state = State::default();

// When
state
.set_compiled_class_hash(*ONE_HASH, *ONE_COMPILED_HASH)
.unwrap();

// Then
let expected = *ONE_COMPILED_HASH;
let actual = state.get_compiled_class_hash(*ONE_HASH).unwrap();
assert_eq!(expected, actual);
}

#[test]
#[should_panic(
expected = "UndeclaredClassHash(ClassHash(StarkFelt(\"0x0000000000000000000000000000000000000000000000000000000000000001\"))"
)]
fn test_uninitialized_compiled_class_hash() {
// Given
let mut state = State::default();

// When
state.get_compiled_class_hash(*ONE_HASH).unwrap();
}
}

0 comments on commit 33f68b2

Please sign in to comment.