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