Skip to content

Commit 7c19baf

Browse files
feat(apollo_starknet_os_program): define and implement static Program
1 parent c9f149c commit 7c19baf

File tree

11 files changed

+154
-18
lines changed

11 files changed

+154
-18
lines changed

.github/workflows/committer_and_os_cli_push.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,19 @@ jobs:
6565
COMMIT_SHA: ${{ github.event.after }}
6666
run: echo "SHORT_HASH=${COMMIT_SHA:0:7}" >> $GITHUB_ENV
6767

68+
# Setup pypy and link to the location expected by .cargo/config.toml.
69+
# Python + requirements are needed to compile the OS.
70+
- uses: actions/setup-python@v5
71+
id: setup-pypy
72+
with:
73+
python-version: "pypy3.9"
74+
cache: 'pip'
75+
- run: ln -s '${{ steps.setup-pypy.outputs.python-path }}' /usr/local/bin/pypy3.9
76+
- env:
77+
LD_LIBRARY_PATH: ${{ env.Python3_ROOT_DIR }}/bin
78+
run: echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}" >> $GITHUB_ENV
79+
- run: pip install -r scripts/requirements.txt
80+
6881
- name: Build CLI binary
6982
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
7083

.github/workflows/committer_ci.yml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,19 @@ jobs:
4040
with:
4141
github_token: ${{ secrets.GITHUB_TOKEN }}
4242

43+
# Setup pypy and link to the location expected by .cargo/config.toml.
44+
# Python + requirements are needed to compile the OS.
45+
- uses: actions/setup-python@v5
46+
id: setup-pypy
47+
with:
48+
python-version: "pypy3.9"
49+
cache: 'pip'
50+
- run: ln -s '${{ steps.setup-pypy.outputs.python-path }}' /usr/local/bin/pypy3.9
51+
- env:
52+
LD_LIBRARY_PATH: ${{ env.Python3_ROOT_DIR }}/bin
53+
run: echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}" >> $GITHUB_ENV
54+
- run: pip install -r scripts/requirements.txt
55+
4356
- id: auth
4457
uses: "google-github-actions/auth@v2"
4558
with:
@@ -61,6 +74,19 @@ jobs:
6174
with:
6275
github_token: ${{ secrets.GITHUB_TOKEN }}
6376

