/ interpreter / src / cursor_alpha.rs
cursor_alpha.rs
  1  // Copyright (C) 2019-2025 ADnet Contributors
  2  // This file is part of the ADL library.
  3  
  4  // The ADL library is free software: you can redistribute it and/or modify
  5  // it under the terms of the GNU General Public License as published by
  6  // the Free Software Foundation, either version 3 of the License, or
  7  // (at your option) any later version.
  8  
  9  // The ADL library is distributed in the hope that it will be useful,
 10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 12  // GNU General Public License for more details.
 13  
 14  // You should have received a copy of the GNU General Public License
 15  // along with the ADL library. If not, see <https://www.gnu.org/licenses/>.
 16  
 17  use super::*;
 18  
 19  use adl_ast::{
 20      BinaryOperation,
 21      IntegerType,
 22      Intrinsic,
 23      Location,
 24      Type,
 25      UnaryOperation,
 26      interpreter_value::{self, AsyncExecution, Value},
 27  };
 28  
 29  use 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  
 47  use std::mem;
 48  
 49  impl 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 .alpha code doesn't access undefined registers").clone()
 67              }
 68              Register::Access(index, accesses) => {
 69                  let value = registers.get(index).expect("valid .alpha code doesn't access undefined registers");
 70                  value.accesses(accesses.iter().cloned()).expect("Accesses should work.")
 71              }
 72          }
 73      }
 74  
 75      fn set_register(&mut self, reg: Register<TestnetV0>, value: Value) {
 76          let Some(Frame { element: Element::AleoExecution { registers, .. }, .. }) = self.frames.last_mut() else {
 77              panic!();
 78          };
 79  
 80          match reg {
 81              Register::Locator(index) => {
 82                  registers.insert(index, value);
 83              }
 84              Register::Access(_, _) => panic!("Can't happen"),
 85          }
 86      }
 87  
 88      fn instructions_len(&self) -> usize {
 89          let Some(Frame { element: Element::AleoExecution { context, .. }, .. }) = self.frames.last() else {
 90              panic!();
 91          };
 92          match &**context {
 93              AleoContext::Closure(closure) => closure.instructions().len(),
 94              AleoContext::Function(function) => function.instructions().len(),
 95              AleoContext::Finalize(finalize) => finalize.commands().len(),
 96          }
 97      }
 98  
 99      fn increment_instruction_index(&mut self) {
100          let Some(Frame { element: Element::AleoExecution { instruction_index, .. }, .. }) = self.frames.last_mut()
101          else {
102              panic!();
103          };
104          *instruction_index += 1;
105      }
106  
107      fn execution_complete(&self) -> bool {
108          let Some(Frame { element: Element::AleoExecution { instruction_index, .. }, .. }) = self.frames.last() else {
109              panic!();
110          };
111          *instruction_index >= self.instructions_len()
112      }
113  
114      fn next_instruction(&self) -> Option<&Instruction<TestnetV0>> {
115          let Some(Frame { element: Element::AleoExecution { instruction_index, context, .. }, .. }) = self.frames.last()
116          else {
117              panic!();
118          };
119          match &**context {
120              AleoContext::Closure(closure) => closure.instructions().get(*instruction_index),
121              AleoContext::Function(function) => function.instructions().get(*instruction_index),
122              AleoContext::Finalize(_) => None,
123          }
124      }
125  
126      fn next_command(&self) -> Option<&Command<TestnetV0>> {
127          let Some(Frame { element: Element::AleoExecution { instruction_index, context, .. }, .. }) = self.frames.last()
128          else {
129              panic!();
130          };
131          match &**context {
132              AleoContext::Closure(_) | AleoContext::Function(_) => None,
133              AleoContext::Finalize(finalize) => finalize.commands().get(*instruction_index),
134          }
135      }
136  
137      fn operand_value(&self, operand: &Operand<TestnetV0>) -> Value {
138          match operand {
139              Operand::Literal(literal) => literal.clone().into(),
140              Operand::Register(register) => self.get_register(register).clone(),
141              Operand::ProgramID(_) => todo!(),
142              Operand::Signer => self.signer.clone(),
143              Operand::Caller => {
144                  if let Some(function_context) = self.contexts.last() {
145                      function_context.caller.clone()
146                  } else {
147                      self.signer.clone()
148                  }
149              }
150              Operand::BlockHeight => self.block_height.into(),
151              Operand::BlockTimestamp => self.block_timestamp.into(),
152              Operand::NetworkID => todo!(),
153              Operand::Checksum(_) => todo!(),
154              Operand::Edition(_) => todo!(),
155              Operand::ProgramOwner(_) => todo!(),
156          }
157      }
158  
159      fn step_alpha_instruction(&mut self, instruction: Instruction<TestnetV0>) -> Result<()> {
160          // The Aleo VM code is a linear sequence of instructions, so we don't need to keep
161          // a stack of Elements (except for calls). Just run instructions in order.
162          use Instruction::*;
163  
164          let Some(Frame { step, .. }) = self.frames.last() else {
165              panic!("frame expected");
166          };
167  
168          macro_rules! unary {
169              ($svm_op: expr, $op: ident) => {{
170                  let operand = self.operand_value(&$svm_op.operands()[0]);
171                  let value =
172                      interpreter_value::evaluate_unary(Default::default(), UnaryOperation::$op, &operand, &None)?;
173                  self.increment_instruction_index();
174                  (value, $svm_op.destinations()[0].clone())
175              }};
176          }
177  
178          macro_rules! binary {
179              ($svm_op: expr, $op: ident) => {{
180                  let operand0 = self.operand_value(&$svm_op.operands()[0]);
181                  let operand1 = self.operand_value(&$svm_op.operands()[1]);
182                  let value = interpreter_value::evaluate_binary(
183                      Default::default(),
184                      BinaryOperation::$op,
185                      &operand0,
186                      &operand1,
187                      &None,
188                  )?;
189                  self.increment_instruction_index();
190                  (value, $svm_op.destinations()[0].clone())
191              }};
192          }
193  
194          macro_rules! commit_function {
195              ($commit: expr, $variant: expr) => {{
196                  let intrinsic = Intrinsic::Commit($variant, $commit.destination_type());
197                  let randomizer_value = self.operand_value(&$commit.operands()[0]);
198                  let operand_value = self.operand_value(&$commit.operands()[1]);
199                  self.values.push(randomizer_value);
200                  self.values.push(operand_value);
201                  let value = interpreter_value::evaluate_intrinsic(self, intrinsic, &[], Span::default())?;
202                  self.increment_instruction_index();
203                  (value.expect("Evaluation should work"), $commit.destinations()[0].clone())
204              }};
205          }
206  
207          macro_rules! hash_function {
208              ($hash: expr, $variant: expr) => {{
209                  // Note. The only supported output types of a `hash` function are literals or bit arrays.
210                  let intrinsic =
211                      Intrinsic::Hash($variant, Type::from_snarkvm::<TestnetV0>($hash.destination_type(), None));
212                  let operand_value = self.operand_value(&$hash.operands()[0]);
213                  self.values.push(operand_value);
214                  let value = interpreter_value::evaluate_intrinsic(self, intrinsic, &[], Span::default())?;
215                  self.increment_instruction_index();
216                  (value.expect("Evaluation should work"), $hash.destinations()[0].clone())
217              }};
218          }
219  
220          macro_rules! ecdsa_function {
221              ($ecdsa: expr, $variant: expr) => {{
222                  let intrinsic = Intrinsic::ECDSAVerify($variant);
223                  let signature = self.operand_value(&$ecdsa.operands()[0]);
224                  let public_key = self.operand_value(&$ecdsa.operands()[1]);
225                  let message = self.operand_value(&$ecdsa.operands()[2]);
226                  self.values.push(signature);
227                  self.values.push(public_key);
228                  self.values.push(message);
229                  let value = interpreter_value::evaluate_intrinsic(self, intrinsic, &[], Span::default())?;
230                  self.increment_instruction_index();
231                  (value.expect("Evaluation should work"), $ecdsa.destinations()[0].clone())
232              }};
233          }
234  
235          macro_rules! schnorr_function {
236              ($schnorr: expr, $variant: expr) => {{
237                  let intrinsic = Intrinsic::SignatureVerify;
238                  let signature = self.operand_value(&$schnorr.operands()[0]);
239                  let public_key = self.operand_value(&$schnorr.operands()[1]);
240                  let message = self.operand_value(&$schnorr.operands()[2]);
241                  self.values.push(signature);
242                  self.values.push(public_key);
243                  self.values.push(message);
244                  let value = interpreter_value::evaluate_intrinsic(self, intrinsic, &[], Span::default())?;
245                  self.increment_instruction_index();
246                  (value.expect("Evaluation should work"), $schnorr.destinations()[0].clone())
247              }};
248          }
249  
250          macro_rules! serialize_function {
251              ($serialize: expr, $variant: expr) => {{
252                  let intrinsic = Intrinsic::Serialize($variant);
253                  let operand_value = self.operand_value(&$serialize.operands()[0]);
254                  self.values.push(operand_value);
255                  let value = interpreter_value::evaluate_intrinsic(self, intrinsic, &[], Span::default())?;
256                  self.increment_instruction_index();
257                  (value.expect("Evaluation should work"), $serialize.destinations()[0].clone())
258              }};
259          }
260  
261          macro_rules! deserialize_function {
262              ($deserialize: expr, $variant: expr) => {{
263                  let intrinsic = Intrinsic::Deserialize(
264                      $variant,
265                      Type::from_snarkvm::<TestnetV0>($deserialize.destination_type(), None),
266                  );
267                  let operand_value = self.operand_value(&$deserialize.operands()[0]);
268                  self.values.push(operand_value);
269                  let value = interpreter_value::evaluate_intrinsic(self, intrinsic, &[], Span::default())?;
270                  self.increment_instruction_index();
271                  (value.expect("Evaluation should work"), $deserialize.destinations()[0].clone())
272              }};
273          }
274  
275          let (value, destination) = match instruction {
276              Abs(abs) => unary!(abs, Abs),
277              AbsWrapped(abs_wrapped) => unary!(abs_wrapped, AbsWrapped),
278              Add(add) => binary!(add, Add),
279              AddWrapped(add_wrapped) => binary!(add_wrapped, AddWrapped),
280              And(and) => binary!(and, BitwiseAnd),
281              AssertEq(assert_eq) => {
282                  let operand0 = self.operand_value(&assert_eq.operands()[0]);
283                  let operand1 = self.operand_value(&assert_eq.operands()[1]);
284                  if !operand0.eq(&operand1)? {
285                      halt_no_span!("assertion failure: {operand0} != {operand1}");
286                  }
287                  self.increment_instruction_index();
288                  return Ok(());
289              }
290              AssertNeq(assert_neq) => {
291                  let operand0 = self.operand_value(&assert_neq.operands()[0]);
292                  let operand1 = self.operand_value(&assert_neq.operands()[1]);
293                  if operand0.eq(&operand1)? {
294                      halt_no_span!("assertion failure: {operand0} != {operand1}");
295                  }
296                  self.increment_instruction_index();
297                  return Ok(());
298              }
299              Async(async_) if *step == 0 => {
300                  let program = self.contexts.current_program().expect("there should be a program");
301                  let name = snarkvm_identifier_to_symbol(async_.function_name());
302                  let arguments: Vec<Value> = async_.operands().iter().map(|op| self.operand_value(op)).collect();
303                  if self.really_async {
304                      self.increment_instruction_index();
305                      let async_ex =
306                          AsyncExecution::AsyncFunctionCall { function: Location::new(program, vec![name]), arguments };
307                      (vec![async_ex].into(), async_.destinations()[0].clone())
308                  } else {
309                      self.do_call(
310                          program,
311                          &[name],
312                          arguments.into_iter(),
313                          true, // finalize
314                          Span::default(),
315                      )?;
316                      self.increment_step();
317                      return Ok(());
318                  }
319              }
320              Call(call) if *step == 0 => {
321                  let (program, name) = match call.operator() {
322                      CallOperator::Locator(locator) => (
323                          snarkvm_identifier_to_symbol(locator.resource()),
324                          snarkvm_identifier_to_symbol(locator.program_id().name()),
325                      ),
326                      CallOperator::Resource(id) => (
327                          snarkvm_identifier_to_symbol(id),
328                          self.contexts.current_program().expect("there should be a program"),
329                      ),
330                  };
331                  let arguments: Vec<Value> = call.operands().iter().map(|op| self.operand_value(op)).collect();
332                  self.do_call(
333                      program,
334                      &[name],
335                      arguments.into_iter(),
336                      false, // finalize
337                      Span::default(),
338                  )?;
339                  self.increment_step();
340                  return Ok(());
341              }
342              Async(async_) if *step == 1 => {
343                  // We've done a call, and the result is on the value stack.
344                  self.values.pop();
345                  self.set_register(async_.destinations()[0].clone(), Vec::<AsyncExecution>::new().into());
346                  self.increment_instruction_index();
347                  return Ok(());
348              }
349              Call(call) if *step == 1 => {
350                  // We've done a call, and the result is on the value stack.
351                  let Some(result) = self.values.pop() else {
352                      panic!("should have a result");
353                  };
354                  if call.destinations().len() == 1 {
355                      self.set_register(call.destinations()[0].clone(), result);
356                  } else {
357                      for (i, dest) in call.destinations().iter().enumerate() {
358                          self.set_register(
359                              dest.clone(),
360                              result.tuple_index(i).expect("Function returning multiple values should create a tuple."),
361                          );
362                      }
363                  }
364                  self.increment_instruction_index();
365                  return Ok(());
366              }
367              Call(_) | Async(_) => unreachable!("all cases covered above"),
368              Cast(cast) => {
369                  let destination = cast.destinations()[0].clone();
370  
371                  self.increment_instruction_index();
372  
373                  match cast.cast_type() {
374                      CastType::GroupXCoordinate => {
375                          let value = self.operand_value(&cast.operands()[0]);
376                          let mut values = vec![value];
377                          let Some(result_value) = interpreter_value::evaluate_intrinsic(
378                              &mut values,
379                              Intrinsic::GroupToXCoordinate,
380                              &[],
381                              Default::default(),
382                          )?
383                          else {
384                              halt_no_span!("GroupToXCoordinate didn't produce a value.");
385                          };
386                          (result_value, destination)
387                      }
388                      CastType::GroupYCoordinate => {
389                          let value = self.operand_value(&cast.operands()[0]);
390                          let mut values = vec![value];
391                          let Some(result_value) = interpreter_value::evaluate_intrinsic(
392                              &mut values,
393                              Intrinsic::GroupToYCoordinate,
394                              &[],
395                              Default::default(),
396                          )?
397                          else {
398                              halt_no_span!("GroupToYCoordinate didn't produce a value.");
399                          };
400                          (result_value, destination)
401                      }
402                      CastType::Plaintext(PlaintextType::Array(_array)) => {
403                          let value = Value::make_array(cast.operands().iter().map(|op| self.operand_value(op)));
404                          (value, destination)
405                      }
406                      CastType::Plaintext(PlaintextType::Literal(literal_type)) => {
407                          let operand = self.operand_value(&cast.operands()[0]);
408                          let Some(value) = operand.cast(&snarkvm_literal_type_to_type(*literal_type)) else {
409                              halt_no_span!("cast failure");
410                          };
411                          (value, destination)
412                      }
413                      CastType::Plaintext(PlaintextType::Struct(struct_name)) => {
414                          let name = Symbol::intern(&struct_name.to_string());
415                          let struct_type = self.composites.get([name].as_slice()).expect("struct type should exist");
416                          let operands = cast.operands().iter().map(|op| self.operand_value(op));
417                          let value = Value::make_struct(
418                              struct_type.keys().cloned().zip(operands),
419                              self.current_program().unwrap(),
420                              vec![name],
421                          );
422                          (value, destination)
423                      }
424                      CastType::Record(record_name) => {
425                          let program = self.current_program().unwrap();
426                          let name = Symbol::intern(&record_name.to_string());
427                          let path = vec![name];
428                          let record_type = self.records.get(&(program, path.clone())).expect("record type should exist");
429                          let operands = cast.operands().iter().map(|op| self.operand_value(op));
430                          let value =
431                              Value::make_record(record_type.keys().cloned().zip(operands), program, path.clone());
432                          (value, destination)
433                      }
434                      CastType::ExternalRecord(locator) => {
435                          let program = Symbol::intern(&locator.program_id().name().to_string());
436                          let name = Symbol::intern(&locator.resource().to_string());
437                          let path = vec![name];
438                          let record_type = self.records.get(&(program, path.clone())).expect("record type should exist");
439                          let operands = cast.operands().iter().map(|op| self.operand_value(op));
440                          let value =
441                              Value::make_record(record_type.keys().cloned().zip(operands), program, path.clone());
442                          (value, destination)
443                      }
444                  }
445              }
446              CastLossy(cast_lossy) => {
447                  match cast_lossy.cast_type() {
448                      CastType::Plaintext(PlaintextType::Literal(literal_type)) => {
449                          // This is the only variant supported for lossy casts.
450                          let operand = self.operand_value(&cast_lossy.operands()[0]);
451                          let Some(value) = operand.cast_lossy(literal_type) else {
452                              halt_no_span!("Cast failure");
453                          };
454                          let destination = cast_lossy.destinations()[0].clone();
455                          (value, destination)
456                      }
457                      _ => tc_fail!(),
458                  }
459              }
460              CommitBHP256(commit) => commit_function!(commit, CommitVariant::CommitBHP256),
461              CommitBHP512(commit) => commit_function!(commit, CommitVariant::CommitBHP512),
462              CommitBHP768(commit) => commit_function!(commit, CommitVariant::CommitBHP768),
463              CommitBHP1024(commit) => commit_function!(commit, CommitVariant::CommitBHP1024),
464              CommitPED64(commit) => commit_function!(commit, CommitVariant::CommitPED64),
465              CommitPED128(commit) => commit_function!(commit, CommitVariant::CommitPED128),
466              Div(div) => binary!(div, Div),
467              DivWrapped(div_wrapped) => binary!(div_wrapped, DivWrapped),
468              Double(double) => unary!(double, Double),
469              GreaterThan(gt) => binary!(gt, Gt),
470              GreaterThanOrEqual(gte) => binary!(gte, Gte),
471              HashBHP256(hash) => hash_function!(hash, HashVariant::HashBHP256),
472              HashBHP512(hash) => hash_function!(hash, HashVariant::HashBHP512),
473              HashBHP768(hash) => hash_function!(hash, HashVariant::HashBHP768),
474              HashBHP1024(hash) => hash_function!(hash, HashVariant::HashBHP1024),
475              HashKeccak256(hash) => hash_function!(hash, HashVariant::HashKeccak256),
476              HashKeccak384(hash) => hash_function!(hash, HashVariant::HashKeccak384),
477              HashKeccak512(hash) => hash_function!(hash, HashVariant::HashKeccak512),
478              HashPED64(hash) => hash_function!(hash, HashVariant::HashPED64),
479              HashPED128(hash) => hash_function!(hash, HashVariant::HashPED128),
480              HashPSD2(hash) => hash_function!(hash, HashVariant::HashPSD2),
481              HashPSD4(hash) => hash_function!(hash, HashVariant::HashPSD4),
482              HashPSD8(hash) => hash_function!(hash, HashVariant::HashPSD8),
483              HashSha3_256(hash) => hash_function!(hash, HashVariant::HashSha3_256),
484              HashSha3_384(hash) => hash_function!(hash, HashVariant::HashSha3_384),
485              HashSha3_512(hash) => hash_function!(hash, HashVariant::HashSha3_512),
486              HashBHP256Raw(hash) => hash_function!(hash, HashVariant::HashBHP256Raw),
487              HashBHP512Raw(hash) => hash_function!(hash, HashVariant::HashBHP512Raw),
488              HashBHP768Raw(hash) => hash_function!(hash, HashVariant::HashBHP768Raw),
489              HashBHP1024Raw(hash) => hash_function!(hash, HashVariant::HashBHP1024Raw),
490              HashKeccak256Raw(hash) => hash_function!(hash, HashVariant::HashKeccak256Raw),
491              HashKeccak384Raw(hash) => hash_function!(hash, HashVariant::HashKeccak384Raw),
492              HashKeccak512Raw(hash) => hash_function!(hash, HashVariant::HashKeccak512Raw),
493              HashPED64Raw(hash) => hash_function!(hash, HashVariant::HashPED64Raw),
494              HashPED128Raw(hash) => hash_function!(hash, HashVariant::HashPED128Raw),
495              HashPSD2Raw(hash) => hash_function!(hash, HashVariant::HashPSD2Raw),
496              HashPSD4Raw(hash) => hash_function!(hash, HashVariant::HashPSD4Raw),
497              HashPSD8Raw(hash) => hash_function!(hash, HashVariant::HashPSD8Raw),
498              HashSha3_256Raw(hash) => hash_function!(hash, HashVariant::HashSha3_256Raw),
499              HashSha3_384Raw(hash) => hash_function!(hash, HashVariant::HashSha3_384Raw),
500              HashSha3_512Raw(hash) => hash_function!(hash, HashVariant::HashSha3_512Raw),
501              HashKeccak256Native(hash) => hash_function!(hash, HashVariant::HashKeccak256Native),
502              HashKeccak384Native(hash) => hash_function!(hash, HashVariant::HashKeccak384Native),
503              HashKeccak512Native(hash) => hash_function!(hash, HashVariant::HashKeccak512Native),
504              HashSha3_256Native(hash) => hash_function!(hash, HashVariant::HashSha3_256Native),
505              HashSha3_384Native(hash) => hash_function!(hash, HashVariant::HashSha3_384Native),
506              HashSha3_512Native(hash) => hash_function!(hash, HashVariant::HashSha3_512Native),
507              HashKeccak256NativeRaw(hash) => hash_function!(hash, HashVariant::HashKeccak256NativeRaw),
508              HashKeccak384NativeRaw(hash) => hash_function!(hash, HashVariant::HashKeccak384NativeRaw),
509              HashKeccak512NativeRaw(hash) => hash_function!(hash, HashVariant::HashKeccak512NativeRaw),
510              HashSha3_256NativeRaw(hash) => hash_function!(hash, HashVariant::HashSha3_256NativeRaw),
511              HashSha3_384NativeRaw(hash) => hash_function!(hash, HashVariant::HashSha3_384NativeRaw),
512              HashSha3_512NativeRaw(hash) => hash_function!(hash, HashVariant::HashSha3_512NativeRaw),
513              ECDSAVerifyDigest(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::Digest),
514              ECDSAVerifyDigestEth(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::DigestEth),
515              ECDSAVerifyKeccak256(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashKeccak256),
516              ECDSAVerifyKeccak256Raw(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashKeccak256Raw),
517              ECDSAVerifyKeccak256Eth(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashKeccak256Eth),
518              ECDSAVerifyKeccak384(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashKeccak384),
519              ECDSAVerifyKeccak384Raw(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashKeccak384Raw),
520              ECDSAVerifyKeccak384Eth(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashKeccak384Eth),
521              ECDSAVerifyKeccak512(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashKeccak512),
522              ECDSAVerifyKeccak512Raw(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashKeccak512Raw),
523              ECDSAVerifyKeccak512Eth(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashKeccak512Eth),
524              ECDSAVerifySha3_256(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashSha3_256),
525              ECDSAVerifySha3_256Raw(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashSha3_256Raw),
526              ECDSAVerifySha3_256Eth(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashSha3_256Eth),
527              ECDSAVerifySha3_384(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashSha3_384),
528              ECDSAVerifySha3_384Raw(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashSha3_384Raw),
529              ECDSAVerifySha3_384Eth(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashSha3_384Eth),
530              ECDSAVerifySha3_512(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashSha3_512),
531              ECDSAVerifySha3_512Raw(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashSha3_512Raw),
532              ECDSAVerifySha3_512Eth(ecdsa) => ecdsa_function!(ecdsa, ECDSAVerifyVariant::HashSha3_512Eth),
533              HashManyPSD2(_) | HashManyPSD4(_) | HashManyPSD8(_) => panic!("these functions don't exist yet"),
534              Inv(inv) => unary!(inv, Inverse),
535              IsEq(eq) => binary!(eq, Eq),
536              IsNeq(neq) => binary!(neq, Neq),
537              LessThan(lt) => binary!(lt, Lt),
538              LessThanOrEqual(lte) => binary!(lte, Lte),
539              Modulo(modulo) => binary!(modulo, Mod),
540              Mul(mul) => binary!(mul, Mul),
541              MulWrapped(mul_wrapped) => binary!(mul_wrapped, MulWrapped),
542              Nand(nand) => binary!(nand, Nand),
543              Neg(neg) => unary!(neg, Negate),
544              Nor(nor) => binary!(nor, Nor),
545              Not(not) => unary!(not, Not),
546              Or(or) => binary!(or, BitwiseOr),
547              Pow(pow) => binary!(pow, Pow),
548              PowWrapped(pow_wrapped) => binary!(pow_wrapped, PowWrapped),
549              Rem(rem) => binary!(rem, Rem),
550              RemWrapped(rem_wrapped) => binary!(rem_wrapped, RemWrapped),
551              Shl(shl) => binary!(shl, Shl),
552              ShlWrapped(shl_wrapped) => binary!(shl_wrapped, ShlWrapped),
553              Shr(shr) => binary!(shr, Shr),
554              ShrWrapped(shr_wrapped) => binary!(shr_wrapped, ShrWrapped),
555              SignVerify(schnorr) => schnorr_function!(schnorr, false),
556              Square(square) => unary!(square, Square),
557              SquareRoot(sqrt) => unary!(sqrt, SquareRoot),
558              Sub(sub) => binary!(sub, Sub),
559              SubWrapped(sub_wrapped) => binary!(sub_wrapped, SubWrapped),
560              Ternary(ternary) => {
561                  let condition = self.operand_value(&ternary.operands()[0]);
562                  let result = match condition.try_into() {
563                      Ok(true) => &ternary.operands()[1],
564                      Ok(false) => &ternary.operands()[2],
565                      _ => tc_fail!(),
566                  };
567                  self.increment_instruction_index();
568                  (self.operand_value(result), ternary.destinations()[0].clone())
569              }
570              Xor(xor) => binary!(xor, Xor),
571              SerializeBits(serialize_bits) => serialize_function!(serialize_bits, SerializeVariant::ToBits),
572              SerializeBitsRaw(serialize_bits_raw) => {
573                  serialize_function!(serialize_bits_raw, SerializeVariant::ToBitsRaw)
574              }
575              DeserializeBits(deserialize_bits) => deserialize_function!(deserialize_bits, DeserializeVariant::FromBits),
576              DeserializeBitsRaw(deserialize_bits_raw) => {
577                  deserialize_function!(deserialize_bits_raw, DeserializeVariant::FromBitsRaw)
578              }
579          };
580  
581          self.set_register(destination, value);
582  
583          Ok(())
584      }
585  
586      fn outputs(&self) -> Vec<Value> {
587          let Some(Frame { element, .. }) = self.frames.last() else {
588              panic!("frame expected");
589          };
590          let Element::AleoExecution { context, .. } = element else {
591              panic!("ALPHA execution expected");
592          };
593  
594          let mut result = match &**context {
595              AleoContext::Closure(closure) => {
596                  closure.outputs().iter().map(|output| self.operand_value(output.operand())).collect()
597              }
598              AleoContext::Function(function) => {
599                  function.outputs().iter().map(|output| self.operand_value(output.operand())).collect()
600              }
601              AleoContext::Finalize(_finalize) => Vec::new(),
602          };
603  
604          if result.is_empty() {
605              result.push(Value::make_unit());
606          }
607          result
608      }
609  
610      fn step_alpha_command(&mut self, command: Command<TestnetV0>) -> Result<()> {
611          use Command::*;
612  
613          let (value, destination) = match command {
614              Instruction(instruction) => {
615                  self.step_alpha_instruction(instruction)?;
616                  return Ok(());
617              }
618              Await(await_) => {
619                  let value = self.get_register(await_.register());
620                  let Some(asyncs) = value.as_future() else {
621                      halt_no_span!("attempted to await a non-future");
622                  };
623                  self.contexts.add_future(asyncs.to_vec());
624                  self.increment_instruction_index();
625                  return Ok(());
626              }
627              Contains(contains) => {
628                  // Value has interior mutability, since SnarkVM's value does, but this is okay - it's just the OnceCell which houses its bits.
629                  #[allow(clippy::mutable_key_type)]
630                  let mapping = self.mapping_by_call_operator(contains.mapping()).expect("mapping should be present");
631                  let key = self.operand_value(contains.key());
632                  let result = mapping.contains_key(&key).into();
633                  self.increment_instruction_index();
634                  (result, contains.destination().clone())
635              }
636              Get(get) => {
637                  let key = self.operand_value(get.key());
638                  let value = self.mapping_by_call_operator(get.mapping()).and_then(|mapping| mapping.get(&key)).cloned();
639                  self.increment_instruction_index();
640  
641                  match value {
642                      Some(v) => (v, get.destination().clone()),
643                      None => halt_no_span!("map access failure: {key}"),
644                  }
645              }
646              GetOrUse(get_or_use) => {
647                  let key = self.operand_value(get_or_use.key());
648                  let value =
649                      self.mapping_by_call_operator(get_or_use.mapping()).and_then(|mapping| mapping.get(&key)).cloned();
650  
651                  let use_value = value.unwrap_or_else(|| self.operand_value(get_or_use.default()));
652                  self.increment_instruction_index();
653  
654                  (use_value, get_or_use.destination().clone())
655              }
656              Remove(remove) => {
657                  let key = self.operand_value(remove.key());
658                  let mapping_name = snarkvm_identifier_to_symbol(remove.mapping_name());
659                  let maybe_mapping = self.lookup_mapping_mut(None, mapping_name);
660                  match maybe_mapping {
661                      None => halt_no_span!("no such mapping {mapping_name}"),
662                      Some(mapping) => {
663                          mapping.remove(&key);
664                      }
665                  }
666                  self.increment_instruction_index();
667                  return Ok(());
668              }
669              Set(set) => {
670                  let key = self.operand_value(set.key());
671                  let value = self.operand_value(set.value());
672                  let mapping_name = snarkvm_identifier_to_symbol(set.mapping_name());
673                  let maybe_mapping = self.lookup_mapping_mut(None, mapping_name);
674                  match maybe_mapping {
675                      None => halt_no_span!("no such mapping {mapping_name}"),
676                      Some(mapping) => {
677                          mapping.insert(key, value);
678                      }
679                  }
680                  self.increment_instruction_index();
681                  return Ok(());
682              }
683              RandChaCha(rand) => {
684                  // TODO - this is not using the other operands which are supposed to seed the RNG.
685                  use Intrinsic::*;
686                  let function = ChaChaRand(rand.destination_type());
687                  let value = interpreter_value::evaluate_intrinsic(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_alpha(&mut self) -> Result<()> {
743          if let Some(command) = self.next_command().cloned() {
744              self.step_alpha_command(command)?;
745          } else if let Some(instruction) = self.next_instruction().cloned() {
746              self.step_alpha_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  
764  fn 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  }