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