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::{CallOperator, CastType, Operand},
35 },
36};
37
38use std::mem;
39
40impl Cursor {
41 fn mapping_by_call_operator(&self, operator: &CallOperator<TestnetV0>) -> Option<&HashMap<Value, Value>> {
42 let (program, name) = match operator {
43 CallOperator::Locator(locator) => {
44 (Some(snarkvm_identifier_to_symbol(locator.name())), snarkvm_identifier_to_symbol(locator.resource()))
45 }
46 CallOperator::Resource(id) => (None, snarkvm_identifier_to_symbol(id)),
47 };
48 self.lookup_mapping(program, name)
49 }
50
51 fn get_register(&self, reg: &Register<TestnetV0>) -> Value {
52 let Some(Frame { element: Element::AleoExecution { registers, .. }, .. }) = self.frames.last() else {
53 panic!();
54 };
55 match reg {
56 Register::Locator(index) => {
57 registers.get(index).expect("valid .aleo code doesn't access undefined registers").clone()
58 }
59 Register::Access(index, accesses) => {
60 let value = registers.get(index).expect("valid .aleo code doesn't access undefined registers");
61 value.accesses(accesses.iter().cloned()).expect("Accesses should work.")
62 }
63 }
64 }
65
66 fn set_register(&mut self, reg: Register<TestnetV0>, value: Value) {
67 let Some(Frame { element: Element::AleoExecution { registers, .. }, .. }) = self.frames.last_mut() else {
68 panic!();
69 };
70
71 match reg {
72 Register::Locator(index) => {
73 registers.insert(index, value);
74 }
75 Register::Access(_, _) => panic!("Can't happen"),
76 }
77 }
78
79 fn instructions_len(&self) -> usize {
80 let Some(Frame { element: Element::AleoExecution { context, .. }, .. }) = self.frames.last() else {
81 panic!();
82 };
83 match &**context {
84 AleoContext::Closure(closure) => closure.instructions().len(),
85 AleoContext::Function(function) => function.instructions().len(),
86 AleoContext::Finalize(finalize) => finalize.commands().len(),
87 }
88 }
89
90 fn increment_instruction_index(&mut self) {
91 let Some(Frame { element: Element::AleoExecution { instruction_index, .. }, .. }) = self.frames.last_mut()
92 else {
93 panic!();
94 };
95 *instruction_index += 1;
96 }
97
98 fn execution_complete(&self) -> bool {
99 let Some(Frame { element: Element::AleoExecution { instruction_index, .. }, .. }) = self.frames.last() else {
100 panic!();
101 };
102 *instruction_index >= self.instructions_len()
103 }
104
105 fn next_instruction(&self) -> Option<&Instruction<TestnetV0>> {
106 let Some(Frame { element: Element::AleoExecution { instruction_index, context, .. }, .. }) = self.frames.last()
107 else {
108 panic!();
109 };
110 match &**context {
111 AleoContext::Closure(closure) => closure.instructions().get(*instruction_index),
112 AleoContext::Function(function) => function.instructions().get(*instruction_index),
113 AleoContext::Finalize(_) => None,
114 }
115 }
116
117 fn next_command(&self) -> Option<&Command<TestnetV0>> {
118 let Some(Frame { element: Element::AleoExecution { instruction_index, context, .. }, .. }) = self.frames.last()
119 else {
120 panic!();
121 };
122 match &**context {
123 AleoContext::Closure(_) | AleoContext::Function(_) => None,
124 AleoContext::Finalize(finalize) => finalize.commands().get(*instruction_index),
125 }
126 }
127
128 fn operand_value(&self, operand: &Operand<TestnetV0>) -> Value {
129 match operand {
130 Operand::Literal(literal) => literal.clone().into(),
131 Operand::Register(register) => self.get_register(register).clone(),
132 Operand::ProgramID(_) => todo!(),
133 Operand::Signer => self.signer.clone(),
134 Operand::Caller => {
135 if let Some(function_context) = self.contexts.last() {
136 function_context.caller.clone()
137 } else {
138 self.signer.clone()
139 }
140 }
141 Operand::BlockHeight => self.block_height.into(),
142 Operand::NetworkID => todo!(),
143 Operand::Checksum(_) => todo!("Look up the program in the global namespace and get its checksum"),
144 Operand::Edition(_) => todo!("Look up the program in the global namespace and get its edition"),
145 Operand::ProgramOwner(_) => todo!("Prompt user if not set"),
146 }
147 }
148
149 fn step_aleo_instruction(&mut self, instruction: Instruction<TestnetV0>) -> Result<()> {
150 use Instruction::*;
153
154 let Some(Frame { step, .. }) = self.frames.last() else {
155 panic!("frame expected");
156 };
157
158 macro_rules! unary {
159 ($svm_op: expr, $op: ident) => {{
160 let operand = self.operand_value(&$svm_op.operands()[0]);
161 let value =
162 interpreter_value::evaluate_unary(Default::default(), UnaryOperation::$op, &operand, &None)?;
163 self.increment_instruction_index();
164 (value, $svm_op.destinations()[0].clone())
165 }};
166 }
167
168 macro_rules! binary {
169 ($svm_op: expr, $op: ident) => {{
170 let operand0 = self.operand_value(&$svm_op.operands()[0]);
171 let operand1 = self.operand_value(&$svm_op.operands()[1]);
172 let value = interpreter_value::evaluate_binary(
173 Default::default(),
174 BinaryOperation::$op,
175 &operand0,
176 &operand1,
177 &None,
178 )?;
179 self.increment_instruction_index();
180 (value, $svm_op.destinations()[0].clone())
181 }};
182 }
183
184 macro_rules! commit_function {
185 ($commit: expr,
186 $to_address: ident,
187 $to_field: ident,
188 $to_group: ident,
189 ) => {{
190 let core_function = match $commit.destination_type() {
191 LiteralType::Address => CoreFunction::$to_address,
192 LiteralType::Field => CoreFunction::$to_field,
193 LiteralType::Group => CoreFunction::$to_group,
194 _ => panic!("invalid commit destination type"),
195 };
196
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,
209 $to_address: ident,
210 $to_field: ident,
211 $to_group: ident,
212 $to_i8: ident,
213 $to_i16: ident,
214 $to_i32: ident,
215 $to_i64: ident,
216 $to_i128: ident,
217 $to_u8: ident,
218 $to_u16: ident,
219 $to_u32: ident,
220 $to_u64: ident,
221 $to_u128: ident,
222 $to_scalar: ident,
223 ) => {{
224 let core_function = match $hash.destination_type() {
225 PlaintextType::Literal(LiteralType::Address) => CoreFunction::$to_address,
226 PlaintextType::Literal(LiteralType::Field) => CoreFunction::$to_field,
227 PlaintextType::Literal(LiteralType::Group) => CoreFunction::$to_group,
228 PlaintextType::Literal(LiteralType::I8) => CoreFunction::$to_i8,
229 PlaintextType::Literal(LiteralType::I16) => CoreFunction::$to_i16,
230 PlaintextType::Literal(LiteralType::I32) => CoreFunction::$to_i32,
231 PlaintextType::Literal(LiteralType::I64) => CoreFunction::$to_i64,
232 PlaintextType::Literal(LiteralType::I128) => CoreFunction::$to_i128,
233 PlaintextType::Literal(LiteralType::U8) => CoreFunction::$to_u8,
234 PlaintextType::Literal(LiteralType::U16) => CoreFunction::$to_u16,
235 PlaintextType::Literal(LiteralType::U32) => CoreFunction::$to_u32,
236 PlaintextType::Literal(LiteralType::U64) => CoreFunction::$to_u64,
237 PlaintextType::Literal(LiteralType::U128) => CoreFunction::$to_u128,
238 PlaintextType::Literal(LiteralType::Scalar) => CoreFunction::$to_scalar,
239 _ => panic!("invalid hash destination type"),
240 };
241 let operand_value = self.operand_value(&$hash.operands()[0]);
242 self.values.push(operand_value);
243 let value = interpreter_value::evaluate_core_function(self, core_function, &[], Span::default())?;
244 self.increment_instruction_index();
245 (value.expect("Evaluation should work"), $hash.destinations()[0].clone())
246 }};
247 }
248
249 let (value, destination) = match instruction {
250 Abs(abs) => unary!(abs, Abs),
251 AbsWrapped(abs_wrapped) => unary!(abs_wrapped, AbsWrapped),
252 Add(add) => binary!(add, Add),
253 AddWrapped(add_wrapped) => binary!(add_wrapped, AddWrapped),
254 And(and) => binary!(and, BitwiseAnd),
255 AssertEq(assert_eq) => {
256 let operand0 = self.operand_value(&assert_eq.operands()[0]);
257 let operand1 = self.operand_value(&assert_eq.operands()[1]);
258 if !operand0.eq(&operand1)? {
259 halt_no_span!("assertion failure: {operand0} != {operand1}");
260 }
261 self.increment_instruction_index();
262 return Ok(());
263 }
264 AssertNeq(assert_neq) => {
265 let operand0 = self.operand_value(&assert_neq.operands()[0]);
266 let operand1 = self.operand_value(&assert_neq.operands()[1]);
267 if operand0.eq(&operand1)? {
268 halt_no_span!("assertion failure: {operand0} != {operand1}");
269 }
270 self.increment_instruction_index();
271 return Ok(());
272 }
273 Async(async_) if *step == 0 => {
274 let program = self.contexts.current_program().expect("there should be a program");
275 let name = snarkvm_identifier_to_symbol(async_.function_name());
276 let arguments: Vec<Value> = async_.operands().iter().map(|op| self.operand_value(op)).collect();
277 if self.really_async {
278 self.increment_instruction_index();
279 let async_ex =
280 AsyncExecution::AsyncFunctionCall { function: Location::new(program, vec![name]), arguments };
281 (vec![async_ex].into(), async_.destinations()[0].clone())
282 } else {
283 self.do_call(
284 program,
285 &[name],
286 arguments.into_iter(),
287 true, Span::default(),
289 )?;
290 self.increment_step();
291 return Ok(());
292 }
293 }
294 Call(call) if *step == 0 => {
295 let (program, name) = match call.operator() {
296 CallOperator::Locator(locator) => (
297 snarkvm_identifier_to_symbol(locator.resource()),
298 snarkvm_identifier_to_symbol(locator.program_id().name()),
299 ),
300 CallOperator::Resource(id) => (
301 snarkvm_identifier_to_symbol(id),
302 self.contexts.current_program().expect("there should be a program"),
303 ),
304 };
305 let arguments: Vec<Value> = call.operands().iter().map(|op| self.operand_value(op)).collect();
306 self.do_call(
307 program,
308 &[name],
309 arguments.into_iter(),
310 false, Span::default(),
312 )?;
313 self.increment_step();
314 return Ok(());
315 }
316 Async(async_) if *step == 1 => {
317 self.values.pop();
319 self.set_register(async_.destinations()[0].clone(), Vec::<AsyncExecution>::new().into());
320 self.increment_instruction_index();
321 return Ok(());
322 }
323 Call(call) if *step == 1 => {
324 let Some(result) = self.values.pop() else {
326 panic!("should have a result");
327 };
328 if call.destinations().len() == 1 {
329 self.set_register(call.destinations()[0].clone(), result);
330 } else {
331 for (i, dest) in call.destinations().iter().enumerate() {
332 self.set_register(
333 dest.clone(),
334 result.tuple_index(i).expect("Function returning multiple values should create a tuple."),
335 );
336 }
337 }
338 self.increment_instruction_index();
339 return Ok(());
340 }
341 Call(_) | Async(_) => unreachable!("all cases covered above"),
342 Cast(cast) => {
343 let destination = cast.destinations()[0].clone();
344
345 self.increment_instruction_index();
346
347 match cast.cast_type() {
348 CastType::GroupXCoordinate => {
349 let value = self.operand_value(&cast.operands()[0]);
350 let mut values = vec![value];
351 let Some(result_value) = interpreter_value::evaluate_core_function(
352 &mut values,
353 CoreFunction::GroupToXCoordinate,
354 &[],
355 Default::default(),
356 )?
357 else {
358 halt_no_span!("GroupToXCoordinate didn't produce a value.");
359 };
360 (result_value, destination)
361 }
362 CastType::GroupYCoordinate => {
363 let value = self.operand_value(&cast.operands()[0]);
364 let mut values = vec![value];
365 let Some(result_value) = interpreter_value::evaluate_core_function(
366 &mut values,
367 CoreFunction::GroupToYCoordinate,
368 &[],
369 Default::default(),
370 )?
371 else {
372 halt_no_span!("GroupToYCoordinate didn't produce a value.");
373 };
374 (result_value, destination)
375 }
376 CastType::Plaintext(PlaintextType::Array(_array)) => {
377 let value = Value::make_array(cast.operands().iter().map(|op| self.operand_value(op)));
378 (value, destination)
379 }
380 CastType::Plaintext(PlaintextType::Literal(literal_type)) => {
381 let operand = self.operand_value(&cast.operands()[0]);
382 let Some(value) = operand.cast(&snarkvm_literal_type_to_type(*literal_type)) else {
383 halt_no_span!("cast failure");
384 };
385 (value, destination)
386 }
387 CastType::Plaintext(PlaintextType::Struct(struct_name)) => {
388 let name = Symbol::intern(&struct_name.to_string());
389 let struct_type = self.structs.get([name].as_slice()).expect("struct type should exist");
390 let operands = cast.operands().iter().map(|op| self.operand_value(op));
391 let value = Value::make_struct(
392 struct_type.keys().cloned().zip(operands),
393 self.current_program().unwrap(),
394 vec![name],
395 );
396 (value, destination)
397 }
398 CastType::Record(record_name) => {
399 let program = self.current_program().unwrap();
400 let name = Symbol::intern(&record_name.to_string());
401 let path = vec![name];
402 let record_type = self.records.get(&(program, path.clone())).expect("record type should exist");
403 let operands = cast.operands().iter().map(|op| self.operand_value(op));
404 let value =
405 Value::make_record(record_type.keys().cloned().zip(operands), program, path.clone());
406 (value, destination)
407 }
408 CastType::ExternalRecord(locator) => {
409 let program = Symbol::intern(&locator.program_id().name().to_string());
410 let name = Symbol::intern(&locator.resource().to_string());
411 let path = vec![name];
412 let record_type = self.records.get(&(program, path.clone())).expect("record type should exist");
413 let operands = cast.operands().iter().map(|op| self.operand_value(op));
414 let value =
415 Value::make_record(record_type.keys().cloned().zip(operands), program, path.clone());
416 (value, destination)
417 }
418 }
419 }
420 CastLossy(cast_lossy) => {
421 match cast_lossy.cast_type() {
422 CastType::Plaintext(PlaintextType::Literal(literal_type)) => {
423 let operand = self.operand_value(&cast_lossy.operands()[0]);
425 let Some(value) = operand.cast_lossy(literal_type) else {
426 halt_no_span!("Cast failure");
427 };
428 let destination = cast_lossy.destinations()[0].clone();
429 (value, destination)
430 }
431 _ => tc_fail!(),
432 }
433 }
434 CommitBHP256(commit) => {
435 commit_function!(commit, BHP256CommitToAddress, BHP256CommitToField, BHP256CommitToGroup,)
436 }
437 CommitBHP512(commit) => {
438 commit_function!(commit, BHP512CommitToAddress, BHP512CommitToField, BHP512CommitToGroup,)
439 }
440 CommitBHP768(commit) => {
441 commit_function!(commit, BHP768CommitToAddress, BHP768CommitToField, BHP768CommitToGroup,)
442 }
443 CommitBHP1024(commit) => {
444 commit_function!(commit, BHP1024CommitToAddress, BHP1024CommitToField, BHP1024CommitToGroup,)
445 }
446 CommitPED64(commit) => {
447 commit_function!(commit, Pedersen64CommitToAddress, Pedersen64CommitToField, Pedersen64CommitToGroup,)
448 }
449 CommitPED128(commit) => {
450 commit_function!(commit, Pedersen128CommitToAddress, Pedersen128CommitToField, Pedersen128CommitToGroup,)
451 }
452 Div(div) => binary!(div, Div),
453 DivWrapped(div_wrapped) => binary!(div_wrapped, DivWrapped),
454 Double(double) => unary!(double, Double),
455 GreaterThan(gt) => binary!(gt, Gt),
456 GreaterThanOrEqual(gte) => binary!(gte, Gte),
457 HashBHP256(hash) => hash_function!(
458 hash,
459 BHP256HashToAddress,
460 BHP256HashToField,
461 BHP256HashToGroup,
462 BHP256HashToI8,
463 BHP256HashToI16,
464 BHP256HashToI32,
465 BHP256HashToI64,
466 BHP256HashToI128,
467 BHP256HashToU8,
468 BHP256HashToU16,
469 BHP256HashToU32,
470 BHP256HashToU64,
471 BHP256HashToU128,
472 BHP256HashToScalar,
473 ),
474 HashBHP512(hash) => hash_function!(
475 hash,
476 BHP512HashToAddress,
477 BHP512HashToField,
478 BHP512HashToGroup,
479 BHP512HashToI8,
480 BHP512HashToI16,
481 BHP512HashToI32,
482 BHP512HashToI64,
483 BHP512HashToI128,
484 BHP512HashToU8,
485 BHP512HashToU16,
486 BHP512HashToU32,
487 BHP512HashToU64,
488 BHP512HashToU128,
489 BHP512HashToScalar,
490 ),
491 HashBHP768(hash) => hash_function!(
492 hash,
493 BHP768HashToAddress,
494 BHP768HashToField,
495 BHP768HashToGroup,
496 BHP768HashToI8,
497 BHP768HashToI16,
498 BHP768HashToI32,
499 BHP768HashToI64,
500 BHP768HashToI128,
501 BHP768HashToU8,
502 BHP768HashToU16,
503 BHP768HashToU32,
504 BHP768HashToU64,
505 BHP768HashToU128,
506 BHP768HashToScalar,
507 ),
508 HashBHP1024(hash) => hash_function!(
509 hash,
510 BHP1024HashToAddress,
511 BHP1024HashToField,
512 BHP1024HashToGroup,
513 BHP1024HashToI8,
514 BHP1024HashToI16,
515 BHP1024HashToI32,
516 BHP1024HashToI64,
517 BHP1024HashToI128,
518 BHP1024HashToU8,
519 BHP1024HashToU16,
520 BHP1024HashToU32,
521 BHP1024HashToU64,
522 BHP1024HashToU128,
523 BHP1024HashToScalar,
524 ),
525 HashKeccak256(hash) => hash_function!(
526 hash,
527 Keccak256HashToAddress,
528 Keccak256HashToField,
529 Keccak256HashToGroup,
530 Keccak256HashToI8,
531 Keccak256HashToI16,
532 Keccak256HashToI32,
533 Keccak256HashToI64,
534 Keccak256HashToI128,
535 Keccak256HashToU8,
536 Keccak256HashToU16,
537 Keccak256HashToU32,
538 Keccak256HashToU64,
539 Keccak256HashToU128,
540 Keccak256HashToScalar,
541 ),
542 HashKeccak384(hash) => hash_function!(
543 hash,
544 Keccak384HashToAddress,
545 Keccak384HashToField,
546 Keccak384HashToGroup,
547 Keccak384HashToI8,
548 Keccak384HashToI16,
549 Keccak384HashToI32,
550 Keccak384HashToI64,
551 Keccak384HashToI128,
552 Keccak384HashToU8,
553 Keccak384HashToU16,
554 Keccak384HashToU32,
555 Keccak384HashToU64,
556 Keccak384HashToU128,
557 Keccak384HashToScalar,
558 ),
559 HashKeccak512(hash) => hash_function!(
560 hash,
561 Keccak512HashToAddress,
562 Keccak512HashToField,
563 Keccak512HashToGroup,
564 Keccak512HashToI8,
565 Keccak512HashToI16,
566 Keccak512HashToI32,
567 Keccak512HashToI64,
568 Keccak512HashToI128,
569 Keccak512HashToU8,
570 Keccak512HashToU16,
571 Keccak512HashToU32,
572 Keccak512HashToU64,
573 Keccak512HashToU128,
574 Keccak512HashToScalar,
575 ),
576 HashPED64(hash) => hash_function!(
577 hash,
578 Pedersen64HashToAddress,
579 Pedersen64HashToField,
580 Pedersen64HashToGroup,
581 Pedersen64HashToI8,
582 Pedersen64HashToI16,
583 Pedersen64HashToI32,
584 Pedersen64HashToI64,
585 Pedersen64HashToI128,
586 Pedersen64HashToU8,
587 Pedersen64HashToU16,
588 Pedersen64HashToU32,
589 Pedersen64HashToU64,
590 Pedersen64HashToU128,
591 Pedersen64HashToScalar,
592 ),
593 HashPED128(hash) => hash_function!(
594 hash,
595 Pedersen128HashToAddress,
596 Pedersen128HashToField,
597 Pedersen128HashToGroup,
598 Pedersen128HashToI8,
599 Pedersen128HashToI16,
600 Pedersen128HashToI32,
601 Pedersen128HashToI64,
602 Pedersen128HashToI128,
603 Pedersen128HashToU8,
604 Pedersen128HashToU16,
605 Pedersen128HashToU32,
606 Pedersen128HashToU64,
607 Pedersen128HashToU128,
608 Pedersen128HashToScalar,
609 ),
610 HashPSD2(hash) => hash_function!(
611 hash,
612 Poseidon2HashToAddress,
613 Poseidon2HashToField,
614 Poseidon2HashToGroup,
615 Poseidon2HashToI8,
616 Poseidon2HashToI16,
617 Poseidon2HashToI32,
618 Poseidon2HashToI64,
619 Poseidon2HashToI128,
620 Poseidon2HashToU8,
621 Poseidon2HashToU16,
622 Poseidon2HashToU32,
623 Poseidon2HashToU64,
624 Poseidon2HashToU128,
625 Poseidon2HashToScalar,
626 ),
627 HashPSD4(hash) => hash_function!(
628 hash,
629 Poseidon4HashToAddress,
630 Poseidon4HashToField,
631 Poseidon4HashToGroup,
632 Poseidon4HashToI8,
633 Poseidon4HashToI16,
634 Poseidon4HashToI32,
635 Poseidon4HashToI64,
636 Poseidon4HashToI128,
637 Poseidon4HashToU8,
638 Poseidon4HashToU16,
639 Poseidon4HashToU32,
640 Poseidon4HashToU64,
641 Poseidon4HashToU128,
642 Poseidon4HashToScalar,
643 ),
644 HashPSD8(hash) => hash_function!(
645 hash,
646 Poseidon8HashToAddress,
647 Poseidon8HashToField,
648 Poseidon8HashToGroup,
649 Poseidon8HashToI8,
650 Poseidon8HashToI16,
651 Poseidon8HashToI32,
652 Poseidon8HashToI64,
653 Poseidon8HashToI128,
654 Poseidon8HashToU8,
655 Poseidon8HashToU16,
656 Poseidon8HashToU32,
657 Poseidon8HashToU64,
658 Poseidon8HashToU128,
659 Poseidon8HashToScalar,
660 ),
661 HashSha3_256(hash) => hash_function!(
662 hash,
663 SHA3_256HashToAddress,
664 SHA3_256HashToField,
665 SHA3_256HashToGroup,
666 SHA3_256HashToI8,
667 SHA3_256HashToI16,
668 SHA3_256HashToI32,
669 SHA3_256HashToI64,
670 SHA3_256HashToI128,
671 SHA3_256HashToU8,
672 SHA3_256HashToU16,
673 SHA3_256HashToU32,
674 SHA3_256HashToU64,
675 SHA3_256HashToU128,
676 SHA3_256HashToScalar,
677 ),
678 HashSha3_384(hash) => hash_function!(
679 hash,
680 SHA3_384HashToAddress,
681 SHA3_384HashToField,
682 SHA3_384HashToGroup,
683 SHA3_384HashToI8,
684 SHA3_384HashToI16,
685 SHA3_384HashToI32,
686 SHA3_384HashToI64,
687 SHA3_384HashToI128,
688 SHA3_384HashToU8,
689 SHA3_384HashToU16,
690 SHA3_384HashToU32,
691 SHA3_384HashToU64,
692 SHA3_384HashToU128,
693 SHA3_384HashToScalar,
694 ),
695 HashSha3_512(hash) => hash_function!(
696 hash,
697 SHA3_512HashToAddress,
698 SHA3_512HashToField,
699 SHA3_512HashToGroup,
700 SHA3_512HashToI8,
701 SHA3_512HashToI16,
702 SHA3_512HashToI32,
703 SHA3_512HashToI64,
704 SHA3_512HashToI128,
705 SHA3_512HashToU8,
706 SHA3_512HashToU16,
707 SHA3_512HashToU32,
708 SHA3_512HashToU64,
709 SHA3_512HashToU128,
710 SHA3_512HashToScalar,
711 ),
712 HashManyPSD2(_) | HashManyPSD4(_) | HashManyPSD8(_) => panic!("these instructions don't exist yet"),
713 Inv(inv) => unary!(inv, Inverse),
714 IsEq(eq) => binary!(eq, Eq),
715 IsNeq(neq) => binary!(neq, Neq),
716 LessThan(lt) => binary!(lt, Lt),
717 LessThanOrEqual(lte) => binary!(lte, Lte),
718 Modulo(modulo) => binary!(modulo, Mod),
719 Mul(mul) => binary!(mul, Mul),
720 MulWrapped(mul_wrapped) => binary!(mul_wrapped, MulWrapped),
721 Nand(nand) => binary!(nand, Nand),
722 Neg(neg) => unary!(neg, Negate),
723 Nor(nor) => binary!(nor, Nor),
724 Not(not) => unary!(not, Not),
725 Or(or) => binary!(or, BitwiseOr),
726 Pow(pow) => binary!(pow, Pow),
727 PowWrapped(pow_wrapped) => binary!(pow_wrapped, PowWrapped),
728 Rem(rem) => binary!(rem, Rem),
729 RemWrapped(rem_wrapped) => binary!(rem_wrapped, RemWrapped),
730 Shl(shl) => binary!(shl, Shl),
731 ShlWrapped(shl_wrapped) => binary!(shl_wrapped, ShlWrapped),
732 Shr(shr) => binary!(shr, Shr),
733 ShrWrapped(shr_wrapped) => binary!(shr_wrapped, ShrWrapped),
734 SignVerify(_) => todo!(),
735 Square(square) => unary!(square, Square),
736 SquareRoot(sqrt) => unary!(sqrt, SquareRoot),
737 Sub(sub) => binary!(sub, Sub),
738 SubWrapped(sub_wrapped) => binary!(sub_wrapped, SubWrapped),
739 Ternary(ternary) => {
740 let condition = self.operand_value(&ternary.operands()[0]);
741 let result = match condition.try_into() {
742 Ok(true) => &ternary.operands()[1],
743 Ok(false) => &ternary.operands()[2],
744 _ => tc_fail!(),
745 };
746 self.increment_instruction_index();
747 (self.operand_value(result), ternary.destinations()[0].clone())
748 }
749 Xor(xor) => binary!(xor, Xor),
750 };
751
752 self.set_register(destination, value);
753
754 Ok(())
755 }
756
757 fn outputs(&self) -> Vec<Value> {
758 let Some(Frame { element, .. }) = self.frames.last() else {
759 panic!("frame expected");
760 };
761 let Element::AleoExecution { context, .. } = element else {
762 panic!("aleo execution expected");
763 };
764
765 let mut result = match &**context {
766 AleoContext::Closure(closure) => {
767 closure.outputs().iter().map(|output| self.operand_value(output.operand())).collect()
768 }
769 AleoContext::Function(function) => {
770 function.outputs().iter().map(|output| self.operand_value(output.operand())).collect()
771 }
772 AleoContext::Finalize(_finalize) => Vec::new(),
773 };
774
775 if result.is_empty() {
776 result.push(Value::make_unit());
777 }
778 result
779 }
780
781 fn step_aleo_command(&mut self, command: Command<TestnetV0>) -> Result<()> {
782 use Command::*;
783
784 let (value, destination) = match command {
785 Instruction(instruction) => {
786 self.step_aleo_instruction(instruction)?;
787 return Ok(());
788 }
789 Await(await_) => {
790 let value = self.get_register(await_.register());
791 let Some(asyncs) = value.as_future() else {
792 halt_no_span!("attempted to await a non-future");
793 };
794 self.contexts.add_future(asyncs.to_vec());
795 self.increment_instruction_index();
796 return Ok(());
797 }
798 Contains(contains) => {
799 #[allow(clippy::mutable_key_type)]
801 let mapping = self.mapping_by_call_operator(contains.mapping()).expect("mapping should be present");
802 let key = self.operand_value(contains.key());
803 let result = mapping.contains_key(&key).into();
804 self.increment_instruction_index();
805 (result, contains.destination().clone())
806 }
807 Get(get) => {
808 let key = self.operand_value(get.key());
809 let value = self.mapping_by_call_operator(get.mapping()).and_then(|mapping| mapping.get(&key)).cloned();
810 self.increment_instruction_index();
811
812 match value {
813 Some(v) => (v, get.destination().clone()),
814 None => halt_no_span!("map access failure: {key}"),
815 }
816 }
817 GetOrUse(get_or_use) => {
818 let key = self.operand_value(get_or_use.key());
819 let value =
820 self.mapping_by_call_operator(get_or_use.mapping()).and_then(|mapping| mapping.get(&key)).cloned();
821
822 let use_value = value.unwrap_or_else(|| self.operand_value(get_or_use.default()));
823 self.increment_instruction_index();
824
825 (use_value, get_or_use.destination().clone())
826 }
827 Remove(remove) => {
828 let key = self.operand_value(remove.key());
829 let mapping_name = snarkvm_identifier_to_symbol(remove.mapping_name());
830 let maybe_mapping = self.lookup_mapping_mut(None, mapping_name);
831 match maybe_mapping {
832 None => halt_no_span!("no such mapping {mapping_name}"),
833 Some(mapping) => {
834 mapping.remove(&key);
835 }
836 }
837 self.increment_instruction_index();
838 return Ok(());
839 }
840 Set(set) => {
841 let key = self.operand_value(set.key());
842 let value = self.operand_value(set.value());
843 let mapping_name = snarkvm_identifier_to_symbol(set.mapping_name());
844 let maybe_mapping = self.lookup_mapping_mut(None, mapping_name);
845 match maybe_mapping {
846 None => halt_no_span!("no such mapping {mapping_name}"),
847 Some(mapping) => {
848 mapping.insert(key, value);
849 }
850 }
851 self.increment_instruction_index();
852 return Ok(());
853 }
854 RandChaCha(rand) => {
855 use CoreFunction::*;
857 let function = match rand.destination_type() {
858 LiteralType::Address => ChaChaRandAddress,
859 LiteralType::Boolean => ChaChaRandBool,
860 LiteralType::Field => ChaChaRandField,
861 LiteralType::Group => ChaChaRandGroup,
862 LiteralType::I8 => ChaChaRandI8,
863 LiteralType::I16 => ChaChaRandI16,
864 LiteralType::I32 => ChaChaRandI32,
865 LiteralType::I64 => ChaChaRandI64,
866 LiteralType::I128 => ChaChaRandI128,
867 LiteralType::U8 => ChaChaRandU8,
868 LiteralType::U16 => ChaChaRandU16,
869 LiteralType::U32 => ChaChaRandU32,
870 LiteralType::U64 => ChaChaRandU64,
871 LiteralType::U128 => ChaChaRandU128,
872 LiteralType::Scalar => ChaChaRandScalar,
873 LiteralType::Signature => todo!(),
874 LiteralType::String => todo!(),
875 };
876 let value =
877 interpreter_value::evaluate_core_function(self, function, &[], Default::default())?.unwrap();
878 self.increment_instruction_index();
879 (value, rand.destination().clone())
880 }
881 BranchEq(branch_eq) => {
882 let first = self.operand_value(branch_eq.first());
883 let second = self.operand_value(branch_eq.second());
884 if first.eq(&second)? {
885 self.branch(branch_eq.position());
886 } else {
887 self.increment_instruction_index();
888 }
889 return Ok(());
890 }
891 BranchNeq(branch_neq) => {
892 let first = self.operand_value(branch_neq.first());
893 let second = self.operand_value(branch_neq.second());
894 if !first.eq(&second)? {
895 self.branch(branch_neq.position());
896 } else {
897 self.increment_instruction_index();
898 }
899 return Ok(());
900 }
901 Position(_) => {
902 self.increment_instruction_index();
903 return Ok(());
904 }
905 };
906
907 self.set_register(destination, value);
908
909 Ok(())
910 }
911
912 fn branch(&mut self, label: &Identifier<TestnetV0>) {
913 let Some(Frame { element: Element::AleoExecution { instruction_index, context, .. }, .. }) =
914 self.frames.last_mut()
915 else {
916 panic!();
917 };
918 let AleoContext::Finalize(finalize) = &mut **context else {
919 panic!();
920 };
921 for (i, cmd) in finalize.commands().iter().enumerate() {
922 if let Command::Position(position) = cmd {
923 if position.name() == label {
924 *instruction_index = i;
925 return;
926 }
927 }
928 }
929 panic!("branch to nonexistent label {label}");
930 }
931
932 pub fn step_aleo(&mut self) -> Result<()> {
933 if let Some(command) = self.next_command().cloned() {
934 self.step_aleo_command(command)?;
935 } else if let Some(instruction) = self.next_instruction().cloned() {
936 self.step_aleo_instruction(instruction)?;
937 }
938
939 if self.execution_complete() {
940 let mut outputs = self.outputs();
941 self.frames.pop();
942 self.contexts.pop();
943 if outputs.len() > 1 {
944 self.values.push(Value::make_tuple(outputs));
945 } else {
946 self.values.push(mem::take(&mut outputs[0]));
947 }
948 }
949
950 Ok(())
951 }
952}
953
954fn snarkvm_literal_type_to_type(snarkvm_type: LiteralType) -> Type {
955 use Type::*;
956 match snarkvm_type {
957 LiteralType::Address => Address,
958 LiteralType::Boolean => Boolean,
959 LiteralType::Field => Field,
960 LiteralType::Group => Group,
961 LiteralType::I8 => Integer(IntegerType::I8),
962 LiteralType::I16 => Integer(IntegerType::I16),
963 LiteralType::I32 => Integer(IntegerType::I32),
964 LiteralType::I64 => Integer(IntegerType::I64),
965 LiteralType::I128 => Integer(IntegerType::I128),
966 LiteralType::U8 => Integer(IntegerType::U8),
967 LiteralType::U16 => Integer(IntegerType::U16),
968 LiteralType::U32 => Integer(IntegerType::U32),
969 LiteralType::U64 => Integer(IntegerType::U64),
970 LiteralType::U128 => Integer(IntegerType::U128),
971 LiteralType::Scalar => Scalar,
972 LiteralType::Signature => todo!(),
973 LiteralType::String => todo!(),
974 }
975}