1use crate::{Opcode, Operand, RegistersCircuit, RegistersTrait, StackTrait};
17use console::{
18 algorithms::{ECDSASignature, Keccak256, Keccak384, Keccak512, Sha3_256, Sha3_384, Sha3_512},
19 network::prelude::*,
20 program::{Boolean, Identifier, Literal, LiteralType, Locator, PlaintextType, Register, RegisterType, Value},
21};
22use snarkvm_utilities::bytes_from_bits_le;
23
24pub type ECDSAVerifyDigest<N> = ECDSAVerify<N, { ECDSAVerifyVariant::Digest as u8 }>;
26pub type ECDSAVerifyDigestEth<N> = ECDSAVerify<N, { ECDSAVerifyVariant::DigestEth as u8 }>;
28
29pub type ECDSAVerifyKeccak256<N> = ECDSAVerify<N, { ECDSAVerifyVariant::HashKeccak256 as u8 }>;
31pub type ECDSAVerifyKeccak256Raw<N> = ECDSAVerify<N, { ECDSAVerifyVariant::HashKeccak256Raw as u8 }>;
33pub type ECDSAVerifyKeccak256Eth<N> = ECDSAVerify<N, { ECDSAVerifyVariant::HashKeccak256Eth as u8 }>;
35pub type ECDSAVerifyKeccak384<N> = ECDSAVerify<N, { ECDSAVerifyVariant::HashKeccak384 as u8 }>;
37pub type ECDSAVerifyKeccak384Raw<N> = ECDSAVerify<N, { ECDSAVerifyVariant::HashKeccak384Raw as u8 }>;
39pub type ECDSAVerifyKeccak384Eth<N> = ECDSAVerify<N, { ECDSAVerifyVariant::HashKeccak384Eth as u8 }>;
41pub type ECDSAVerifyKeccak512<N> = ECDSAVerify<N, { ECDSAVerifyVariant::HashKeccak512 as u8 }>;
43pub type ECDSAVerifyKeccak512Raw<N> = ECDSAVerify<N, { ECDSAVerifyVariant::HashKeccak512Raw as u8 }>;
45pub type ECDSAVerifyKeccak512Eth<N> = ECDSAVerify<N, { ECDSAVerifyVariant::HashKeccak512Eth as u8 }>;
47
48pub type ECDSAVerifySha3_256<N> = ECDSAVerify<N, { ECDSAVerifyVariant::HashSha3_256 as u8 }>;
50pub type ECDSAVerifySha3_256Raw<N> = ECDSAVerify<N, { ECDSAVerifyVariant::HashSha3_256Raw as u8 }>;
52pub type ECDSAVerifySha3_256Eth<N> = ECDSAVerify<N, { ECDSAVerifyVariant::HashSha3_256Eth as u8 }>;
54pub type ECDSAVerifySha3_384<N> = ECDSAVerify<N, { ECDSAVerifyVariant::HashSha3_384 as u8 }>;
56pub type ECDSAVerifySha3_384Raw<N> = ECDSAVerify<N, { ECDSAVerifyVariant::HashSha3_384Raw as u8 }>;
58pub type ECDSAVerifySha3_384Eth<N> = ECDSAVerify<N, { ECDSAVerifyVariant::HashSha3_384Eth as u8 }>;
60pub type ECDSAVerifySha3_512<N> = ECDSAVerify<N, { ECDSAVerifyVariant::HashSha3_512 as u8 }>;
62pub type ECDSAVerifySha3_512Raw<N> = ECDSAVerify<N, { ECDSAVerifyVariant::HashSha3_512Raw as u8 }>;
64pub type ECDSAVerifySha3_512Eth<N> = ECDSAVerify<N, { ECDSAVerifyVariant::HashSha3_512Eth as u8 }>;
66
67#[derive(Debug, Clone, Eq, PartialEq)]
69pub enum ECDSAVerifyVariant {
70 Digest,
71 DigestEth,
72 HashKeccak256,
73 HashKeccak256Raw,
74 HashKeccak256Eth,
75 HashKeccak384,
76 HashKeccak384Raw,
77 HashKeccak384Eth,
78 HashKeccak512,
79 HashKeccak512Raw,
80 HashKeccak512Eth,
81 HashSha3_256,
82 HashSha3_256Raw,
83 HashSha3_256Eth,
84 HashSha3_384,
85 HashSha3_384Raw,
86 HashSha3_384Eth,
87 HashSha3_512,
88 HashSha3_512Raw,
89 HashSha3_512Eth,
90}
91
92impl ECDSAVerifyVariant {
93 pub const fn new(variant: u8) -> Self {
95 match variant {
96 0 => Self::Digest,
97 1 => Self::DigestEth,
98 2 => Self::HashKeccak256,
99 3 => Self::HashKeccak256Raw,
100 4 => Self::HashKeccak256Eth,
101 5 => Self::HashKeccak384,
102 6 => Self::HashKeccak384Raw,
103 7 => Self::HashKeccak384Eth,
104 8 => Self::HashKeccak512,
105 9 => Self::HashKeccak512Raw,
106 10 => Self::HashKeccak512Eth,
107 11 => Self::HashSha3_256,
108 12 => Self::HashSha3_256Raw,
109 13 => Self::HashSha3_256Eth,
110 14 => Self::HashSha3_384,
111 15 => Self::HashSha3_384Raw,
112 16 => Self::HashSha3_384Eth,
113 17 => Self::HashSha3_512,
114 18 => Self::HashSha3_512Raw,
115 19 => Self::HashSha3_512Eth,
116 _ => panic!("Invalid 'ecdsa.verify' instruction opcode"),
117 }
118 }
119
120 pub const fn opcode(&self) -> &'static str {
122 match self {
123 Self::Digest => "ecdsa.verify.digest",
124 Self::DigestEth => "ecdsa.verify.digest.eth",
125 Self::HashKeccak256 => "ecdsa.verify.keccak256",
126 Self::HashKeccak256Raw => "ecdsa.verify.keccak256.raw",
127 Self::HashKeccak256Eth => "ecdsa.verify.keccak256.eth",
128 Self::HashKeccak384 => "ecdsa.verify.keccak384",
129 Self::HashKeccak384Raw => "ecdsa.verify.keccak384.raw",
130 Self::HashKeccak384Eth => "ecdsa.verify.keccak384.eth",
131 Self::HashKeccak512 => "ecdsa.verify.keccak512",
132 Self::HashKeccak512Raw => "ecdsa.verify.keccak512.raw",
133 Self::HashKeccak512Eth => "ecdsa.verify.keccak512.eth",
134 Self::HashSha3_256 => "ecdsa.verify.sha3_256",
135 Self::HashSha3_256Raw => "ecdsa.verify.sha3_256.raw",
136 Self::HashSha3_256Eth => "ecdsa.verify.sha3_256.eth",
137 Self::HashSha3_384 => "ecdsa.verify.sha3_384",
138 Self::HashSha3_384Raw => "ecdsa.verify.sha3_384.raw",
139 Self::HashSha3_384Eth => "ecdsa.verify.sha3_384.eth",
140 Self::HashSha3_512 => "ecdsa.verify.sha3_512",
141 Self::HashSha3_512Raw => "ecdsa.verify.sha3_512.raw",
142 Self::HashSha3_512Eth => "ecdsa.verify.sha3_512.eth",
143 }
144 }
145
146 pub const fn requires_byte_alignment(&self) -> bool {
148 match self {
149 Self::Digest => true,
150 Self::DigestEth => true,
151 Self::HashKeccak256 => false,
152 Self::HashKeccak256Raw => true,
153 Self::HashKeccak256Eth => true,
154 Self::HashKeccak384 => false,
155 Self::HashKeccak384Raw => true,
156 Self::HashKeccak384Eth => true,
157 Self::HashKeccak512 => false,
158 Self::HashKeccak512Raw => true,
159 Self::HashKeccak512Eth => true,
160 Self::HashSha3_256 => false,
161 Self::HashSha3_256Raw => true,
162 Self::HashSha3_256Eth => true,
163 Self::HashSha3_384 => false,
164 Self::HashSha3_384Raw => true,
165 Self::HashSha3_384Eth => true,
166 Self::HashSha3_512 => false,
167 Self::HashSha3_512Raw => true,
168 Self::HashSha3_512Eth => true,
169 }
170 }
171
172 pub const fn is_raw(&self) -> bool {
174 match self {
175 Self::Digest => true,
176 Self::DigestEth => true,
177 Self::HashKeccak256 => false,
178 Self::HashKeccak256Raw => true,
179 Self::HashKeccak256Eth => true,
180 Self::HashKeccak384 => false,
181 Self::HashKeccak384Raw => true,
182 Self::HashKeccak384Eth => true,
183 Self::HashKeccak512 => false,
184 Self::HashKeccak512Raw => true,
185 Self::HashKeccak512Eth => true,
186 Self::HashSha3_256 => false,
187 Self::HashSha3_256Raw => true,
188 Self::HashSha3_256Eth => true,
189 Self::HashSha3_384 => false,
190 Self::HashSha3_384Raw => true,
191 Self::HashSha3_384Eth => true,
192 Self::HashSha3_512 => false,
193 Self::HashSha3_512Raw => true,
194 Self::HashSha3_512Eth => true,
195 }
196 }
197}
198
199#[derive(Clone, PartialEq, Eq, Hash)]
201pub struct ECDSAVerify<N: Network, const VARIANT: u8> {
202 operands: Vec<Operand<N>>,
204 destination: Register<N>,
206}
207
208impl<N: Network, const VARIANT: u8> ECDSAVerify<N, VARIANT> {
209 #[inline]
211 pub fn new(operands: Vec<Operand<N>>, destination: Register<N>) -> Result<Self> {
212 ensure!(operands.len() == 3, "Instruction '{}' must have three operands", Self::opcode());
214 Ok(Self { operands, destination })
216 }
217
218 #[inline]
220 pub const fn opcode() -> Opcode {
221 Opcode::ECDSA(ECDSAVerifyVariant::new(VARIANT).opcode())
222 }
223
224 #[inline]
226 pub fn operands(&self) -> &[Operand<N>] {
227 debug_assert!(self.operands.len() == 3, "Instruction '{}' must have three operands", Self::opcode());
229 &self.operands
231 }
232
233 #[inline]
235 pub fn destinations(&self) -> Vec<Register<N>> {
236 vec![self.destination.clone()]
237 }
238}
239
240#[rustfmt::skip]
242macro_rules! do_ecdsa_verification {
243 ($variant: expr, $signature: expr, $pub_key: expr, $message: expr) => {{
244 let bits = || $message.to_bits_le();
245 let bits_raw = || $message.to_bits_raw_le();
246
247 let pub_key = || ECDSASignature::verifying_key_from_bytes(&bytes_from_bits_le(&$pub_key.to_bits_raw_le()));
248 let ethereum_address = || {
249 bytes_from_bits_le(&$pub_key.to_bits_raw_le())
250 .try_into()
251 .map_err(|_| anyhow!("Failed to parse Ethereum address"))
252 };
253
254 let signature_bytes = bytes_from_bits_le(&$signature.to_bits_raw_le());
255 let ecdsa_signature = ECDSASignature::from_bytes_le(&signature_bytes)?;
256
257 let output = match $variant {
258 ECDSAVerifyVariant::Digest => ecdsa_signature.verify_with_digest(&pub_key()?, &bits_raw()),
259 ECDSAVerifyVariant::DigestEth => ecdsa_signature.verify_ethereum_with_digest(ðereum_address()?, &bits_raw()),
260 ECDSAVerifyVariant::HashKeccak256 => ecdsa_signature.verify(&pub_key()?, &Keccak256::default(), &bits()),
261 ECDSAVerifyVariant::HashKeccak256Raw => ecdsa_signature.verify(&pub_key()?, &Keccak256::default(), &bits_raw()),
262 ECDSAVerifyVariant::HashKeccak256Eth => ecdsa_signature.verify_ethereum(ðereum_address()?, &Keccak256::default(), &bits_raw()),
263 ECDSAVerifyVariant::HashKeccak384 => ecdsa_signature.verify(&pub_key()?, &Keccak384::default(), &bits()),
264 ECDSAVerifyVariant::HashKeccak384Raw => ecdsa_signature.verify(&pub_key()?, &Keccak384::default(), &bits_raw()),
265 ECDSAVerifyVariant::HashKeccak384Eth => ecdsa_signature.verify_ethereum(ðereum_address()?, &Keccak384::default(), &bits_raw()),
266 ECDSAVerifyVariant::HashKeccak512 => ecdsa_signature.verify(&pub_key()?, &Keccak512::default(), &bits()),
267 ECDSAVerifyVariant::HashKeccak512Raw => ecdsa_signature.verify(&pub_key()?, &Keccak512::default(), &bits_raw()),
268 ECDSAVerifyVariant::HashKeccak512Eth => ecdsa_signature.verify_ethereum(ðereum_address()?, &Keccak512::default(), &bits_raw()),
269 ECDSAVerifyVariant::HashSha3_256 => ecdsa_signature.verify(&pub_key()?, &Sha3_256::default(), &bits()),
270 ECDSAVerifyVariant::HashSha3_256Raw => ecdsa_signature.verify(&pub_key()?, &Sha3_256::default(), &bits_raw()),
271 ECDSAVerifyVariant::HashSha3_256Eth => ecdsa_signature.verify_ethereum(ðereum_address()?, &Sha3_256::default(), &bits_raw()),
272 ECDSAVerifyVariant::HashSha3_384 => ecdsa_signature.verify(&pub_key()?, &Sha3_384::default(), &bits()),
273 ECDSAVerifyVariant::HashSha3_384Raw => ecdsa_signature.verify(&pub_key()?, &Sha3_384::default(), &bits_raw()),
274 ECDSAVerifyVariant::HashSha3_384Eth => ecdsa_signature.verify_ethereum(ðereum_address()?, &Sha3_384::default(), &bits_raw()),
275 ECDSAVerifyVariant::HashSha3_512 => ecdsa_signature.verify(&pub_key()?, &Sha3_512::default(), &bits()),
276 ECDSAVerifyVariant::HashSha3_512Raw => ecdsa_signature.verify(&pub_key()?, &Sha3_512::default(), &bits_raw()),
277 ECDSAVerifyVariant::HashSha3_512Eth => ecdsa_signature.verify_ethereum(ðereum_address()?, &Sha3_512::default(), &bits_raw()),
278 };
279
280 output.is_ok()
281 }};
282}
283
284pub fn evaluate_ecdsa_verification<N: Network>(
289 variant: ECDSAVerifyVariant,
290 signature: &Value<N>,
291 public_key: &Value<N>,
292 message: &Value<N>,
293) -> Result<bool> {
294 evaluate_ecdsa_verification_internal(variant, signature, public_key, message)
295}
296
297fn evaluate_ecdsa_verification_internal<N: Network>(
298 variant: ECDSAVerifyVariant,
299 signature: &Value<N>,
300 public_key: &Value<N>,
301 message: &Value<N>,
302) -> Result<bool> {
303 Ok(do_ecdsa_verification!(variant, signature, public_key, message))
304}
305
306impl<N: Network, const VARIANT: u8> ECDSAVerify<N, VARIANT> {
307 #[inline]
309 pub fn evaluate(&self, _stack: &impl StackTrait<N>, _registers: &mut impl RegistersTrait<N>) -> Result<()> {
310 bail!("Instruction '{}' is currently only supported in finalize", Self::opcode());
311 }
312
313 #[inline]
315 pub fn execute<A: circuit::Aleo<Network = N>>(
316 &self,
317 _stack: &impl StackTrait<N>,
318 _registers: &mut impl RegistersCircuit<N, A>,
319 ) -> Result<()> {
320 bail!("Instruction '{}' is currently only supported in finalize", Self::opcode());
321 }
322
323 #[inline]
325 pub fn finalize(&self, stack: &impl StackTrait<N>, registers: &mut impl RegistersTrait<N>) -> Result<()> {
326 if self.operands.len() != 3 {
328 bail!("Instruction '{}' expects 3 operands, found {} operands", Self::opcode(), self.operands.len())
329 }
330
331 let signature = registers.load(stack, &self.operands[0])?;
334 let public_key = registers.load(stack, &self.operands[1])?;
335 let message = registers.load(stack, &self.operands[2])?;
336
337 let output =
339 evaluate_ecdsa_verification_internal(ECDSAVerifyVariant::new(VARIANT), &signature, &public_key, &message)?;
340 let output = Literal::Boolean(Boolean::new(output));
341
342 registers.store_literal(stack, &self.destination, output)
344 }
345
346 #[inline]
348 pub fn output_types(
349 &self,
350 stack: &impl StackTrait<N>,
351 input_types: &[RegisterType<N>],
352 ) -> Result<Vec<RegisterType<N>>> {
353 if input_types.len() != 3 {
355 bail!("Instruction '{}' expects 3 inputs, found {} inputs", Self::opcode(), input_types.len())
356 }
357
358 match &input_types[0] {
360 RegisterType::Plaintext(PlaintextType::Array(array_type))
361 if array_type.base_element_type() == &PlaintextType::Literal(LiteralType::U8)
362 && **array_type.length() as usize == ECDSASignature::SIGNATURE_SIZE_IN_BYTES =>
363 {
364 }
366 _ => bail!(
367 "Instruction '{}' expects the first input to be a {}-byte array. Found input of type '{}'",
368 Self::opcode(),
369 ECDSASignature::SIGNATURE_SIZE_IN_BYTES,
370 input_types[0]
371 ),
372 }
373
374 let variant = ECDSAVerifyVariant::new(VARIANT);
376
377 let expected_length = match variant {
379 ECDSAVerifyVariant::Digest
381 | ECDSAVerifyVariant::HashKeccak256
382 | ECDSAVerifyVariant::HashKeccak256Raw
383 | ECDSAVerifyVariant::HashKeccak384
384 | ECDSAVerifyVariant::HashKeccak384Raw
385 | ECDSAVerifyVariant::HashKeccak512
386 | ECDSAVerifyVariant::HashKeccak512Raw
387 | ECDSAVerifyVariant::HashSha3_256
388 | ECDSAVerifyVariant::HashSha3_256Raw
389 | ECDSAVerifyVariant::HashSha3_384
390 | ECDSAVerifyVariant::HashSha3_384Raw
391 | ECDSAVerifyVariant::HashSha3_512
392 | ECDSAVerifyVariant::HashSha3_512Raw => ECDSASignature::VERIFYING_KEY_SIZE_IN_BYTES,
393 ECDSAVerifyVariant::DigestEth
395 | ECDSAVerifyVariant::HashKeccak256Eth
396 | ECDSAVerifyVariant::HashKeccak384Eth
397 | ECDSAVerifyVariant::HashKeccak512Eth
398 | ECDSAVerifyVariant::HashSha3_256Eth
399 | ECDSAVerifyVariant::HashSha3_384Eth
400 | ECDSAVerifyVariant::HashSha3_512Eth => ECDSASignature::ETHEREUM_ADDRESS_SIZE_IN_BYTES,
401 };
402
403 match &input_types[1] {
405 RegisterType::Plaintext(PlaintextType::Array(array_type))
406 if array_type.base_element_type() == &PlaintextType::Literal(LiteralType::U8)
407 && expected_length == **array_type.length() as usize => {}
408
409 invalid_input_type => bail!(
410 "Instruction '{}' expects the second input to be a {}-byte array. Found '{}'",
411 Self::opcode(),
412 expected_length,
413 invalid_input_type
414 ),
415 }
416
417 if matches!(variant, ECDSAVerifyVariant::Digest | ECDSAVerifyVariant::DigestEth) {
419 let expected_message_length = ECDSASignature::PREHASH_SIZE_IN_BYTES;
421
422 match &input_types[2] {
423 RegisterType::Plaintext(PlaintextType::Array(array_type))
424 if array_type.base_element_type() == &PlaintextType::Literal(LiteralType::U8)
425 && expected_message_length == **array_type.length() as usize => {}
426
427 invalid_input_type => bail!(
428 "Instruction '{}' expects the third input to be a {}-byte array. Found '{}'",
429 Self::opcode(),
430 expected_message_length,
431 invalid_input_type
432 ),
433 }
434 }
435 else if variant.requires_byte_alignment() {
437 let get_struct = |identifier: &Identifier<N>| stack.program().get_struct(identifier).cloned();
439
440 let get_record = |identifier: &Identifier<N>| stack.program().get_record(identifier).cloned();
442
443 let get_external_record = |locator: &Locator<N>| {
445 stack.get_external_stack(locator.program_id())?.program().get_record(locator.resource()).cloned()
446 };
447
448 let get_future = |locator: &Locator<N>| {
450 Ok(match stack.program_id() == locator.program_id() {
451 true => stack
452 .program()
453 .get_function_ref(locator.resource())?
454 .finalize_logic()
455 .ok_or_else(|| anyhow!("'{locator}' does not have a finalize scope"))?
456 .input_types(),
457 false => stack
458 .get_external_stack(locator.program_id())?
459 .program()
460 .get_function_ref(locator.resource())?
461 .finalize_logic()
462 .ok_or_else(|| anyhow!("Failed to find function '{locator}'"))?
463 .input_types(),
464 })
465 };
466
467 let size_in_bits = match variant.is_raw() {
469 false => input_types[2].size_in_bits(&get_struct, &get_record, &get_external_record, &get_future)?,
470 true => input_types[2].size_in_bits_raw(&get_struct, &get_record, &get_external_record, &get_future)?,
471 };
472 ensure!(
474 size_in_bits % 8 == 0,
475 "Expected a multiple of 8 bits for '{}', found '{size_in_bits}'",
476 variant.opcode()
477 );
478 }
479
480 Ok(vec![RegisterType::Plaintext(PlaintextType::Literal(LiteralType::Boolean))])
481 }
482}
483
484impl<N: Network, const VARIANT: u8> Parser for ECDSAVerify<N, VARIANT> {
485 #[inline]
487 fn parse(string: &str) -> ParserResult<Self> {
488 let (string, _) = tag(*Self::opcode())(string)?;
490 let (string, _) = Sanitizer::parse_whitespaces(string)?;
492 let (string, first) = Operand::parse(string)?;
494 let (string, _) = Sanitizer::parse_whitespaces(string)?;
496 let (string, second) = Operand::parse(string)?;
498 let (string, _) = Sanitizer::parse_whitespaces(string)?;
500 let (string, third) = Operand::parse(string)?;
502 let (string, _) = Sanitizer::parse_whitespaces(string)?;
504 let (string, _) = tag("into")(string)?;
506 let (string, _) = Sanitizer::parse_whitespaces(string)?;
508 let (string, destination) = Register::parse(string)?;
510
511 Ok((string, Self { operands: vec![first, second, third], destination }))
512 }
513}
514
515impl<N: Network, const VARIANT: u8> FromStr for ECDSAVerify<N, VARIANT> {
516 type Err = Error;
517
518 #[inline]
520 fn from_str(string: &str) -> Result<Self> {
521 match Self::parse(string) {
522 Ok((remainder, object)) => {
523 ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\"");
525 Ok(object)
527 }
528 Err(error) => bail!("Failed to parse string. {error}"),
529 }
530 }
531}
532
533impl<N: Network, const VARIANT: u8> Debug for ECDSAVerify<N, VARIANT> {
534 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
536 Display::fmt(self, f)
537 }
538}
539
540impl<N: Network, const VARIANT: u8> Display for ECDSAVerify<N, VARIANT> {
541 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
543 if self.operands.len() != 3 {
545 return Err(fmt::Error);
546 }
547 write!(f, "{} ", Self::opcode())?;
549 self.operands.iter().try_for_each(|operand| write!(f, "{operand} "))?;
550 write!(f, "into {}", self.destination)
551 }
552}
553
554impl<N: Network, const VARIANT: u8> FromBytes for ECDSAVerify<N, VARIANT> {
555 fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
557 let mut operands = Vec::with_capacity(3);
559 for _ in 0..3 {
561 operands.push(Operand::read_le(&mut reader)?);
562 }
563 let destination = Register::read_le(&mut reader)?;
565
566 Ok(Self { operands, destination })
568 }
569}
570
571impl<N: Network, const VARIANT: u8> ToBytes for ECDSAVerify<N, VARIANT> {
572 fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
574 if self.operands.len() != 3 {
576 return Err(error(format!("The number of operands must be 3, found {}", self.operands.len())));
577 }
578 self.operands.iter().try_for_each(|operand| operand.write_le(&mut writer))?;
580 self.destination.write_le(&mut writer)
582 }
583}
584
585#[cfg(test)]
586mod tests {
587 use super::*;
588 use console::network::MainnetV0;
589
590 type CurrentNetwork = MainnetV0;
591
592 #[test]
593 fn test_parse() {
594 let (string, is) = ECDSAVerifyDigest::<CurrentNetwork>::parse("ecdsa.verify.digest r0 r1 r2 into r3").unwrap();
595 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'");
596 assert_eq!(is.operands.len(), 3, "The number of operands is incorrect");
597 assert_eq!(is.operands[0], Operand::Register(Register::Locator(0)), "The first operand is incorrect");
598 assert_eq!(is.operands[1], Operand::Register(Register::Locator(1)), "The second operand is incorrect");
599 assert_eq!(is.operands[2], Operand::Register(Register::Locator(2)), "The third operand is incorrect");
600 assert_eq!(is.destination, Register::Locator(3), "The destination register is incorrect");
601
602 let (string, is) =
603 ECDSAVerifyDigestEth::<CurrentNetwork>::parse("ecdsa.verify.digest.eth r0 r1 r2 into r3").unwrap();
604 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'");
605 assert_eq!(is.operands.len(), 3, "The number of operands is incorrect");
606 assert_eq!(is.operands[0], Operand::Register(Register::Locator(0)), "The first operand is incorrect");
607 assert_eq!(is.operands[1], Operand::Register(Register::Locator(1)), "The second operand is incorrect");
608 assert_eq!(is.operands[2], Operand::Register(Register::Locator(2)), "The third operand is incorrect");
609 assert_eq!(is.destination, Register::Locator(3), "The destination register is incorrect");
610
611 let (string, is) =
612 ECDSAVerifyKeccak256::<CurrentNetwork>::parse("ecdsa.verify.keccak256 r0 r1 r2 into r3").unwrap();
613 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'");
614 assert_eq!(is.operands.len(), 3, "The number of operands is incorrect");
615 assert_eq!(is.operands[0], Operand::Register(Register::Locator(0)), "The first operand is incorrect");
616 assert_eq!(is.operands[1], Operand::Register(Register::Locator(1)), "The second operand is incorrect");
617 assert_eq!(is.operands[2], Operand::Register(Register::Locator(2)), "The third operand is incorrect");
618 assert_eq!(is.destination, Register::Locator(3), "The destination register is incorrect");
619
620 let (string, is) =
621 ECDSAVerifyKeccak256Raw::<CurrentNetwork>::parse("ecdsa.verify.keccak256.raw r0 r1 r2 into r3").unwrap();
622 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'");
623 assert_eq!(is.operands.len(), 3, "The number of operands is incorrect");
624 assert_eq!(is.operands[0], Operand::Register(Register::Locator(0)), "The first operand is incorrect");
625 assert_eq!(is.operands[1], Operand::Register(Register::Locator(1)), "The second operand is incorrect");
626 assert_eq!(is.operands[2], Operand::Register(Register::Locator(2)), "The third operand is incorrect");
627 assert_eq!(is.destination, Register::Locator(3), "The destination register is incorrect");
628
629 let (string, is) =
630 ECDSAVerifyKeccak256Eth::<CurrentNetwork>::parse("ecdsa.verify.keccak256.eth r0 r1 r2 into r3").unwrap();
631 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'");
632 assert_eq!(is.operands.len(), 3, "The number of operands is incorrect");
633 assert_eq!(is.operands[0], Operand::Register(Register::Locator(0)), "The first operand is incorrect");
634 assert_eq!(is.operands[1], Operand::Register(Register::Locator(1)), "The second operand is incorrect");
635 assert_eq!(is.operands[2], Operand::Register(Register::Locator(2)), "The third operand is incorrect");
636 assert_eq!(is.destination, Register::Locator(3), "The destination register is incorrect");
637 }
638}