Skip to content
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: 1 addition & 1 deletion .github/workflows/committer_and_os_cli_push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ jobs:
- run: pip install -r scripts/requirements.txt

- name: Build CLI binary
run: ./build_native_in_docker.sh rustup toolchain install && cargo build -p starknet_committer_and_os_cli -r --bin starknet_committer_and_os_cli --target-dir CLI_TARGET
run: ./build_native_in_docker.sh cargo build -p starknet_committer_and_os_cli -r --bin starknet_committer_and_os_cli --target-dir CLI_TARGET

- id: auth
uses: "google-github-actions/auth@v2"
Expand Down
1 change: 1 addition & 0 deletions crates/apollo_starknet_os_program/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ dump_source_files = []
workspace = true

[dependencies]
apollo_infra_utils.workspace = true
cairo-vm.workspace = true
serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
Expand Down
10 changes: 5 additions & 5 deletions crates/apollo_starknet_os_program/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ pub static CAIRO_FILES_MAP: LazyLock<HashMap<String, String>> = LazyLock::new(||
.unwrap_or_else(|error| panic!("Failed to deserialize cairo_files_map.json: {error:?}."))
});

pub const OS_PROGRAM_BYTES: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/starknet_os_bytes"));

pub static OS_PROGRAM: LazyLock<Program> = LazyLock::new(|| {
Program::from_bytes(
include_bytes!(concat!(env!("OUT_DIR"), "/starknet_os_bytes")),
Some("main"),
)
.expect("Failed to load the OS bytes.")
Program::from_bytes(OS_PROGRAM_BYTES, Some("main")).expect("Failed to load the OS bytes.")
});

pub static PROGRAM_HASH: LazyLock<ProgramHash> = LazyLock::new(|| {
// As the program hash file may not exist at runtime, it's contents must be included at compile
// time.
serde_json::from_str(include_str!("program_hash.json"))
.expect("Failed to deserialize program_hash.json.")
});
4 changes: 2 additions & 2 deletions crates/apollo_starknet_os_program/src/program_hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ pub enum ProgramHashError {
UnexpectedRelocatable,
}

#[derive(Deserialize, Serialize)]
#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct ProgramHash {
os: Felt,
pub os: Felt,
}

const BOOTLOADER_VERSION: u8 = 0;
Expand Down
28 changes: 26 additions & 2 deletions crates/apollo_starknet_os_program/src/program_hash_test.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,31 @@
use crate::program_hash::compute_os_program_hash;
use std::path::PathBuf;
use std::sync::LazyLock;

use apollo_infra_utils::compile_time_cargo_manifest_dir;

use crate::program_hash::{compute_os_program_hash, ProgramHash};
use crate::PROGRAM_HASH;

static PROGRAM_HASH_PATH: LazyLock<PathBuf> = LazyLock::new(|| {
PathBuf::from(compile_time_cargo_manifest_dir!()).join("src/program_hash.json")
});

/// Asserts the program hash of the compiled Starknet OS program matches the program hash in the
/// JSON.
/// To fix this test, run the following command:
/// ```bash
/// FIX_PROGRAM_HASH=1 cargo test -p apollo_starknet_os_program test_program_hash
/// ```
#[test]
fn test_program_hash() {
assert_eq!(compute_os_program_hash().unwrap(), PROGRAM_HASH.os)
let computed_hash = ProgramHash { os: compute_os_program_hash().unwrap() };
if std::env::var("FIX_PROGRAM_HASH").is_ok() {
std::fs::write(
PROGRAM_HASH_PATH.as_path(),
serde_json::to_string_pretty(&computed_hash).unwrap(),
)
.unwrap_or_else(|error| panic!("Failed to write the program hash file: {error:?}."));
} else {
assert_eq!(computed_hash, *PROGRAM_HASH);
}
}
19 changes: 17 additions & 2 deletions crates/starknet_committer_and_os_cli/src/os_cli/commands.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::fs;
use std::path::Path;

use apollo_starknet_os_program::CAIRO_FILES_MAP;
use apollo_starknet_os_program::{CAIRO_FILES_MAP, OS_PROGRAM_BYTES, PROGRAM_HASH};
use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass;
use cairo_vm::types::layout_name::LayoutName;
use cairo_vm::vm::runners::cairo_pie::CairoPie;
Expand All @@ -14,7 +14,7 @@ use starknet_os::io::os_output::StarknetOsRunnerOutput;
use starknet_os::runner::run_os_stateless;
use tracing::info;

use super::run_os_cli::OsCliOutput;
use crate::os_cli::run_os_cli::{OsCliOutput, ProgramToDump};
use crate::shared_utils::read::{load_input, write_to_file};

#[derive(Deserialize, Debug)]
Expand Down Expand Up @@ -106,3 +106,18 @@ pub(crate) fn serialize_os_runner_output(
pub(crate) fn dump_source_files(output_path: String) {
write_to_file(&output_path, &*CAIRO_FILES_MAP);
}

pub(crate) fn dump_program(output_path: String, program: ProgramToDump) {
let bytes = match program {
ProgramToDump::Os => OS_PROGRAM_BYTES,
};
// Dumping the `Program` struct won't work - it is not deserializable via cairo-lang's Program
// class. JSONify the raw bytes instead.
let program_json = serde_json::from_slice::<serde_json::Value>(bytes)
.expect("Program bytes are JSON-serializable.");
write_to_file(&output_path, &program_json);
}

pub(crate) fn dump_program_hashes(output_path: String) {
write_to_file(&output_path, &*PROGRAM_HASH);
}
29 changes: 28 additions & 1 deletion crates/starknet_committer_and_os_cli/src/os_cli/run_os_cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@ use tracing::level_filters::LevelFilter;
use tracing_subscriber::reload::Handle;
use tracing_subscriber::Registry;

use crate::os_cli::commands::{dump_source_files, parse_and_run_os};
use crate::os_cli::commands::{
dump_program,
dump_program_hashes,
dump_source_files,
parse_and_run_os,
};
use crate::os_cli::tests::python_tests::OsPythonTestRunner;
use crate::shared_utils::types::{run_python_test, IoArgs, PythonTestArg};

Expand All @@ -19,8 +24,28 @@ pub struct OsCliCommand {
command: Command,
}

#[derive(clap::ValueEnum, Clone, Debug, Serialize)]
#[serde(rename_all = "kebab-case")]
pub enum ProgramToDump {
Os,
}

#[derive(Debug, Subcommand)]
enum Command {
DumpProgram {
/// File path to output.
#[clap(long, short = 'o', default_value = "stdout")]
output_path: String,

/// Program to dump.
#[clap(long, value_enum)]
program: ProgramToDump,
},
DumpProgramHashes {
/// File path to output.
#[clap(long, short = 'o', default_value = "stdout")]
output_path: String,
},
DumpSourceFiles {
/// File path to output.
#[clap(long, short = 'o')]
Expand All @@ -39,6 +64,8 @@ pub async fn run_os_cli(
) {
info!("Starting starknet-os-cli with command: \n{:?}", os_command);
match os_command.command {
Command::DumpProgram { output_path, program } => dump_program(output_path, program),
Command::DumpProgramHashes { output_path } => dump_program_hashes(output_path),
Command::DumpSourceFiles { output_path } => dump_source_files(output_path),
Command::PythonTest(python_test_arg) => {
run_python_test::<OsPythonTestRunner>(python_test_arg).await;
Expand Down
Loading