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