Skip to content

Commit

Permalink
feat: add state dump and loading for the sequencer
Browse files Browse the repository at this point in the history
  • Loading branch information
Harsh Bajpai authored and Harsh Bajpai committed Sep 22, 2023
1 parent b0b853b commit 469bc32
Show file tree
Hide file tree
Showing 12 changed files with 10,435 additions and 5 deletions.
6 changes: 6 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ starknet_api = { git = "https://github.com/starkware-libs/starknet-api", rev = "
# Other
async-trait = "0.1.58"
bytes = "1"
cairo-vm = "0.8.2"
cairo-lang-starknet = "2.2.0"
chrono = { version = "0.4.26", features = ["serde"] }
ctor = "0.2.4"
dotenv = "0.15.0"
Expand Down
7 changes: 7 additions & 0 deletions crates/sequencer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,21 @@ license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
anyhow = "1.0.75"
# Starknet
# TODO: remove the blockifier patch on the workspace once we can remove Katana.
blockifier = { package = "blockifier", git = "https://github.com/starkware-libs/blockifier.git", tag = "v0.3.0-rc0" }
cairo-lang-starknet = { workspace = true }
cairo-vm = { workspace = true }
serde.workspace = true
serde_json.workspace = true
starknet_api = { workspace = true }
starknet = { workspace = true }
thiserror.workspace = true

# Other
rustc-hash = "1.1.0"

[dev-dependencies]
lazy_static = { workspace = true }
starknet = { workspace = true }
1 change: 1 addition & 0 deletions crates/sequencer/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod constants;
pub mod sequencer;
pub mod serde;
pub mod state;
246 changes: 246 additions & 0 deletions crates/sequencer/src/serde/contract.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
use std::collections::HashMap;
use std::sync::Arc;

use serde::{Deserialize, Serialize};
use starknet_api::core::EntryPointSelector;
use starknet_api::deprecated_contract_class::{EntryPoint, EntryPointOffset, EntryPointType};

use super::program::SerializableProgram;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum SerializableContractClass {
V0(SerializableContractClassV0),
V1(SerializableContractClassV1),
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SerializableContractClassV0 {
pub program: SerializableProgram,
pub entry_points_by_type: HashMap<EntryPointType, Vec<SerializableEntryPoint>>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SerializableContractClassV1 {
pub program: SerializableProgram,
pub entry_points_by_type: HashMap<EntryPointType, Vec<SerializableEntryPointV1>>,
pub hints: HashMap<String, Vec<u8>>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SerializableEntryPoint {
pub selector: EntryPointSelector,
pub offset: SerializableEntryPointOffset,
}

impl From<EntryPoint> for SerializableEntryPoint {
fn from(value: EntryPoint) -> Self {
Self {
selector: value.selector,
offset: value.offset.into(),
}
}
}

impl From<SerializableEntryPoint> for EntryPoint {
fn from(value: SerializableEntryPoint) -> Self {
Self {
selector: value.selector,
offset: value.offset.into(),
}
}
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SerializableEntryPointOffset(pub usize);

impl From<EntryPointOffset> for SerializableEntryPointOffset {
fn from(value: EntryPointOffset) -> Self {
Self(value.0)
}
}

impl From<SerializableEntryPointOffset> for EntryPointOffset {
fn from(value: SerializableEntryPointOffset) -> Self {
Self(value.0)
}
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SerializableEntryPointV1 {
pub selector: EntryPointSelector,
pub offset: SerializableEntryPointOffset,
pub builtins: Vec<String>,
}

impl From<SerializableEntryPointV1> for blockifier::execution::contract_class::EntryPointV1 {
fn from(value: SerializableEntryPointV1) -> Self {
blockifier::execution::contract_class::EntryPointV1 {
selector: value.selector,
offset: value.offset.into(),
builtins: value.builtins,
}
}
}

impl From<blockifier::execution::contract_class::EntryPointV1> for SerializableEntryPointV1 {
fn from(value: blockifier::execution::contract_class::EntryPointV1) -> Self {
SerializableEntryPointV1 {
selector: value.selector,
offset: value.offset.into(),
builtins: value.builtins,
}
}
}

impl TryFrom<SerializableContractClass> for blockifier::execution::contract_class::ContractClass {
type Error = anyhow::Error;

fn try_from(value: SerializableContractClass) -> Result<Self, Self::Error> {
Ok(match value {
SerializableContractClass::V0(v0) => {
blockifier::execution::contract_class::ContractClass::V0(
blockifier::execution::contract_class::ContractClassV0(Arc::new(
blockifier::execution::contract_class::ContractClassV0Inner {
program: v0.program.into(),
entry_points_by_type: v0
.entry_points_by_type
.into_iter()
.map(|(k, v)| (k, v.into_iter().map(|h| h.into()).collect()))
.collect(),
},
)),
)
}
SerializableContractClass::V1(v1) => {
blockifier::execution::contract_class::ContractClass::V1(
blockifier::execution::contract_class::ContractClassV1(Arc::new(
blockifier::execution::contract_class::ContractClassV1Inner {
hints: v1
.hints
.clone()
.into_iter()
.map(|(k, v)| (k, serde_json::from_slice(&v).unwrap()))
.collect(),
program: v1.program.into(),
entry_points_by_type: v1
.entry_points_by_type
.into_iter()
.map(|(k, v)| {
(
k,
v.into_iter()
.map(Into::into)
.collect::<Vec<
blockifier::execution::contract_class::EntryPointV1,
>>(),
)
})
.collect::<HashMap<_, _>>(),
},
)),
)
}
})
}
}

impl From<blockifier::execution::contract_class::ContractClass> for SerializableContractClass {
fn from(value: blockifier::execution::contract_class::ContractClass) -> Self {
match value {
blockifier::execution::contract_class::ContractClass::V0(v0) => {
SerializableContractClass::V0(SerializableContractClassV0 {
program: v0.program.clone().into(),
entry_points_by_type: v0
.entry_points_by_type
.clone()
.into_iter()
.map(|(k, v)| (k, v.into_iter().map(|h| h.into()).collect()))
.collect(),
})
}
blockifier::execution::contract_class::ContractClass::V1(v1) => {
SerializableContractClass::V1(SerializableContractClassV1 {
program: v1.program.clone().into(),
entry_points_by_type: v1
.entry_points_by_type
.clone()
.into_iter()
.map(|(k, v)| {
(
k,
v.into_iter()
.map(Into::into)
.collect::<Vec<SerializableEntryPointV1>>(),
)
})
.collect::<HashMap<_, _>>(),
hints: v1
.hints
.clone()
.into_iter()
.map(|(k, v)| (k, serde_json::to_vec(&v).unwrap()))
.collect(),
})
}
}
}
}

#[cfg(test)]
mod tests {
use blockifier::execution::contract_class::ContractClass;
use starknet::core::types::contract::SierraClass;

use super::*;
use crate::serde::utils::{get_contract_class, rpc_to_inner_class};

#[test]
fn serialize_and_deserialize_legacy_contract() {
let original_contract = get_contract_class(include_str!(
"../test_data/contracts/compiled/universal_deployer.json"
));

let serializable_contract: SerializableContractClass = original_contract.clone().into();
assert!(matches!(
serializable_contract,
SerializableContractClass::V0(_)
));

let bytes = serde_json::to_vec(&serializable_contract).unwrap();
let serializable_contract: SerializableContractClass =
serde_json::from_slice(&bytes).unwrap();

let contract: ContractClass = serializable_contract
.try_into()
.expect("should deserialize");
assert_eq!(contract, original_contract);
}

#[test]
fn serialize_and_deserialize_contract() {
let class = serde_json::from_str::<SierraClass>(include_str!(
"../test_data/contracts/compiled/cairo1_contract.json"
))
.expect("should deserialize sierra class")
.flatten()
.expect("should flatten");

let (_, original_contract) =
rpc_to_inner_class(&class).expect("should convert from flattened to contract class");

let serializable_contract: SerializableContractClass = original_contract.clone().into();
assert!(matches!(
serializable_contract,
SerializableContractClass::V1(_)
));

let bytes = serde_json::to_vec(&serializable_contract).unwrap();
let serializable_contract: SerializableContractClass =
serde_json::from_slice(&bytes).unwrap();

let contract: ContractClass = serializable_contract
.try_into()
.expect("should deserialize");
assert_eq!(contract, original_contract);
}
}
4 changes: 4 additions & 0 deletions crates/sequencer/src/serde/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
pub mod contract;
pub mod program;
pub mod state;
pub mod utils;
Loading

0 comments on commit 469bc32

Please sign in to comment.