Skip to content

Commit 602304c

Browse files
feat(apollo_starknet_os_program): add aggregator program + program hash(es)
1 parent 71eea6a commit 602304c

File tree

6 files changed

+81
-23
lines changed

6 files changed

+81
-23
lines changed

crates/apollo_starknet_os_program/build/compile_program.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,8 @@ use std::path::PathBuf;
33
use apollo_infra_utils::cairo0_compiler::{compile_cairo0_program, Cairo0CompilerError};
44
use apollo_infra_utils::compile_time_cargo_manifest_dir;
55

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) {
6+
fn compile_program(path_to_main_file: PathBuf) -> Vec<u8> {
7+
match compile_cairo0_program(path_to_main_file, cairo_root_path()) {
118
Ok(bytes) => bytes,
129
Err(Cairo0CompilerError::Cairo0CompilerVersion(error)) => {
1310
panic!(
@@ -18,7 +15,19 @@ pub fn compile_starknet_os() -> Vec<u8> {
1815
)
1916
}
2017
Err(other_error) => {
21-
panic!("Failed to compile the StarkNet OS program. Error:\n{other_error}.")
18+
panic!("Failed to compile the program. Error:\n{other_error}.")
2219
}
2320
}
2421
}
22+
23+
fn cairo_root_path() -> PathBuf {
24+
PathBuf::from(compile_time_cargo_manifest_dir!()).join("src/cairo")
25+
}
26+
27+
pub fn compile_starknet_os() -> Vec<u8> {
28+
compile_program(cairo_root_path().join("starkware/starknet/core/os/os.cairo"))
29+
}
30+
31+
pub fn compile_starknet_aggregator() -> Vec<u8> {
32+
compile_program(cairo_root_path().join("starkware/starknet/core/aggregator/main.cairo"))
33+
}

crates/apollo_starknet_os_program/build/main.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,11 @@ fn main() {
1919
let starknet_os_bytes_path = out_dir.join("starknet_os_bytes");
2020
std::fs::write(&starknet_os_bytes_path, &starknet_os_bytes)
2121
.expect("Failed to write the compiled OS bytes to the output directory.");
22+
23+
println!("cargo::warning=Compiling Starknet aggregator program...");
24+
let starknet_aggregator_bytes = compile_program::compile_starknet_aggregator();
25+
println!("cargo::warning=Done. Writing compiled bytes to output directory.");
26+
let starknet_aggregator_bytes_path = out_dir.join("starknet_aggregator_bytes");
27+
std::fs::write(&starknet_aggregator_bytes_path, &starknet_aggregator_bytes)
28+
.expect("Failed to write the compiled aggregator bytes to the output directory.");
2229
}

crates/apollo_starknet_os_program/src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,16 @@ pub static CAIRO_FILES_MAP: LazyLock<HashMap<String, String>> = LazyLock::new(||
1616
});
1717

1818
pub const OS_PROGRAM_BYTES: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/starknet_os_bytes"));
19+
pub const AGGREGATOR_PROGRAM_BYTES: &[u8] =
20+
include_bytes!(concat!(env!("OUT_DIR"), "/starknet_aggregator_bytes"));
1921

2022
pub static OS_PROGRAM: LazyLock<Program> = LazyLock::new(|| {
2123
Program::from_bytes(OS_PROGRAM_BYTES, Some("main")).expect("Failed to load the OS bytes.")
2224
});
25+
pub static AGGREGATOR_PROGRAM: LazyLock<Program> = LazyLock::new(|| {
26+
Program::from_bytes(AGGREGATOR_PROGRAM_BYTES, Some("main"))
27+
.expect("Failed to load the aggregator bytes.")
28+
});
2329

2430
pub static PROGRAM_HASH: LazyLock<ProgramHash> = LazyLock::new(|| {
2531
serde_json::from_reader(
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
{
2-
"os": "0x44a93b0a0bed63f4c3ca30418dff64aed464ce2cf1e9cad25624f540cac27c8"
3-
}
2+
"os": "0x44a93b0a0bed63f4c3ca30418dff64aed464ce2cf1e9cad25624f540cac27c8",
3+
"aggregator": "0x181986bfe23bbfdac56c40522bd5c2b1b64c824c74bd6722a3ccacc8cc888e2",
4+
"aggregator_with_prefix": "0x1ae51bd7157e0754f1e1729806ad5579a7ac6926cd0c8dd342ad1e7a3758c2e"
5+
}

crates/apollo_starknet_os_program/src/program_hash.rs

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ use std::sync::LazyLock;
44
use apollo_infra_utils::compile_time_cargo_manifest_dir;
55
use cairo_vm::types::builtin_name::BuiltinName;
66
use cairo_vm::types::errors::program_errors::ProgramError;
7+
use cairo_vm::types::program::Program;
78
use serde::{Deserialize, Serialize};
89
use starknet_types_core::felt::Felt;
910
use starknet_types_core::hash::{Pedersen, StarkHash};
1011

11-
use crate::OS_PROGRAM;
12+
use crate::{AGGREGATOR_PROGRAM, OS_PROGRAM};
1213

1314
#[cfg(test)]
1415
#[path = "program_hash_test.rs"]
@@ -31,10 +32,27 @@ pub(crate) static PROGRAM_HASH_PATH: LazyLock<PathBuf> = LazyLock::new(|| {
3132
#[derive(Debug, Deserialize, Serialize, PartialEq)]
3233
pub struct ProgramHash {
3334
pub os: Felt,
35+
pub aggregator: Felt,
36+
pub aggregator_with_prefix: Felt,
37+
}
38+
39+
pub struct AggregatorHash {
40+
pub with_prefix: Felt,
41+
pub without_prefix: Felt,
3442
}
3543

3644
const BOOTLOADER_VERSION: u8 = 0;
3745

46+
fn pad_to_32_bytes(data: &[u8]) -> [u8; 32] {
47+
let mut padded = [0; 32];
48+
let len = data.len();
49+
if len > 32 {
50+
panic!("Data length exceeds 32 bytes.");
51+
}
52+
padded[32 - len..].copy_from_slice(data);
53+
padded
54+
}
55+
3856
fn pedersen_hash_chain(data: Vec<Felt>) -> Felt {
3957
let length = Felt::from(data.len());
4058
vec![length]
@@ -45,35 +63,40 @@ fn pedersen_hash_chain(data: Vec<Felt>) -> Felt {
4563
.expect("Hash data chain is not empty.")
4664
}
4765

48-
pub fn compute_os_program_hash() -> Result<Felt, ProgramHashError> {
49-
let builtins = OS_PROGRAM
66+
fn compute_program_hash(program: &Program) -> Result<Felt, ProgramHashError> {
67+
let builtins = program
5068
.iter_builtins()
5169
.map(|builtin| {
5270
let builtin_bytes = builtin.to_str().to_string().into_bytes();
5371
if builtin_bytes.len() > 32 {
5472
Err(ProgramHashError::BuiltinNameTooLong(*builtin))
5573
} else {
56-
let mut padded_builtin_bytes = [0].repeat(32 - builtin_bytes.len());
57-
padded_builtin_bytes.extend(builtin_bytes);
58-
Ok(Felt::from_bytes_be(
59-
padded_builtin_bytes
60-
.as_slice()
61-
.try_into()
62-
.expect("Padded bytes are 32 bytes long."),
63-
))
74+
Ok(Felt::from_bytes_be(&pad_to_32_bytes(&builtin_bytes)))
6475
}
6576
})
6677
.collect::<Result<Vec<Felt>, _>>()?;
6778
let program_header = vec![
6879
Felt::from(BOOTLOADER_VERSION),
69-
Felt::from(OS_PROGRAM.get_stripped_program()?.main),
80+
Felt::from(program.get_stripped_program()?.main),
7081
Felt::from(builtins.len()),
7182
];
72-
let data = OS_PROGRAM
83+
let data = program
7384
.iter_data()
7485
.map(|data| data.get_int().ok_or(ProgramHashError::UnexpectedRelocatable))
7586
.collect::<Result<Vec<Felt>, _>>()?;
7687

7788
let data_chain: Vec<Felt> = program_header.into_iter().chain(builtins).chain(data).collect();
7889
Ok(pedersen_hash_chain(data_chain))
7990
}
91+
92+
pub fn compute_os_program_hash() -> Result<Felt, ProgramHashError> {
93+
compute_program_hash(&OS_PROGRAM)
94+
}
95+
96+
pub fn compute_aggregator_program_hash() -> Result<AggregatorHash, ProgramHashError> {
97+
let hash = compute_program_hash(&AGGREGATOR_PROGRAM)?;
98+
Ok(AggregatorHash {
99+
with_prefix: Pedersen::hash(&Felt::from_bytes_be(&pad_to_32_bytes(b"AGGREGATOR")), &hash),
100+
without_prefix: hash,
101+
})
102+
}

crates/apollo_starknet_os_program/src/program_hash_test.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
use crate::program_hash::{compute_os_program_hash, ProgramHash, PROGRAM_HASH_PATH};
1+
use crate::program_hash::{
2+
compute_aggregator_program_hash,
3+
compute_os_program_hash,
4+
AggregatorHash,
5+
ProgramHash,
6+
PROGRAM_HASH_PATH,
7+
};
28
use crate::PROGRAM_HASH;
39

410
/// Asserts the program hash of the compiled Starknet OS program matches the program hash in the
@@ -9,7 +15,12 @@ use crate::PROGRAM_HASH;
915
/// ```
1016
#[test]
1117
fn test_program_hash() {
12-
let computed_hash = ProgramHash { os: compute_os_program_hash().unwrap() };
18+
let AggregatorHash { with_prefix, without_prefix } = compute_aggregator_program_hash().unwrap();
19+
let computed_hash = ProgramHash {
20+
os: compute_os_program_hash().unwrap(),
21+
aggregator: without_prefix,
22+
aggregator_with_prefix: with_prefix,
23+
};
1324
if std::env::var("FIX_PROGRAM_HASH").is_ok() {
1425
std::fs::write(
1526
PROGRAM_HASH_PATH.as_path(),

0 commit comments

Comments
 (0)