1use super::*;
18
19use leo_ast::{
20 BinaryOperation,
21 CoreFunction,
22 IntegerType,
23 Location,
24 Type,
25 UnaryOperation,
26 interpreter_value::{self, AsyncExecution, Value},
27};
28
29use snarkvm::{
30 prelude::{Identifier, LiteralType, PlaintextType, Register, TestnetV0},
31 synthesizer::{
32 Command,
33 Instruction,
34 program::{
35 CallOperator,
36 CastType,
37 CommitVariant,
38 DeserializeVariant,
39 ECDSAVerifyVariant,
40 HashVariant,
41 Operand,
42 SerializeVariant,
43 },
44 },
45};
46
47use std::mem;
48
49impl Cursor {
50 fn mapping_by_call_operator(&self, operator: &CallOperator<TestnetV0>) -> Option<&HashMap<Value, Value>> {
51 let (program, name) = match operator {
52 CallOperator::Locator(locator) => {
53 (Some(snarkvm_identifier_to_symbol(locator.name())), snarkvm_identifier_to_symbol(locator.resource()))
54 }
55 CallOperator::Resource(id) => (None, snarkvm_identifier_to_symbol(id)),
56 };
57 self.lookup_mapping(program, name)
58 }
59
60 fn get_register(&self, reg: &Register<TestnetV0>) -> Value {
61 let Some(Frame { element: Element::AleoExecution { registers, .. }, .. }) = self.frames.last() else {
62 panic!();
63 };
64 match reg {
65 Register::Locator(index) => {
66 registers.get(index).expect("valid .aleo code doesn't access undefined registers").clone()
67 }
68 Register::Access(index, accesses) => {
69 let value = registers.get(index).expect("valid .aleo code doesn't access undefined registers");
70 value.accesses(accesses.iter().cloned()).expect("Accesses should work.")
71 }
72 }
73 }
74
75 fn set_register(&mut self, reg: Register<TestnetV0>, value: Value) {
76 let Some(Frame { element: Element::AleoExecution { registers, .. }, .. }) = self.frames.last_mut() else {
77 panic!();
78 };
79
80 match reg {
81 Register::Locator(index) => {
82 registers.insert(index, value);
83 }
84 Register::Access(_, _) => panic!("Can't happen"),
85 }
86 }
87
88 fn instructions_len(&self) -> usize {
89 let Some(Frame { element: Element::AleoExecution { context, .. }, .. }) = self.frames.last() else {
90 panic!();
91 };
92 match &**context {
93 AleoContext::Closure(closure) => closure.instructions().len(),
94 AleoContext::Function(function) => function.instructions().len(),
95 AleoContext::Finalize(finalize) => finalize.commands().len(),
96 }
97 }
98
99 fn increment_instruction_index(&mut self) {
100 let Some(Frame { element: Element::AleoExecution { instruction_index, .. }, .. }) = self.frames.last_mut()
101 else {
102 panic!();
103 };
104 *instruction_index += 1;
105 }
106
107 fn execution_complete(&self) -> bool {
108 let Some(Frame { element: Element::AleoExecution { instruction_index, .. }, .. }) = self.frames.last() else {
109 panic!();
110 };
111 *instruction_index >= self.instructions_len()
112 }
113
114 fn next_instruction(&self) -> Option<&Instruction<TestnetV0>> {
115 let Some(Frame { element: Element::AleoExecution { instruction_index, context, .. }, .. }) = self.frames.last()
116 else {
117 panic!();
118 };
119 match &**context {
120 AleoContext::Closure(closure) => closure.instructions().get(*instruction_index),
121 AleoContext::Function(function) => function.instructions().get(*instruction_index),
122 AleoContext::Finalize(_) => None,
123 }
124 }
125
126 fn next_command(&self) -> Option<&Command<TestnetV0>> {
127 let Some(Frame { element: Element::AleoExecution { instruction_index, context, .. }, .. }) = self.frames.last()
128 else {
129 panic!();
130 };
131 match &**context {
132 AleoContext::Closure(_) | AleoContext::Function(_) => None,
133 AleoContext::Finalize(finalize) => finalize.commands().get(*instruction_index),
134 }
135 }
136
137 fn operand_value(&self, operand: &Operand<TestnetV0>) -> Value {
138 match operand {
139 Operand::Literal(literal) => literal.clone().into(),
140 Operand::Register(register) => self.get_register(register).clone(),
141 Operand::ProgramID(_) => todo!(),
142 Operand::Signer => self.signer.clone(),
143 Operand::Caller => {
144 if let Some(function_context) = self.contexts.last() {
145 function_context.caller.clone()
146 } else {
147 self.signer.clone()
148 }
149 }
150 Operand::BlockHeight => self.block_height.into(),
151 Operand::BlockTimestamp => self.block_timestamp.into(),
152 Operand::NetworkID => todo!(),
153 Operand::Checksum(_) => todo!(),
154 Operand::Edition(_) => todo!(),
155 Operand::ProgramOwner(_) => todo!(),
156 }
157 }
158
159 fn step_aleo_instruction(&mut self, instruction: Instruction<TestnetV0>) -> Result<()> {
160 use Instruction::*;
163
164 let Some(Frame { step, .. }) = self.frames.last() else {
165 panic!("frame expected");
166 };
167
168 macro_rules! unary {
169 ($svm_op: expr, $op: ident) => {{
170 let operand = self.operand_value(&$svm_op.operands()[0]);
171 let value =
172 interpreter_value::evaluate_unary(Default::default(), UnaryOperation::$op, &operand, &None)?;
173 self.increment_instruction_index();
174 (value, $svm_op.destinations()[0].clone())
175 }};
176 }
177
178 macro_rules! binary {
179 ($svm_op: expr, $op: ident) => {{
180 let operand0 = self.operand_value(&$svm_op.operands()[0]);
181 let operand1 = self.operand_value(&$svm_op.operands()[1]);
182 let value = interpreter_value::evaluate_binary(
183 Default::default(),
184 BinaryOperation::$op,
185 &operand0,
186 &operand1,
187 &None,
188 )?;
189 self.increment_instruction_index();
190 (value, $svm_op.destinations()[0].clone())
191 }};
192 }
193
194 macro_rules! commit_function {
195 ($commit: expr, $variant: expr) => {{
196 let core_function = CoreFunction::Commit($variant, $commit.destination_type());
197 let randomizer_value = self.operand_value(&$commit.operands()[0]);
198 let operand_value = self.operand_value(&$commit.operands()[1]);
199 self.values.push(randomizer_value);
200 self.values.push(operand_value);
201 let value = interpreter_value::evaluate_core_function(self, core_function, &[], Span::default())?;
202 self.increment_instruction_index();
203 (value.expect("Evaluation should work"), $commit.destinations()[0].clone())
204 }};
205 }
206
207 macro_rules! hash_function {
208 ($hash: expr, $variant: expr) => {{
209 let core_function =
211 CoreFunction::Hash($variant, Type::from_snarkvm::<TestnetV0>($hash.destination_type(), None));
212 let operand_value = self.operand_value(&$hash.operands()[0]);
213 self.values.push(operand_value);
214 let value = interpreter_value::evaluate_core_function(self, core_function, &[], Span::default())?;
215 self.increment_instruction_index();
216 (value.expect("Evaluation should work"), $hash.destinations()[0].clone())
217 }};
218 }
219
220 macro_rules! ecdsa_function {
221 ($ecdsa: expr, $variant: expr) => {{
222 let core_function = CoreFunction::ECDSAVerify($variant);
223 let signature = self.operand_value(&$ecdsa.operands()[0]);
224 let public_key = self.operand_value(&$ecdsa.operands()[1]);
225 let message = self.operand_value(&$ecdsa.operands()[2]);
226 self.values.push(signature);
227 self.values.push(public_key);
228 self.values.push(message);
229 let value = interpreter_value::evaluate_core_function(self, core_function, &[], Span::default())?;
230 self.increment_instruction_index();
231 (value.expect("Evaluation should work"), $ecdsa.destinations()[0].clone())
232 }};
233 }
234
235 macro_rules! schnorr_function {
236 ($schnorr: expr, $variant: expr) => {{
237 let core_function = CoreFunction::SignatureVerify;
238 let signature = self.operand_value(&$schnorr.operands()[0]);
239 let public_key = self.operand_value(&$schnorr.operands()[1]);
240 let message = self.operand_value(&$schnorr.operands()[2]);
241 self.values.push(signature);
242 self.values.push(public_key);
243 self.values.push(message);
244 let value = interpreter_value::evaluate_core_function(self, core_function, &[], Span::default())?;
245 self.increment_instruction_index();
246 (value.expect("Evaluation should work"), $schnorr.destinations()[0].clone())
247 }};
248 }
249
250 macro_rules! serialize_function {
251 ($serialize: expr, $variant: expr) => {{
252 let core_function = CoreFunction::Serialize($variant);
253 let operand_value = self.operand_value(&$serialize.operands()[0]);
254 self.values.push(operand_value);
255 let value = interpreter_value::evaluate_core_function(self, core_function, &[], Span::default())?;
256 self.increment_instruction_index();
257 (value.expect("Evaluation should work"), $serialize.destinations()[0].clone())
258 }};
259 }
260
261 macro_rules! deserialize_function {
262 ($deserialize: expr, $variant: expr) => {{
263 let core_function = CoreFunction::Deserialize(
264 $variant,
265 Type::from_snarkvm::<TestnetV0>($deserialize.destination_type(), None),
266 );
267 let operand_value = self.operand_value(&$deserialize.operands()[0]);
268 self.values.push(operand_value);
269 let value = interpreter_value::evaluate_core_function(self, core_function, &[], Span::default())?;
270 self.increment_instruction_index();
271 (value.expect("Evaluation should work"), $deserialize.destinations()[0].clone())
272 }};
273 }
274
275 let (value, destination) = match instruction {
276 Abs(abs) => unary!(abs, Abs),
277 AbsWrapped(abs_wrapped) => unary!(abs_wrapped, AbsWrapped),
278 Add(add) => binary!(add, Add),
279 AddWrapped(add_wrapped) => binary!(add_wrapped, AddWrapped),
280 And(and) => binary!(and, BitwiseAnd),
281 AssertEq(assert_eq) => {
282 let operand0 = self.operand_value(&assert_eq.operands()[0]);
283 let operand1 = self.operand_value(&assert_eq.operands()[1]);
284 if !operand0.eq(&operand1)? {
285 halt_no_span!("assertion failure: {operand0} != {operand1}");
286 }
287 self.increment_instruction_index();
288 return Ok(());
289 }
290 AssertNeq(assert_neq) => {
291 let operand0 = self.operand_value(&assert_neq.operands()[0]);
292 let operand1 = self.operand_value(&assert_neq.operands()[1]);
293 if operand0.eq(&operand1)? {
294 halt_no_span!("assertion failure: {operand0} != {operand1}");
295 }
296 self.increment_instruction_index();
297 return Ok(());
298 }
299 Async(async_) if *step == 0 => {
300 let program = self.contexts.current_program().expect("there should be a program");
301 let name = snarkvm_identifier_to_symbol(async_.function_name());
302 let arguments: Vec<Value> = async_.operands().iter().map(|op| self.operand_value(op)).collect();
303 if self.really_async {
304 self.increment_instruction_index();
305 let async_ex =
306 AsyncExecution::AsyncFunctionCall { function: Location::new(program, vec![name]), arguments };
307 (vec![async_ex].into(), async_.destinations()[0].clone())
308 } else {
309 self.do_call(
310 program,
311 &[name],
312 arguments.into_iter(),
313 true, Span::default(),
315 )?;
316 self.increment_step();
317 return Ok(());
318 }
319 }
320 Call(call) if *step == 0 => {
321 let (program, name) = match call.operator() {
322 CallOperator::Locator(locator) => (
323 snarkvm_identifier_to_symbol(locator.resource()),
324 snarkvm_identifier_to_symbol(locator.program_id().name()),
325 ),
326 CallOperator::Resource(id) => (
327 snarkvm_identifier_to_symbol(id),
328 self.contexts.current_program().expect("there should be a program"),
329 ),
330 };
331 let arguments: Vec<Value> = call.operands().iter().map(|op| self.operand_value(op)).collect();
332 self.do_call(
333 program,
334 &[name],
335 arguments.into_iter(),
336 false, Span::default(),
338 )?;
339 self.increment_step();
340 return Ok(());
341 }
342 Async(async_) if *step == 1 => {
343 self.values.pop();
345 self.set_register(async_.destinations()[0].clone(), Vec::<AsyncExecution>::new().into());
346 self.increment_instruction_index();
347 return Ok(());
348 }
349 Call(call) if *step == 1 => {
350 let Some(result) = self.values.pop() else {
352 panic!("should have a result");
353 };
354 if call.destinations().len() == 1 {
355 self.set_register(call.destinations()[0].clone(), result);
356 } else {
357 for (i, dest) in call.destinations().iter().enumerate() {
358 self.set_register(
359 dest.clone(),
360 result.tuple_index(i).expect("Function returning multiple values should create a tuple."),
361 );
362 }
363 }
364 self.increment_instruction_index();
365 return Ok(());
366 }
367 Call(_) | Async(_) => unreachable!("all cases covered above"),
368 Cast(cast) => {
369 let destination = cast.destinations()[0].clone();
370
371 self.increment_instruction_index();
372
373 match cast.cast_type() {
374 CastType::GroupXCoordinate => {
375 let value = self.operand_value(&cast.operands()[0]);
376 let mut values = vec![value];
377 let Some(result_value) = interpreter_value::evaluate_core_function(
378 &mut values,
379 CoreFunction::GroupToXCoordinate,
380 &[],
381 Default::default(),
382 )?
383 else {
384 halt_no_span!("GroupToXCoordinate didn't produce a value.");
385 };
386 (result_value, destination)
387 }
388 CastType::GroupYCoordinate => {
389 let value = self.operand_value(&cast.operands()[0]);
390 let mut values = vec![value];
391 let Some(result_value) = interpreter_value::evaluate_core_function(
392 &mut values,
393 CoreFunction::GroupToYCoordinate,
394 &[],
395 Default::default(),
396 )?
397 else {
398 halt_no_span!("GroupToYCoordinate didn't produce a value.");
399 };
400 (result_value, destination)
401 }
402 CastType::Plaintext(PlaintextType::Array(_array)) => {
403 let value = Value::make_array(cast.operands().iter().map(|op| self.operand_value(op)));
404 (value, destination)
405 }
406 CastType::Plaintext(PlaintextType::Literal(literal_type)) => {
407 let operand = self.operand_value(&cast.operands()[0]);
408 let Some(value) = operand.cast(&snarkvm_literal_type_to_type(*literal_type)) else {
409 halt_no_span!("cast failure");
410 };
411 (value, destination)
412 }
413 CastType::Plaintext(PlaintextType::Struct(struct_name)) => {
414 let name = Symbol::intern(&struct_name.to_string());
415 let struct_type = self.structs.get([name].as_slice()).expect("struct type should exist");
416 let operands = cast.operands().iter().map(|op| self.operand_value(op));
417 let value = Value::make_struct(
418 struct_type.keys().cloned().zip(operands),
419 self.current_program().unwrap(),
420 vec![name],
421 );
422 (value, destination)
423 }
424 CastType::Record(record_name) => {
425 let program = self.current_program().unwrap();
426 let name = Symbol::intern(&record_name.to_string());
427 let path = vec![name];
428 let record_type = self.records.get(&(program, path.clone())).expect("record type should exist");
429 let operands = cast.operands().iter().map(|op| self.operand_value(op));
430 let value =
431 Value::make_record(record_type.keys().cloned().zip(operands), program, path.clone());
432 (value, destination)
433 }
434 CastType::ExternalRecord(locator) => {
435 let program = Symbol::intern(&locator.program_id().name().to_string());
436 let name = Symbol::intern(&locator.resource().to_string());
437 let path = vec![name];
438 let record_type = self.records.get(&(program, path.clone())).expect("record type should exist");
439 let operands = cast.operands().iter().map(|op| self.operand_value(op));
440 let value =
441 Value::make_record(record_type.keys().cloned().zip(operands), program, path.clone());
442 (value, destination)
443 }
444 }
445 }
446 CastLossy(cast_lossy) => {
447 match cast_lossy.cast_type() {
448 CastType::Plaintext(PlaintextType::Literal(literal_type)) => {
449 let operand = self.operand_value(&cast_lossy.operands()[0]);
451 let Some(value) = operand.cast_lossy(literal_type) else {
452 halt_no_span!("Cast failure");
453 };
454 let destination = cast_lossy.destinations()[0].clone();
455 (value, destination)
456 }
457 _ => tc_fail!(),
458 }
459 }
460 CommitBHP256(commit) => commit_function!(commit, CommitVariant::CommitBHP256),
461 CommitBHP512(commit) => commit_function!(commit, CommitVariant::CommitBHP512),
462 CommitBHP768(commit) => commit_function!(commit, CommitVariant::CommitBHP768),
463 CommitBHP1024(commit) => commit_function!(commit, CommitVariant::CommitBHP1024),
464 CommitPED64(commit) => commit_function!(commit, CommitVariant::CommitPED64),
465 CommitPED128(commit) => commit_function!(commit, CommitVariant::CommitPED128),
466 Div(div) => binary!(div, Div),
467 DivWrapped(div_wrapped) => binary!(div_wrapped, DivWrapped),
468 Double(double) => unary!(double, Double),
469 GreaterThan(gt) => binary!(gt, Gt),
470 GreaterThanOrEqual(gte) => binary!(gte, Gte),
471 HashBHP256(hash) => hash_function!(hash, HashVariant::HashBHP256),
472 HashBHP512(hash) => hash_function!(hash, HashVariant::HashBHP512),
473 HashBHP768(hash) => hash_function!(hash, HashVariant::HashBHP768),
474 HashBHP1024(hash) => hash_function!(hash, HashVariant::HashBHP1024),
475 HashKeccak256(hash) => hash_function!(hash, HashVariant::HashKeccak256),
476 HashKeccak384(hash) => hash_function!(hash, HashVariant::HashKeccak384),
477 HashKeccak512(hash) => hash_function!(hash, HashVariant::HashKeccak512),
478 HashPED64(hash) => hash_function!(hash, HashVariant::HashPED64),
479 HashPED128(hash) => hash_function!(hash, HashVariant::HashPED128),
480 HashPSD2(hash) => hash_function!(hash, HashVariant::HashPSD2),
481 HashPSD4(hash) => hash_function!(hash, HashVariant::HashPSD4),
482 HashPSD8(hash) => hash_function!(hash, HashVariant::HashPSD8),
483 HashSha3_256(hash) => hash_function!(hash, HashVariant::HashSha3_256),
484 HashSha3_384(hash) => hash_function!(hash, HashVariant::HashSha3_384),
485 HashSha3_512(hash) => hash_function!(hash, HashVariant::HashSha3_512),
486 HashBHP256Raw(hash) => hash_function!(hash, HashVariant::HashBHP256Raw),
487 HashBHP512Raw(hash) => hash_function!(hash, HashVariant::HashBHP512Raw),
488 HashBHP768Raw(hash) => hash_function!(hash, HashVariant::HashBHP768Raw),
489 HashBHP1024Raw(hash) => hash_function!(hash, HashVariant::HashBHP1024Raw),
490 HashKeccak256Raw(hash) => hash_function!(hash, HashVariant::HashKeccak256Raw),
491 HashKeccak384Raw(hash) => hash_function!(hash, HashVariant::HashKeccak384Raw),
492 HashKeccak512Raw(hash) => hash_function!(hash, HashVariant::HashKeccak512Raw),
493 HashPED64Raw(hash) => hash_function!(hash, HashVariant::HashPED64Raw),
494 HashPED128Raw(hash) => hash_function!(hash, HashVariant::HashPED128Raw),
495 HashPSD2Raw(hash) => hash_function!(hash, HashVariant::HashPSD2Raw),
496 HashPSD4Raw(hash) => hash_function!(hash, HashVariant::HashPSD4Raw),
497 HashPSD8Raw(hash) => hash_function!(hash, HashVariant::HashPSD8Raw),
498 HashSha3_256Raw(hash) => hash_function!(hash, HashVariant::HashSha3_256Raw),
499 HashSha3_384Raw(hash) => hash_function!(hash, HashVariant::HashSha3_384Raw),
500 HashSha3_512Raw(hash) => hash_function!(hash, HashVariant::HashSha3_512Raw),
501 HashKeccak256Native(hash) => hash_function!(hash, HashVariant::HashKeccak256Native),
502 HashKeccak384Native(hash) => hash_function!(hash, HashVariant::HashKeccak384Native),
503 HashKeccak512Native(hash) => hash_function!(hash, HashVariant::HashKeccak512Native),
504 HashSha3_256Native(hash) => hash_function!(hash, HashVariant::HashSha3_256Native),
505 HashSha3_384Native(hash) => hash_function!(hash, HashVariant::HashSha3_384Native),
506 HashSha3_512Native(hash) => hash_function!(hash, HashVariant::HashSha3_512Native),
507 HashKeccak256NativeRaw(hash) => hash_function!(hash, HashVariant::HashKeccak256NativeRaw),
508 HashKeccak384NativeRaw(hash) => hash_function!(hash, HashVariant::HashKeccak384NativeRaw),
509 HashKeccak512NativeRaw(hash) => hash_function!(hash, HashVariant::HashKeccak512NativeRaw),
510 HashSha3_256NativeRaw(hash) => hash_function!(hash, HashVariant::HashSha3_256NativeRaw),
511 HashSha3_384NativeRaw(hash) => hash_function!(hash, HashVariant::HashSha3_384NativeRaw),
512 HashSha3_512NativeRaw(hash) => hash_function!(hash, HashVariant::HashSha3_512NativeRaw),
513 ECDSAVerifyDigest(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::Digest),
514 ECDSAVerifyDigestEth(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::DigestEth),
515 ECDSAVerifyKeccak256(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashKeccak256),
516 ECDSAVerifyKeccak256Raw(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashKeccak256Raw),
517 ECDSAVerifyKeccak256Eth(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashKeccak256Eth),
518 ECDSAVerifyKeccak384(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashKeccak384),
519 ECDSAVerifyKeccak384Raw(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashKeccak384Raw),
520 ECDSAVerifyKeccak384Eth(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashKeccak384Eth),
521 ECDSAVerifyKeccak512(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashKeccak512),
522 ECDSAVerifyKeccak512Raw(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashKeccak512Raw),
523 ECDSAVerifyKeccak512Eth(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashKeccak512Eth),
524 ECDSAVerifySha3_256(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashSha3_256),
525 ECDSAVerifySha3_256Raw(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashSha3_256Raw),
526 ECDSAVerifySha3_256Eth(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashSha3_256Eth),
527 ECDSAVerifySha3_384(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashSha3_384),
528 ECDSAVerifySha3_384Raw(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashSha3_384Raw),
529 ECDSAVerifySha3_384Eth(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashSha3_384Eth),
530 ECDSAVerifySha3_512(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashSha3_512),
531 ECDSAVerifySha3_512Raw(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashSha3_512Raw),
532 ECDSAVerifySha3_512Eth(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashSha3_512Eth),
533 HashManyPSD2(_) | HashManyPSD4(_) | HashManyPSD8(_) => panic!("these functions don't exist yet"),
534 Inv(inv) => unary!(inv, Inverse),
535 IsEq(eq) => binary!(eq, Eq),
536 IsNeq(neq) => binary!(neq, Neq),
537 LessThan(lt) => binary!(lt, Lt),
538 LessThanOrEqual(lte) => binary!(lte, Lte),
539 Modulo(modulo) => binary!(modulo, Mod),
540 Mul(mul) => binary!(mul, Mul),
541 MulWrapped(mul_wrapped) => binary!(mul_wrapped, MulWrapped),
542 Nand(nand) => binary!(nand, Nand),
543 Neg(neg) => unary!(neg, Negate),
544 Nor(nor) => binary!(nor, Nor),
545 Not(not) => unary!(not, Not),
546 Or(or) => binary!(or, BitwiseOr),
547 Pow(pow) => binary!(pow, Pow),
548 PowWrapped(pow_wrapped) => binary!(pow_wrapped, PowWrapped),
549 Rem(rem) => binary!(rem, Rem),
550 RemWrapped(rem_wrapped) => binary!(rem_wrapped, RemWrapped),
551 Shl(shl) => binary!(shl, Shl),
552 ShlWrapped(shl_wrapped) => binary!(shl_wrapped, ShlWrapped),
553 Shr(shr) => binary!(shr, Shr),
554 ShrWrapped(shr_wrapped) => binary!(shr_wrapped, ShrWrapped),
555 SignVerify(schnorr) => schnorr_function!(schnorr, false),
556 Square(square) => unary!(square, Square),
557 SquareRoot(sqrt) => unary!(sqrt, SquareRoot),
558 Sub(sub) => binary!(sub, Sub),
559 SubWrapped(sub_wrapped) => binary!(sub_wrapped, SubWrapped),
560 Ternary(ternary) => {
561 let condition = self.operand_value(&ternary.operands()[0]);
562 let result = match condition.try_into() {
563 Ok(true) => &ternary.operands()[1],
564 Ok(false) => &ternary.operands()[2],
565 _ => tc_fail!(),
566 };
567 self.increment_instruction_index();
568 (self.operand_value(result), ternary.destinations()[0].clone())
569 }
570 Xor(xor) => binary!(xor, Xor),
571 SerializeBits(serialize_bits) => serialize_function!(serialize_bits, SerializeVariant::ToBits),
572 SerializeBitsRaw(serialize_bits_raw) => {
573 serialize_function!(serialize_bits_raw, SerializeVariant::ToBitsRaw)
574 }
575 DeserializeBits(deserialize_bits) => deserialize_function!(deserialize_bits, DeserializeVariant::FromBits),
576 DeserializeBitsRaw(deserialize_bits_raw) => {
577 deserialize_function!(deserialize_bits_raw, DeserializeVariant::FromBitsRaw)
578 }
579 };
580
581 self.set_register(destination, value);
582
583 Ok(())
584 }
585
586 fn outputs(&self) -> Vec<Value> {
587 let Some(Frame { element, .. }) = self.frames.last() else {
588 panic!("frame expected");
589 };
590 let Element::AleoExecution { context, .. } = element else {
591 panic!("aleo execution expected");
592 };
593
594 let mut result = match &**context {
595 AleoContext::Closure(closure) => {
596 closure.outputs().iter().map(|output| self.operand_value(output.operand())).collect()
597 }
598 AleoContext::Function(function) => {
599 function.outputs().iter().map(|output| self.operand_value(output.operand())).collect()
600 }
601 AleoContext::Finalize(_finalize) => Vec::new(),
602 };
603
604 if result.is_empty() {
605 result.push(Value::make_unit());
606 }
607 result
608 }
609
610 fn step_aleo_command(&mut self, command: Command<TestnetV0>) -> Result<()> {
611 use Command::*;
612
613 let (value, destination) = match command {
614 Instruction(instruction) => {
615 self.step_aleo_instruction(instruction)?;
616 return Ok(());
617 }
618 Await(await_) => {
619 let value = self.get_register(await_.register());
620 let Some(asyncs) = value.as_future() else {
621 halt_no_span!("attempted to await a non-future");
622 };
623 self.contexts.add_future(asyncs.to_vec());
624 self.increment_instruction_index();
625 return Ok(());
626 }
627 Contains(contains) => {
628 #[allow(clippy::mutable_key_type)]
630 let mapping = self.mapping_by_call_operator(contains.mapping()).expect("mapping should be present");
631 let key = self.operand_value(contains.key());
632 let result = mapping.contains_key(&key).into();
633 self.increment_instruction_index();
634 (result, contains.destination().clone())
635 }
636 Get(get) => {
637 let key = self.operand_value(get.key());
638 let value = self.mapping_by_call_operator(get.mapping()).and_then(|mapping| mapping.get(&key)).cloned();
639 self.increment_instruction_index();
640
641 match value {
642 Some(v) => (v, get.destination().clone()),
643 None => halt_no_span!("map access failure: {key}"),
644 }
645 }
646 GetOrUse(get_or_use) => {
647 let key = self.operand_value(get_or_use.key());
648 let value =
649 self.mapping_by_call_operator(get_or_use.mapping()).and_then(|mapping| mapping.get(&key)).cloned();
650
651 let use_value = value.unwrap_or_else(|| self.operand_value(get_or_use.default()));
652 self.increment_instruction_index();
653
654 (use_value, get_or_use.destination().clone())
655 }
656 Remove(remove) => {
657 let key = self.operand_value(remove.key());
658 let mapping_name = snarkvm_identifier_to_symbol(remove.mapping_name());
659 let maybe_mapping = self.lookup_mapping_mut(None, mapping_name);
660 match maybe_mapping {
661 None => halt_no_span!("no such mapping {mapping_name}"),
662 Some(mapping) => {
663 mapping.remove(&key);
664 }
665 }
666 self.increment_instruction_index();
667 return Ok(());
668 }
669 Set(set) => {
670 let key = self.operand_value(set.key());
671 let value = self.operand_value(set.value());
672 let mapping_name = snarkvm_identifier_to_symbol(set.mapping_name());
673 let maybe_mapping = self.lookup_mapping_mut(None, mapping_name);
674 match maybe_mapping {
675 None => halt_no_span!("no such mapping {mapping_name}"),
676 Some(mapping) => {
677 mapping.insert(key, value);
678 }
679 }
680 self.increment_instruction_index();
681 return Ok(());
682 }
683 RandChaCha(rand) => {
684 use CoreFunction::*;
686 let function = ChaChaRand(rand.destination_type());
687 let value =
688 interpreter_value::evaluate_core_function(self, function, &[], Default::default())?.unwrap();
689 self.increment_instruction_index();
690 (value, rand.destination().clone())
691 }
692 BranchEq(branch_eq) => {
693 let first = self.operand_value(branch_eq.first());
694 let second = self.operand_value(branch_eq.second());
695 if first.eq(&second)? {
696 self.branch(branch_eq.position());
697 } else {
698 self.increment_instruction_index();
699 }
700 return Ok(());
701 }
702 BranchNeq(branch_neq) => {
703 let first = self.operand_value(branch_neq.first());
704 let second = self.operand_value(branch_neq.second());
705 if !first.eq(&second)? {
706 self.branch(branch_neq.position());
707 } else {
708 self.increment_instruction_index();
709 }
710 return Ok(());
711 }
712 Position(_) => {
713 self.increment_instruction_index();
714 return Ok(());
715 }
716 };
717
718 self.set_register(destination, value);
719
720 Ok(())
721 }
722
723 fn branch(&mut self, label: &Identifier<TestnetV0>) {
724 let Some(Frame { element: Element::AleoExecution { instruction_index, context, .. }, .. }) =
725 self.frames.last_mut()
726 else {
727 panic!();
728 };
729 let AleoContext::Finalize(finalize) = &mut **context else {
730 panic!();
731 };
732 for (i, cmd) in finalize.commands().iter().enumerate() {
733 if let Command::Position(position) = cmd
734 && position.name() == label
735 {
736 *instruction_index = i;
737 return;
738 }
739 }
740 panic!("branch to nonexistent label {label}");
741 }
742
743 pub fn step_aleo(&mut self) -> Result<()> {
744 if let Some(command) = self.next_command().cloned() {
745 self.step_aleo_command(command)?;
746 } else if let Some(instruction) = self.next_instruction().cloned() {
747 self.step_aleo_instruction(instruction)?;
748 }
749
750 if self.execution_complete() {
751 let mut outputs = self.outputs();
752 self.frames.pop();
753 self.contexts.pop();
754 if outputs.len() > 1 {
755 self.values.push(Value::make_tuple(outputs));
756 } else {
757 self.values.push(mem::take(&mut outputs[0]));
758 }
759 }
760
761 Ok(())
762 }
763}
764
765fn snarkvm_literal_type_to_type(snarkvm_type: LiteralType) -> Type {
766 use Type::*;
767 match snarkvm_type {
768 LiteralType::Address => Address,
769 LiteralType::Boolean => Boolean,
770 LiteralType::Field => Field,
771 LiteralType::Group => Group,
772 LiteralType::I8 => Integer(IntegerType::I8),
773 LiteralType::I16 => Integer(IntegerType::I16),
774 LiteralType::I32 => Integer(IntegerType::I32),
775 LiteralType::I64 => Integer(IntegerType::I64),
776 LiteralType::I128 => Integer(IntegerType::I128),
777 LiteralType::U8 => Integer(IntegerType::U8),
778 LiteralType::U16 => Integer(IntegerType::U16),
779 LiteralType::U32 => Integer(IntegerType::U32),
780 LiteralType::U64 => Integer(IntegerType::U64),
781 LiteralType::U128 => Integer(IntegerType::U128),
782 LiteralType::Scalar => Scalar,
783 LiteralType::Signature => todo!(),
784 LiteralType::String => todo!(),
785 }
786}