1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use crate::any_box;
use crate::serde::deserialize_program::ApTracking;
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::vm::errors::hint_errors::HintError;
use crate::vm::errors::vm_errors::VirtualMachineError;
use crate::vm::vm_core::VirtualMachine;
use std::any::Any;
use std::collections::HashMap;
use super::builtin_hint_processor::builtin_hint_processor_definition::HintProcessorData;
use felt::Felt;
pub trait HintProcessor {
fn execute_hint(
&mut self,
vm: &mut VirtualMachine,
exec_scopes: &mut ExecutionScopes,
hint_data: &Box<dyn Any>,
constants: &HashMap<String, Felt>,
) -> Result<(), HintError>;
fn compile_hint(
&self,
hint_code: &str,
ap_tracking_data: &ApTracking,
reference_ids: &HashMap<String, usize>,
references: &HashMap<usize, HintReference>,
) -> Result<Box<dyn Any>, VirtualMachineError> {
Ok(any_box!(HintProcessorData {
code: hint_code.to_string(),
ap_tracking: ap_tracking_data.clone(),
ids_data: get_ids_data(reference_ids, references)?,
}))
}
}
fn get_ids_data(
reference_ids: &HashMap<String, usize>,
references: &HashMap<usize, HintReference>,
) -> Result<HashMap<String, HintReference>, VirtualMachineError> {
let mut ids_data = HashMap::<String, HintReference>::new();
for (path, ref_id) in reference_ids {
let name = path
.rsplit('.')
.next()
.ok_or(VirtualMachineError::Unexpected)?;
ids_data.insert(
name.to_string(),
references
.get(ref_id)
.ok_or(VirtualMachineError::Unexpected)?
.clone(),
);
}
Ok(ids_data)
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct HintReference {
pub offset1: OffsetValue,
pub offset2: OffsetValue,
pub dereference: bool,
pub ap_tracking_data: Option<ApTracking>,
pub cairo_type: Option<String>,
}
impl HintReference {
pub fn new_simple(offset1: i32) -> Self {
HintReference {
offset1: OffsetValue::Reference(Register::FP, offset1, false),
offset2: OffsetValue::Value(0),
ap_tracking_data: None,
dereference: true,
cairo_type: None,
}
}
pub fn new(offset1: i32, offset2: i32, inner_dereference: bool, dereference: bool) -> Self {
HintReference {
offset1: OffsetValue::Reference(Register::FP, offset1, inner_dereference),
offset2: OffsetValue::Value(offset2),
ap_tracking_data: None,
dereference,
cairo_type: None,
}
}
}
impl From<Reference> for HintReference {
fn from(reference: Reference) -> Self {
HintReference {
offset1: reference.value_address.offset1.clone(),
offset2: reference.value_address.offset2.clone(),
dereference: reference.value_address.dereference,
ap_tracking_data: match (
&reference.value_address.offset1,
&reference.value_address.offset2,
) {
(OffsetValue::Reference(Register::AP, _, _), _)
| (_, OffsetValue::Reference(Register::AP, _, _)) => {
Some(reference.ap_tracking_data.clone())
}
_ => None,
},
cairo_type: Some(reference.value_address.value_type.clone()),
}
}
}