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
47 changes: 47 additions & 0 deletions cairo_programs/simulated_builtins.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
%builtins ec_op

from starkware.cairo.common.cairo_builtins import EcOpBuiltin
from starkware.cairo.common.ec_point import EcPoint
from starkware.cairo.common.ec import ec_op

func main{ec_op_ptr: EcOpBuiltin*}() {
alloc_locals;
let (local ec_op_ptr) = init_ec_op(ec_op_ptr=ec_op_ptr);

let p = EcPoint(
0x6a4beaef5a93425b973179cdba0c9d42f30e01a5f1e2db73da0884b8d6756fc,
0x72565ec81bc09ff53fbfad99324a92aa5b39fb58267e395e8abe36290ebf24f,
);
let m = 34;
let q = EcPoint(
0x654fd7e67a123dd13868093b3b7777f1ffef596c2e324f25ceaf9146698482c,
0x4fad269cbf860980e38768fe9cb6b0b9ab03ee3fe84cfde2eccce597c874fd8,
);
let (r) = ec_op(p, m, q);
assert r.x = 108925483682366235368969256555281508851459278989259552980345066351008608800;
assert r.y = 1592365885972480102953613056006596671718206128324372995731808913669237079419;
return ();
}

// Initializes the ec_op builtin pointer if not initialized.
//
// If the builtin is included in the layout, the ec_op_ptr will be valid, and
// this function will do nothing. If the builtin is not included in the layout,
// then it will obtain the pointer of the ec_op simulated builtin and return
// it. For this to work properly, the runner must have the ec_op simulated
// builtin runner at index 0.
func init_ec_op(ec_op_ptr: EcOpBuiltin*) -> (ec_op_ptr: EcOpBuiltin*) {
if (ec_op_ptr != 0) {
return (ec_op_ptr=ec_op_ptr);
}

alloc_locals;
local builtin_idx = 0;
local new_ptr;

// This hint is not defined in the original VM,
// and its declared for testing purposes only.
%{ ids.new_ptr = get_simulated_builtin_base(ids.builtin_idx) %}

return (ec_op_ptr=cast(new_ptr, EcOpBuiltin*));
}
Original file line number Diff line number Diff line change
Expand Up @@ -1017,6 +1017,16 @@ impl HintProcessorLogic for BuiltinHintProcessor {
&hint_data.ap_tracking,
constants,
),
#[cfg(feature = "test_utils")]
super::simulated_builtins::GET_SIMULATED_BUILTIN_BASE => {
super::simulated_builtins::get_simulated_builtin_base(
vm,
exec_scopes,
&hint_data.ids_data,
&hint_data.ap_tracking,
constants,
)
}

code => Err(HintError::UnknownHint(code.to_string().into_boxed_str())),
}
Expand Down
3 changes: 3 additions & 0 deletions vm/src/hint_processor/builtin_hint_processor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ pub mod sha256_utils;
pub mod signature;
#[cfg(feature = "test_utils")]
#[cfg_attr(docsrs, doc(cfg(feature = "test_utils")))]
pub mod simulated_builtins;
#[cfg(feature = "test_utils")]
#[cfg_attr(docsrs, doc(cfg(feature = "test_utils")))]
pub mod skip_next_instruction;
pub mod squash_dict_utils;
pub mod uint256_utils;
Expand Down
46 changes: 46 additions & 0 deletions vm/src/hint_processor/builtin_hint_processor/simulated_builtins.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use crate::hint_processor::hint_processor_definition::HintReference;
use crate::stdlib::collections::HashMap;
use crate::types::relocatable::Relocatable;
use crate::Felt252;
use crate::{
serde::deserialize_program::ApTracking,
types::exec_scope::ExecutionScopes,
vm::{errors::hint_errors::HintError, vm_core::VirtualMachine},
};
use num_traits::ToPrimitive;

use super::hint_utils::{get_integer_from_var_name, insert_value_from_var_name};

pub const GET_SIMULATED_BUILTIN_BASE: &str =
"ids.new_ptr = get_simulated_builtin_base(ids.builtin_idx)";

/// Obtains the simulated builtin runner base, at the given index. The simulated
/// builtin runner must be initialized before the execution.
///
/// This hint is not defined in the original VM, and its declared for testing
/// purposes only.
pub fn get_simulated_builtin_base(
vm: &mut VirtualMachine,
_exec_scopes: &mut ExecutionScopes,
ids_data: &HashMap<String, HintReference>,
ap_tracking: &ApTracking,
_constants: &HashMap<String, Felt252>,
) -> Result<(), HintError> {
// Obtain the simulated builtin runner from the builtin_idx variable.
let builtin_idx = get_integer_from_var_name("builtin_idx", vm, ids_data, ap_tracking)?
.to_usize()
.ok_or(HintError::BigintToUsizeFail)?;
let builtin_runner = &vm.simulated_builtin_runners[builtin_idx];

// Set new_ptr with the value of the builtin runner base.
insert_value_from_var_name(
"new_ptr",
Relocatable {
segment_index: builtin_runner.base() as isize,
offset: 0,
},
vm,
ids_data,
ap_tracking,
)
}
31 changes: 31 additions & 0 deletions vm/src/vm/runners/cairo_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5731,4 +5731,35 @@ mod tests {
let builtin_segments = cairo_runner.get_builtin_segments();
assert!(builtin_segments.get(&9) == Some(&BuiltinName::poseidon));
}

#[test]
#[cfg(feature = "test_utils")]
fn test_simulated_builtins() {
let program_bytes = include_bytes!("../../../../cairo_programs/simulated_builtins.json");
let program =
Program::from_bytes(program_bytes, Some("main")).expect("failed to read program");

let program: &Program = &program;
let mut cairo_runner =
CairoRunner::new(program, LayoutName::plain, None, false, false, false)
.expect("failed to create runner");

// We allow missing builtins, as we will simulate them later.
let end = cairo_runner
.initialize(true)
.expect("failed to initialize builtins");

// Initialize the ec_op simulated builtin runner.
let mut builtin_runner = BuiltinRunner::EcOp(EcOpBuiltinRunner::new(None, true));
builtin_runner.initialize_segments(&mut cairo_runner.vm.segments);
cairo_runner
.vm
.simulated_builtin_runners
.push(builtin_runner);

let hint_processor: &mut dyn HintProcessor = &mut BuiltinHintProcessor::new_empty();
cairo_runner
.run_until_pc(end, hint_processor)
.expect("failed to run program");
}
}
10 changes: 10 additions & 0 deletions vm/src/vm/vm_core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,16 @@ impl DeducedOperands {
pub struct VirtualMachine {
pub(crate) run_context: RunContext,
pub builtin_runners: Vec<BuiltinRunner>,
/// A simulated builtin is being verified in the executed Cairo
/// code (so proving them only involves proving cairo steps), rather
/// than being outputted as their own segment and proven later using
/// dedicated AIRs.
///
/// These builtins won't be included in the layout, hence the builtin
/// segment pointer won't be passed as argument to the program. The program
/// needs a mechanism for obtaining the segment pointer. See example
/// implementation of this mechanism in `simulated_builtins.cairo`, or
/// cairo-lang's `simple_bootloader.cairo`.
pub simulated_builtin_runners: Vec<BuiltinRunner>,
pub segments: MemorySegmentManager,
pub(crate) trace: Option<Vec<TraceEntry>>,
Expand Down
Loading