-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9dc3a6e
commit de24338
Showing
4 changed files
with
302 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,262 @@ | ||
use std::any::Any; | ||
use std::collections::HashMap; | ||
|
||
use cairo_vm::air_private_input::AirPrivateInput; | ||
use cairo_vm::air_public_input::PublicInputError; | ||
use cairo_vm::cairo_run::{ | ||
write_encoded_memory, write_encoded_trace, CairoRunConfig, EncodeTraceError, | ||
}; | ||
use cairo_vm::hint_processor::builtin_hint_processor::bootloader::types::{ | ||
BootloaderConfig, BootloaderInput, PackedOutput, SimpleBootloaderInput, Task, TaskSpec, | ||
}; | ||
use cairo_vm::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor; | ||
use cairo_vm::hint_processor::hint_processor_definition::HintProcessor; | ||
use cairo_vm::types::errors::cairo_pie_error::CairoPieError; | ||
use cairo_vm::types::errors::program_errors::ProgramError; | ||
use cairo_vm::types::program::Program; | ||
use cairo_vm::vm::errors::cairo_run_errors::CairoRunError; | ||
use cairo_vm::vm::errors::trace_errors::TraceError; | ||
use cairo_vm::vm::errors::vm_exception::VmException; | ||
use cairo_vm::vm::runners::cairo_pie::CairoPie; | ||
use cairo_vm::vm::runners::cairo_runner::CairoRunner; | ||
use cairo_vm::vm::security::verify_secure_runner; | ||
use cairo_vm::vm::vm_core::VirtualMachine; | ||
use cairo_vm::{any_box, Felt252}; | ||
use thiserror::Error; | ||
|
||
use bincode::error::EncodeError; | ||
|
||
use crate::models::{Layout, PublicInput}; | ||
|
||
// Copied from cairo_run.rs and adapted to support injecting the bootloader input. | ||
// TODO: check if modifying CairoRunConfig to specify custom variables is accepted upstream. | ||
pub fn cairo_run( | ||
program: &Program, | ||
cairo_run_config: &CairoRunConfig, | ||
hint_executor: &mut dyn HintProcessor, | ||
variables: HashMap<String, Box<dyn Any>>, | ||
) -> Result<(CairoRunner, VirtualMachine), CairoRunError> { | ||
let secure_run = cairo_run_config | ||
.secure_run | ||
.unwrap_or(!cairo_run_config.proof_mode); | ||
|
||
let mut cairo_runner = CairoRunner::new( | ||
program, | ||
cairo_run_config.layout, | ||
cairo_run_config.proof_mode, | ||
)?; | ||
for (key, value) in variables { | ||
cairo_runner.exec_scopes.insert_box(&key, value); | ||
} | ||
|
||
let mut vm = VirtualMachine::new(cairo_run_config.trace_enabled); | ||
let end = cairo_runner.initialize(&mut vm)?; | ||
// check step calculation | ||
|
||
cairo_runner | ||
.run_until_pc(end, &mut vm, hint_executor) | ||
.map_err(|err| VmException::from_vm_error(&cairo_runner, &vm, err))?; | ||
cairo_runner.end_run( | ||
cairo_run_config.disable_trace_padding, | ||
false, | ||
&mut vm, | ||
hint_executor, | ||
)?; | ||
|
||
vm.verify_auto_deductions()?; | ||
cairo_runner.read_return_values(&mut vm)?; | ||
if cairo_run_config.proof_mode { | ||
cairo_runner.finalize_segments(&mut vm)?; | ||
} | ||
if secure_run { | ||
verify_secure_runner(&cairo_runner, true, None, &mut vm)?; | ||
} | ||
cairo_runner.relocate(&mut vm, cairo_run_config.relocate_mem)?; | ||
|
||
Ok((cairo_runner, vm)) | ||
} | ||
|
||
/// Run a Cairo program in proof mode. | ||
/// | ||
/// * `program_content`: Compiled program content. | ||
pub fn run_in_proof_mode( | ||
program_content: &[u8], | ||
layout: Layout, | ||
) -> Result<(CairoRunner, VirtualMachine), CairoRunError> { | ||
let proof_mode = true; | ||
|
||
let cairo_run_config = CairoRunConfig { | ||
entrypoint: "main", | ||
trace_enabled: true, | ||
relocate_mem: true, | ||
layout: &layout.to_string(), | ||
proof_mode, | ||
secure_run: None, | ||
disable_trace_padding: false, | ||
}; | ||
|
||
let mut hint_processor = BuiltinHintProcessor::new_empty(); | ||
|
||
cairo_vm::cairo_run::cairo_run(program_content, &cairo_run_config, &mut hint_processor) | ||
} | ||
|
||
#[derive(thiserror::Error, Debug)] | ||
pub enum BootloaderTaskError { | ||
#[error("Failed to read program: {0}")] | ||
Program(#[from] ProgramError), | ||
|
||
#[error("Failed to read PIE: {0}")] | ||
Pie(#[from] CairoPieError), | ||
} | ||
|
||
pub fn make_bootloader_tasks( | ||
programs: &[Vec<u8>], | ||
pies: &[Vec<u8>], | ||
) -> Result<Vec<TaskSpec>, BootloaderTaskError> { | ||
let program_tasks = programs.iter().map(|program_bytes| { | ||
let program = Program::from_bytes(program_bytes, Some("main")); | ||
program | ||
.map(|program| TaskSpec { | ||
task: Task::Program(program), | ||
}) | ||
.map_err(BootloaderTaskError::Program) | ||
}); | ||
|
||
let cairo_pie_tasks = pies.iter().map(|pie_bytes| { | ||
let pie = CairoPie::from_bytes(pie_bytes); | ||
pie.map(|pie| TaskSpec { | ||
task: Task::Pie(pie), | ||
}) | ||
.map_err(BootloaderTaskError::Pie) | ||
}); | ||
|
||
program_tasks.chain(cairo_pie_tasks).collect() | ||
} | ||
|
||
pub struct ExecutionArtifacts { | ||
pub public_input: PublicInput, | ||
pub private_input: AirPrivateInput, | ||
pub memory: Vec<u8>, | ||
pub trace: Vec<u8>, | ||
} | ||
|
||
#[derive(Error, Debug)] | ||
pub enum ExecutionError { | ||
#[error(transparent)] | ||
RunFailed(#[from] CairoRunError), | ||
#[error(transparent)] | ||
GeneratePublicInput(#[from] PublicInputError), | ||
#[error(transparent)] | ||
GenerateTrace(#[from] TraceError), | ||
#[error(transparent)] | ||
EncodeMemory(EncodeTraceError), | ||
#[error(transparent)] | ||
EncodeTrace(EncodeTraceError), | ||
#[error(transparent)] | ||
SerializePublicInput(#[from] serde_json::Error), | ||
} | ||
|
||
/// An in-memory writer for bincode encoding. | ||
#[derive(Default)] | ||
pub struct MemWriter { | ||
pub buf: Vec<u8>, | ||
} | ||
|
||
impl MemWriter { | ||
pub fn new() -> Self { | ||
Self::default() | ||
} | ||
} | ||
|
||
impl bincode::enc::write::Writer for MemWriter { | ||
fn write(&mut self, bytes: &[u8]) -> Result<(), EncodeError> { | ||
self.buf.extend_from_slice(bytes); | ||
Ok(()) | ||
} | ||
} | ||
|
||
/// Extracts execution artifacts from the runner and VM (after execution). | ||
/// | ||
/// * `cairo_runner` Cairo runner object. | ||
/// * `vm`: Cairo VM object. | ||
pub fn extract_execution_artifacts( | ||
cairo_runner: CairoRunner, | ||
vm: VirtualMachine, | ||
) -> Result<ExecutionArtifacts, ExecutionError> { | ||
let memory = &cairo_runner.relocated_memory; | ||
let trace = cairo_runner | ||
.relocated_trace | ||
.as_ref() | ||
.ok_or(ExecutionError::GenerateTrace(TraceError::TraceNotEnabled))?; | ||
|
||
let mut memory_writer = MemWriter::new(); | ||
write_encoded_memory(memory, &mut memory_writer).map_err(ExecutionError::EncodeMemory)?; | ||
let memory_raw = memory_writer.buf; | ||
|
||
let mut trace_writer = MemWriter::new(); | ||
write_encoded_trace(trace, &mut trace_writer).map_err(ExecutionError::EncodeTrace)?; | ||
let trace_raw = trace_writer.buf; | ||
|
||
let cairo_vm_public_input = cairo_runner.get_air_public_input(&vm)?; | ||
let public_input = PublicInput::try_from(cairo_vm_public_input)?; | ||
|
||
let private_input = cairo_runner.get_air_private_input(&vm); | ||
|
||
Ok(ExecutionArtifacts { | ||
public_input, | ||
private_input, | ||
memory: memory_raw, | ||
trace: trace_raw, | ||
}) | ||
} | ||
|
||
pub fn run_bootloader_in_proof_mode( | ||
bootloader: &Program, | ||
tasks: Vec<TaskSpec>, | ||
) -> Result<ExecutionArtifacts, ExecutionError> { | ||
let proof_mode = true; | ||
let layout = "starknet_with_keccak"; | ||
|
||
let cairo_run_config = CairoRunConfig { | ||
entrypoint: "main", | ||
trace_enabled: true, | ||
relocate_mem: true, | ||
layout, | ||
proof_mode, | ||
secure_run: None, | ||
disable_trace_padding: false, | ||
}; | ||
|
||
let n_tasks = tasks.len(); | ||
|
||
let bootloader_input = BootloaderInput { | ||
simple_bootloader_input: SimpleBootloaderInput { | ||
fact_topologies_path: Some("/tmp/fact_topologies".into()), | ||
single_page: false, | ||
tasks, | ||
}, | ||
bootloader_config: BootloaderConfig { | ||
simple_bootloader_program_hash: Felt252::from(0), | ||
supported_cairo_verifier_program_hashes: vec![], | ||
}, | ||
packed_outputs: vec![PackedOutput::Plain(vec![]); n_tasks], | ||
}; | ||
|
||
let mut hint_processor = BuiltinHintProcessor::new_empty(); | ||
let variables = HashMap::<String, Box<dyn Any>>::from([ | ||
("bootloader_input".to_string(), any_box!(bootloader_input)), | ||
( | ||
"bootloader_program".to_string(), | ||
any_box!(bootloader.clone()), | ||
), | ||
]); | ||
|
||
let (cairo_runner, vm) = cairo_run( | ||
bootloader, | ||
&cairo_run_config, | ||
&mut hint_processor, | ||
variables, | ||
)?; | ||
|
||
extract_execution_artifacts(cairo_runner, vm) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
pub mod cairo_vm; | ||
pub mod error; | ||
pub mod fri; | ||
pub(crate) mod json; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters