Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add HintProcessor::execute_hint_extensive + refactor hint_ranges #1491

Merged
merged 27 commits into from
Nov 27, 2023
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
b5d8b9e
Merge branch 'main' of github.com:lambdaclass/cairo-vm
fmoletta Nov 15, 2023
9318cda
Merge branch 'main' of github.com:lambdaclass/cairo-vm
fmoletta Nov 22, 2023
0760f22
Usa a Hashmap for HintRanges
fmoletta Nov 22, 2023
980f15f
Add execute_and_mutate_hints
fmoletta Nov 22, 2023
64a570c
comments
fmoletta Nov 23, 2023
f259ad1
Fix hashmap ranges-related stuff
fmoletta Nov 23, 2023
655f5fa
Add execute_hint_extensive
fmoletta Nov 23, 2023
10dd42a
Process
fmoletta Nov 23, 2023
569583d
Add error handling
fmoletta Nov 23, 2023
15774e9
Add comments & remove previous impl
fmoletta Nov 23, 2023
fc76a36
Use Box to reduce output size
fmoletta Nov 23, 2023
69651d6
Fix tests
fmoletta Nov 23, 2023
e69513e
Fix tests
fmoletta Nov 23, 2023
0741762
Fix bug
fmoletta Nov 23, 2023
dc37475
Revert hook changes + fmt
fmoletta Nov 23, 2023
0a0a85c
Uncomment code
fmoletta Nov 23, 2023
9e37055
revert hook-related vchanges'
fmoletta Nov 23, 2023
961cdb0
Add comments
fmoletta Nov 23, 2023
f2227bd
Remove old comments from proxy era
fmoletta Nov 23, 2023
3260f53
Revert "Use Box to reduce output size"
fmoletta Nov 23, 2023
380518d
Simplify output type of execute_hint_extensive`
fmoletta Nov 23, 2023
72c2ce9
Merge branch 'main' of github.com:lambdaclass/cairo-vm into fede-refa…
fmoletta Nov 24, 2023
7cb5cee
Add disclaimers for execute_hint & execute_hint_extensive
fmoletta Nov 24, 2023
8df1ee4
Start changelog
fmoletta Nov 24, 2023
4eab69d
List functionality changes in changelog
fmoletta Nov 24, 2023
9c959ec
fix names
fmoletta Nov 24, 2023
480601c
Merge branch 'main' into fede-refactor-v3
fmoletta Nov 27, 2023
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
24 changes: 20 additions & 4 deletions vm/src/hint_processor/hint_processor_definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::serde::deserialize_program::OffsetValue;
use crate::serde::deserialize_program::Reference;
use crate::types::exec_scope::ExecutionScopes;
use crate::types::instruction::Register;
use crate::types::relocatable::Relocatable;
use crate::vm::errors::hint_errors::HintError;
use crate::vm::errors::vm_errors::VirtualMachineError;
use crate::vm::runners::cairo_runner::ResourceTracker;
Expand All @@ -21,11 +22,7 @@ pub trait HintProcessorLogic {
//Executes the hint which's data is provided by a dynamic structure previously created by compile_hint
fn execute_hint(
&mut self,
//Proxy to VM, contains refrences to necessary data
//+ MemoryProxy, which provides the necessary methods to manipulate memory
vm: &mut VirtualMachine,
//Proxy to ExecutionScopes, provides the necessary methods to manipulate the scopes and
//access current scope variables
exec_scopes: &mut ExecutionScopes,
//Data structure that can be downcasted to the structure generated by compile_hint
hint_data: &Box<dyn Any>,
Expand All @@ -52,8 +49,27 @@ pub trait HintProcessorLogic {
ids_data: get_ids_data(reference_ids, references)?,
}))
}

//Executes the hint which's data is provided by a dynamic structure previously created by compile_hint
// Can also return a map of hints to be loaded after the current hint is executed
fn execute_hint_extensive(
&mut self,
vm: &mut VirtualMachine,
exec_scopes: &mut ExecutionScopes,
//Data structure that can be downcasted to the structure generated by compile_hint
hint_data: &Box<dyn Any>,
//Constant values extracted from the program specification.
constants: &HashMap<String, Felt252>,
) -> Result<Option<HintExtension>, HintError> {
self.execute_hint(vm, exec_scopes, hint_data, constants)?;
Ok(None)
}
}

// A map of hints that can be used to extend the current map of hints for the vm run
// The map matches the pc at which the hints should be executed to a vec of compiled hints (Outputed by HintProcessor::CompileHint)
pub type HintExtension = HashMap<Relocatable, Vec<Box<dyn Any>>>;

pub trait HintProcessor: HintProcessorLogic + ResourceTracker {}
impl<T> HintProcessor for T where T: HintProcessorLogic + ResourceTracker {}

Expand Down
62 changes: 24 additions & 38 deletions vm/src/types/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
#[cfg(all(feature = "arbitrary", feature = "std"))]
use arbitrary::{Arbitrary, Unstructured};

use super::relocatable::Relocatable;

// NOTE: `Program` has been split in two containing some data that will be deep-copied
// and some that will be allocated on the heap inside an `Arc<_>`.
// This is because it has been reported that cloning the whole structure when creating
Expand Down Expand Up @@ -106,7 +108,7 @@
pub(crate) struct HintsCollection {
hints: Vec<HintParams>,
/// This maps a PC to the range of hints in `hints` that correspond to it.
hints_ranges: Vec<HintRange>,
pub(crate) hints_ranges: HashMap<Relocatable, HintRange>,
}

impl HintsCollection {
Expand All @@ -122,7 +124,7 @@
let Some((max_hint_pc, full_len)) = bounds else {
return Ok(HintsCollection {
hints: Vec::new(),
hints_ranges: Vec::new(),
hints_ranges: HashMap::new(),
});
};

Expand All @@ -131,14 +133,14 @@
}

let mut hints_values = Vec::with_capacity(full_len);
let mut hints_ranges = vec![None; max_hint_pc + 1];
let mut hints_ranges = HashMap::new();

for (pc, hs) in hints.iter().filter(|(_, hs)| !hs.is_empty()) {
let range = (
hints_values.len(),
NonZeroUsize::new(hs.len()).expect("empty vecs already filtered"),
);
hints_ranges[*pc] = Some(range);
hints_ranges.insert(Relocatable::from((0_isize, *pc)), range);
hints_values.extend_from_slice(&hs[..]);
}

Expand All @@ -151,29 +153,20 @@
pub fn iter_hints(&self) -> impl Iterator<Item = &HintParams> {
self.hints.iter()
}

pub fn get_hint_range_for_pc(&self, pc: usize) -> Option<HintRange> {
self.hints_ranges.get(pc).cloned()
}
}

impl From<&HintsCollection> for BTreeMap<usize, Vec<HintParams>> {
fn from(hc: &HintsCollection) -> Self {
let mut hint_map = BTreeMap::new();
for (i, r) in hc.hints_ranges.iter().enumerate() {
let Some(r) = r else {
continue;
};
hint_map.insert(i, hc.hints[r.0..r.0 + r.1.get()].to_owned());
for (pc, r) in hc.hints_ranges.iter() {
hint_map.insert(pc.offset, hc.hints[r.0..r.0 + r.1.get()].to_owned());
}
hint_map
}
}

/// Represents a range of hints corresponding to a PC.
///
/// Is [`None`] if the range is empty, and it is [`Some`] tuple `(start, length)` otherwise.
type HintRange = Option<(usize, NonZeroUsize)>;
/// Represents a range of hints corresponding to a PC as a tuple `(start, length)`.
pub type HintRange = (usize, NonZeroUsize);

#[cfg_attr(all(feature = "arbitrary", feature = "std"), derive(Arbitrary))]
#[derive(Clone, Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -425,19 +418,14 @@
#[cfg(test)]
impl HintsCollection {
pub fn iter(&self) -> impl Iterator<Item = (usize, &[HintParams])> {
self.hints_ranges
.iter()
.enumerate()
.filter_map(|(pc, range)| {
range.and_then(|(start, len)| {
let end = start + len.get();
if end <= self.hints.len() {
Some((pc, &self.hints[start..end]))
} else {
None
}
})
})
self.hints_ranges.iter().filter_map(|(pc, (start, len))| {
let end = start + len.get();
if end <= self.hints.len() {
Some((pc.offset, &self.hints[*start..end]))
} else {
None

Check warning on line 426 in vm/src/types/program.rs

View check run for this annotation

Codecov / codecov/patch

vm/src/types/program.rs#L426

Added line #L426 was not covered by tests
}
})
}
}

Expand Down Expand Up @@ -493,7 +481,7 @@
);
assert_eq!(
program.shared_program_data.hints_collection.hints_ranges,
Vec::new()
HashMap::new()
);
}

Expand Down Expand Up @@ -539,7 +527,7 @@
);
assert_eq!(
program.shared_program_data.hints_collection.hints_ranges,
Vec::new()
HashMap::new()
);
}

Expand Down Expand Up @@ -600,12 +588,10 @@
.hints_collection
.hints_ranges
.iter()
.enumerate()
.filter_map(|(pc, r)| r.map(|(s, l)| (pc, (s, s + l.get()))))
.map(|(pc, (s, e))| {
.map(|(pc, (s, l))| {
(
pc,
program.shared_program_data.hints_collection.hints[s..e].to_vec(),
pc.offset,
program.shared_program_data.hints_collection.hints[*s..(s + l.get())].to_vec(),
)
})
.collect();
Expand Down Expand Up @@ -1250,7 +1236,7 @@
fn default_program() {
let hints_collection = HintsCollection {
hints: Vec::new(),
hints_ranges: Vec::new(),
hints_ranges: HashMap::new(),
};

let shared_program_data = SharedProgramData {
Expand Down
40 changes: 18 additions & 22 deletions vm/src/vm/runners/cairo_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -548,23 +548,21 @@ impl CairoRunner {
hint_processor: &mut dyn HintProcessor,
) -> Result<(), VirtualMachineError> {
let references = &self.program.shared_program_data.reference_manager;
let hint_data = self.get_hint_data(references, hint_processor)?;
let mut hint_data = self.get_hint_data(references, hint_processor)?;
let mut hint_ranges = self
.program
.shared_program_data
.hints_collection
.hints_ranges
.clone();
#[cfg(feature = "hooks")]
vm.execute_before_first_step(self, &hint_data)?;
while vm.run_context.pc != address && !hint_processor.consumed() {
let hint_data = &self
.program
.shared_program_data
.hints_collection
.get_hint_range_for_pc(vm.run_context.pc.offset)
.and_then(|range| {
range.and_then(|(start, length)| hint_data.get(start..start + length.get()))
})
.unwrap_or(&[]);
vm.step(
hint_processor,
&mut self.exec_scopes,
hint_data,
&mut hint_data,
&mut hint_ranges,
&self.program.constants,
)?;
hint_processor.consume_step();
Expand All @@ -585,26 +583,24 @@ impl CairoRunner {
hint_processor: &mut dyn HintProcessor,
) -> Result<(), VirtualMachineError> {
let references = &self.program.shared_program_data.reference_manager;
let hint_data = self.get_hint_data(references, hint_processor)?;
let mut hint_data = self.get_hint_data(references, hint_processor)?;
let mut hint_ranges = self
.program
.shared_program_data
.hints_collection
.hints_ranges
.clone();

for remaining_steps in (1..=steps).rev() {
if self.final_pc.as_ref() == Some(&vm.run_context.pc) {
return Err(VirtualMachineError::EndOfProgram(remaining_steps));
}

let hint_data = self
.program
.shared_program_data
.hints_collection
.get_hint_range_for_pc(vm.run_context.pc.offset)
.and_then(|range| {
range.and_then(|(start, length)| hint_data.get(start..start + length.get()))
})
.unwrap_or(&[]);
vm.step(
hint_processor,
&mut self.exec_scopes,
hint_data,
&mut hint_data,
&mut hint_ranges,
&self.program.constants,
)?;
}
Expand Down
Loading
Loading