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 }