cairo_proof_parser/
program.rs1use starknet_crypto::{poseidon_hash_many, FieldElement};
2use std::collections::HashMap;
3use std::convert::TryInto;
4
5use crate::parse_raw;
6
7pub struct ExtractProgramResult {
8 pub program: Vec<FieldElement>,
9 pub program_hash: FieldElement,
10}
11
12pub fn extract_program(input: String) -> anyhow::Result<ExtractProgramResult> {
13 let proof = parse_raw(&input)?;
15
16 let program_segment = proof
18 .public_input
19 .segments
20 .first()
21 .ok_or_else(|| anyhow::Error::msg("Program segment not found"))?;
22
23 let execution_segment = proof
25 .public_input
26 .segments
27 .get(1)
28 .ok_or_else(|| anyhow::Error::msg("Execution segment not found"))?;
29
30 let mut main_page_map = HashMap::new();
32 for element in &proof.public_input.main_page {
33 let value_bytes = element.value.to_bytes_be();
34 let padded_value = vec![0u8; 32 - value_bytes.len()]
35 .iter()
36 .chain(value_bytes.iter())
37 .copied()
38 .collect::<Vec<u8>>();
39 let field_element = FieldElement::from_bytes_be(
40 &padded_value.try_into().expect("Failed to convert to array"),
41 )
42 .expect("Failed to convert to FieldElement");
43
44 main_page_map.insert(element.address, field_element);
45 }
46
47 let initial_pc = program_segment.begin_addr;
48 let initial_fp = execution_segment.begin_addr;
49
50 let program: Vec<FieldElement> = (initial_pc..(initial_fp - initial_pc - 1))
52 .map(|addr| {
53 *main_page_map
54 .get(&addr)
55 .expect("Address not found in main page map")
56 })
57 .collect();
58
59 let program_hash = poseidon_hash_many(&program);
61
62 Ok(ExtractProgramResult {
63 program,
64 program_hash,
65 })
66}