77+
# Setup pypy and link to the location expected by .cargo/config.toml.
78+
# Python + requirements are needed to compile the OS.
79+
- uses: actions/setup-python@v5
80+
id: setup-pypy
81+
with:
82+
python-version: "pypy3.9"
83+
cache: 'pip'
84+
- run: ln -s '${{ steps.setup-pypy.outputs.python-path }}' /usr/local/bin/pypy3.9
85+
- env:
86+
LD_LIBRARY_PATH: ${{ env.Python3_ROOT_DIR }}/bin
87+
run: echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}" >> $GITHUB_ENV
88+
- run: pip install -r scripts/requirements.txt
89+
6490
# Download the old benchmark inputs.
6591
- id: auth
6692
uses: "google-github-actions/auth@v2"

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/apollo_infra_utils/src/cairo0_compiler.rs

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,26 +37,38 @@ pub enum Cairo0CompilerVersionError {
3737
"{0}. Are you in the venv? If not, run the following commands:\n{}",
3838
*ENTER_VENV_INSTRUCTIONS
3939
)]
40-
NotFound(String),
40+
CompilerNotFound(String),
41+
}
42+
43+
#[derive(thiserror::Error, Debug)]
44+
pub enum Cairo0CompilerError {
45+
#[error(transparent)]
46+
Cairo0CompilerVersion(#[from] Cairo0CompilerVersionError),
47+
#[error("Cairo root path not found at {0:?}.")]
48+
CairoRootNotFound(PathBuf),
49+
#[error("Failed to compile the program. Error: {0}.")]
50+
CompileError(String),
51+
#[error("Invalid path unicode: {0:?}.")]
52+
InvalidPath(PathBuf),
53+
#[error(transparent)]
54+
Io(#[from] std::io::Error),
55+
#[error("No file found at path {0:?}.")]
56+
SourceFileNotFound(PathBuf),
4157
}
4258

4359
pub fn cairo0_compilers_correct_version() -> Result<(), Cairo0CompilerVersionError> {
4460
for compiler in [CAIRO0_COMPILE, STARKNET_COMPILE_DEPRECATED] {
4561
let version = match Command::new(compiler).arg("--version").output() {
4662
Ok(output) => String::from_utf8_lossy(&output.stdout).to_string(),
4763
Err(error) => {
48-
return Err(Cairo0CompilerVersionError::NotFound(format!(
64+
return Err(Cairo0CompilerVersionError::CompilerNotFound(format!(
4965
"Failed to get {compiler} version: {error}."
5066
)));
5167
}
5268
};
53-
if version
54-
.trim()
55-
.replace("==", " ")
56-
.split(" ")
57-
.nth(1)
58-
.ok_or(Cairo0CompilerVersionError::NotFound("No compiler version found.".to_string()))?
59-
!= EXPECTED_CAIRO0_VERSION
69+
if version.trim().replace("==", " ").split(" ").nth(1).ok_or(
70+
Cairo0CompilerVersionError::CompilerNotFound("No compiler version found.".to_string()),
71+
)? != EXPECTED_CAIRO0_VERSION
6072
{
6173
return Err(Cairo0CompilerVersionError::IncorrectVersion {
6274
compiler: compiler.to_string(),
@@ -69,6 +81,39 @@ pub fn cairo0_compilers_correct_version() -> Result<(), Cairo0CompilerVersionErr
6981
Ok(())
7082
}
7183

84+
/// Compile a Cairo0 program.
85+
pub fn compile_cairo0_program(
86+
path_to_main: PathBuf,
87+
cairo_root_path: PathBuf,
88+
) -> Result<Vec<u8>, Cairo0CompilerError> {
89+
cairo0_compilers_correct_version()?;
90+
if !path_to_main.exists() {
91+
return Err(Cairo0CompilerError::SourceFileNotFound(path_to_main));
92+
}
93+
if !cairo_root_path.exists() {
94+
return Err(Cairo0CompilerError::CairoRootNotFound(cairo_root_path));
95+
}
96+
let mut compile_command = Command::new(CAIRO0_COMPILE);
97+
compile_command.args([
98+
path_to_main.to_str().ok_or(Cairo0CompilerError::InvalidPath(path_to_main.clone()))?,
99+
"--debug_info_with_source",
100+
"--cairo_path",
101+
cairo_root_path
102+
.to_str()
103+
.ok_or(Cairo0CompilerError::InvalidPath(cairo_root_path.clone()))?,
104+
]);
105+
let compile_output = compile_command.output()?;
106+
107+
// Verify output.
108+
if !compile_output.status.success() {
109+
return Err(Cairo0CompilerError::CompileError(
110+
String::from_utf8_lossy(&compile_output.stderr).trim().to_string(),
111+
));
112+
}
113+
114+
Ok(compile_output.stdout)
115+
}
116+
72117
/// Verifies that the required Cairo0 compiler is available; panics if unavailable.
73118
/// For use in tests only. If cairo0 compiler verification is required in business logic, use
74119
/// `crate::cairo0_compiler::cairo0_compilers_correct_version` instead.
@@ -78,7 +123,9 @@ pub fn verify_cairo0_compiler_deps() {
78123
Ok(_) => {
79124
return;
80125
}
81-
Err(Cairo0CompilerVersionError::NotFound(_)) => "no installed cairo-lang found".to_string(),
126+
Err(Cairo0CompilerVersionError::CompilerNotFound(_)) => {
127+
"no installed cairo-lang found".to_string()
128+
}
82129
Err(Cairo0CompilerVersionError::IncorrectVersion { existing, .. }) => {
83130
format!("installed version: {existing}")
84131
}

crates/apollo_starknet_os_program/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ dump_source_files = []
1414
workspace = true
1515

1616
[dependencies]
17+
cairo-vm.workspace = true
1718
serde_json.workspace = true
1819

1920
[build-dependencies]
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
use std::path::PathBuf;
2+
3+
use apollo_infra_utils::cairo0_compiler::{compile_cairo0_program, Cairo0CompilerError};
4+
use apollo_infra_utils::compile_time_cargo_manifest_dir;
5+
6+
/// Compile the StarkNet OS program.
7+
pub fn compile_starknet_os() -> Vec<u8> {
8+
let cairo_root_path = PathBuf::from(compile_time_cargo_manifest_dir!()).join("src/cairo");
9+
let os_main_path = cairo_root_path.join("starkware/starknet/core/os/os.cairo");
10+
match compile_cairo0_program(os_main_path, cairo_root_path) {
11+
Ok(bytes) => bytes,
12+
Err(Cairo0CompilerError::Cairo0CompilerVersion(error)) => {
13+
panic!(
14+
"Failed to verify correct cairo0 package installation. Please make sure you do \
15+
not have a conflicting installation in your {}/bin directory.\nOriginal error: \
16+
{error:?}.",
17+
std::env::var("CARGO_HOME").unwrap_or("${CARGO_HOME}".to_string())
18+
)
19+
}
20+
Err(other_error) => {
21+
panic!("Failed to compile the StarkNet OS program. Error:\n{other_error}.")
22+
}
23+
}
24+
}

crates/apollo_starknet_os_program/build/dump_source.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ fn get_cairo_file_map_recursive(entry: DirEntry) -> HashMap<String, String> {
2828

2929
/// Find all files with a .cairo extension in the `src` directory, insert them into a map and dump
3030
/// the map as JSON to the specified location.
31-
pub fn dump_source_files(dump_to: PathBuf) {
31+
pub fn dump_source_files(dump_to: &PathBuf) {
3232
println!("cargo::warning=Dumping OS source files...");
3333

3434
// Recursively fetch all cairo files and contents, and convert the paths to relative paths.
@@ -47,6 +47,6 @@ pub fn dump_source_files(dump_to: PathBuf) {
4747

4848
// Serialize and dump the map to the specified location.
4949
let serialized = serde_json::to_string(&map_without_prefixes).unwrap();
50-
std::fs::write(&dump_to, serialized)
50+
std::fs::write(dump_to, serialized)
5151
.unwrap_or_else(|error| panic!("Failed to write to {dump_to:?}: {error:?}."));
5252
}
Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
1-
#[cfg(feature = "dump_source_files")]
21
use std::path::PathBuf;
32

3+
mod compile_program;
44
#[cfg(feature = "dump_source_files")]
55
mod dump_source;
66

77
/// Build script for the `apollo_starknet_os_program` crate.
88
/// Recompiles the OS program if the source files change.
99
/// Optionally, also exposes all source cairo files in a mapping from file path to contents.
1010
fn main() {
11+
let out_dir = PathBuf::from(std::env::var("OUT_DIR").expect("OUT_DIR not set."));
12+
1113
#[cfg(feature = "dump_source_files")]
12-
let out_dir = std::env::var("OUT_DIR").expect("OUT_DIR not set.");
13-
#[cfg(feature = "dump_source_files")]
14-
dump_source::dump_source_files(PathBuf::from(out_dir).join("cairo_files_map.json"));
14+
dump_source::dump_source_files(&out_dir.join("cairo_files_map.json"));
15+
16+
println!("cargo::warning=Compiling Starknet OS program...");
17+
let starknet_os_bytes = compile_program::compile_starknet_os();
18+
println!("cargo::warning=Done. Writing compiled bytes to output directory.");
19+
let starknet_os_bytes_path = out_dir.join("starknet_os_bytes");
20+
std::fs::write(&starknet_os_bytes_path, &starknet_os_bytes)
21+
.expect("Failed to write the compiled OS bytes to the output directory.");
1522
}
Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,19 @@
11
#[cfg(feature = "dump_source_files")]
22
use std::collections::HashMap;
3-
#[cfg(feature = "dump_source_files")]
43
use std::sync::LazyLock;
54

5+
use cairo_vm::types::program::Program;
6+
67
#[cfg(feature = "dump_source_files")]
78
pub static CAIRO_FILES_MAP: LazyLock<HashMap<String, String>> = LazyLock::new(|| {
89
serde_json::from_str(include_str!(concat!(env!("OUT_DIR"), "/cairo_files_map.json")))
910
.unwrap_or_else(|error| panic!("Failed to deserialize cairo_files_map.json: {error:?}."))
1011
});
12+
13+
pub static OS_PROGRAM: LazyLock<Program> = LazyLock::new(|| {
14+
Program::from_bytes(
15+
include_bytes!(concat!(env!("OUT_DIR"), "/starknet_os_bytes")),
16+
Some("main"),
17+
)
18+
.expect("Failed to load the OS bytes.")
19+
});

deployments/images/base/Dockerfile

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ FROM ubuntu:24.04 AS base
88

99
COPY scripts/install_build_tools.sh .
1010
COPY scripts/dependencies.sh .
11+
COPY scripts/requirements.txt .
1112
COPY rust-toolchain.toml .
1213

1314
RUN apt update && apt -y install \
@@ -24,5 +25,11 @@ RUN ./install_build_tools.sh
2425
RUN rustup toolchain install
2526
RUN cargo install cargo-chef
2627

28+
# Define python venv and install python packages.
29+
ENV VIRTUAL_ENV=/opt/sequencer_venv
30+
RUN python3 -m venv ${VIRTUAL_ENV}
31+
RUN ${VIRTUAL_ENV}/bin/pip install -r requirements.txt
32+
ENV PATH="${VIRTUAL_ENV}/bin:$PATH"
33+
2734
# Cleanup.
28-
RUN rm -f install_build_tools.sh dependencies.sh
35+
RUN rm -f install_build_tools.sh dependencies.sh requirements.txt

0 commit comments

Comments
 (0)