snarkvm_synthesizer_program/logic/instruction/operation/
sign_verify.rs1use crate::{
17 Opcode,
18 Operand,
19 traits::{RegistersLoad, RegistersLoadCircuit, RegistersStore, RegistersStoreCircuit, StackMatches, StackProgram},
20};
21use circuit::prelude::ToFields as CircuitToFields;
22use console::{
23 network::prelude::*,
24 program::{Literal, LiteralType, PlaintextType, Register, RegisterType, ToFields as ConsoleToFields},
25 types::Boolean,
26};
27
28#[derive(Clone, PartialEq, Eq, Hash)]
30pub struct SignVerify<N: Network> {
31 operands: Vec<Operand<N>>,
33 destination: Register<N>,
35}
36
37impl<N: Network> SignVerify<N> {
38 #[inline]
40 pub fn new(operands: Vec<Operand<N>>, destination: Register<N>) -> Result<Self> {
41 ensure!(operands.len() == 3, "Instruction '{}' must have three operands", Self::opcode());
43 Ok(Self { operands, destination })
45 }
46
47 #[inline]
49 pub const fn opcode() -> Opcode {
50 Opcode::Sign
51 }
52
53 #[inline]
55 pub fn operands(&self) -> &[Operand<N>] {
56 debug_assert!(self.operands.len() == 3, "Instruction '{}' must have three operands", Self::opcode());
58 &self.operands
60 }
61
62 #[inline]
64 pub fn destinations(&self) -> Vec<Register<N>> {
65 vec![self.destination.clone()]
66 }
67}
68
69impl<N: Network> SignVerify<N> {
70 #[inline]
72 pub fn evaluate(
73 &self,
74 stack: &(impl StackMatches<N> + StackProgram<N>),
75 registers: &mut (impl RegistersLoad<N> + RegistersStore<N>),
76 ) -> Result<()> {
77 if self.operands.len() != 3 {
79 bail!("Instruction '{}' expects 3 operands, found {} operands", Self::opcode(), self.operands.len())
80 }
81
82 let signature = match registers.load_literal(stack, &self.operands[0])? {
84 Literal::Signature(signature) => signature,
85 _ => bail!("Expected the first operand to be a signature."),
86 };
87 let address = match registers.load_literal(stack, &self.operands[1])? {
88 Literal::Address(address) => address,
89 _ => bail!("Expected the second operand to be an address."),
90 };
91 let message = registers.load(stack, &self.operands[2])?;
92
93 let output = Literal::Boolean(Boolean::new(signature.verify(&address, &message.to_fields()?)));
95
96 registers.store_literal(stack, &self.destination, output)
98 }
99
100 #[inline]
102 pub fn execute<A: circuit::Aleo<Network = N>>(
103 &self,
104 stack: &(impl StackMatches<N> + StackProgram<N>),
105 registers: &mut (impl RegistersLoadCircuit<N, A> + RegistersStoreCircuit<N, A>),
106 ) -> Result<()> {
107 if self.operands.len() != 3 {
109 bail!("Instruction '{}' expects 3 operands, found {} operands", Self::opcode(), self.operands.len())
110 }
111
112 let signature = match registers.load_literal_circuit(stack, &self.operands[0])? {
114 circuit::Literal::Signature(signature) => signature,
115 _ => bail!("Expected the first operand to be a signature."),
116 };
117 let address = match registers.load_literal_circuit(stack, &self.operands[1])? {
118 circuit::Literal::Address(address) => address,
119 _ => bail!("Expected the second operand to be an address."),
120 };
121 let message = registers.load_circuit(stack, &self.operands[2])?;
122
123 let output = circuit::Literal::Boolean(signature.verify(&address, &message.to_fields()));
125
126 registers.store_literal_circuit(stack, &self.destination, output)
128 }
129
130 #[inline]
132 pub fn finalize(
133 &self,
134 stack: &(impl StackMatches<N> + StackProgram<N>),
135 registers: &mut (impl RegistersLoad<N> + RegistersStore<N>),
136 ) -> Result<()> {
137 self.evaluate(stack, registers)
138 }
139
140 #[inline]
142 pub fn output_types(
143 &self,
144 _stack: &impl StackProgram<N>,
145 input_types: &[RegisterType<N>],
146 ) -> Result<Vec<RegisterType<N>>> {
147 if input_types.len() != 3 {
149 bail!("Instruction '{}' expects 3 inputs, found {} inputs", Self::opcode(), input_types.len())
150 }
151
152 if input_types[0] != RegisterType::Plaintext(PlaintextType::Literal(LiteralType::Signature)) {
154 bail!(
155 "Instruction '{}' expects the first input to be a 'signature'. Found input of type '{}'",
156 Self::opcode(),
157 input_types[0]
158 )
159 }
160
161 if input_types[1] != RegisterType::Plaintext(PlaintextType::Literal(LiteralType::Address)) {
163 bail!(
164 "Instruction '{}' expects the second input to be an 'address'. Found input of type '{}'",
165 Self::opcode(),
166 input_types[1]
167 )
168 }
169
170 Ok(vec![RegisterType::Plaintext(PlaintextType::Literal(LiteralType::Boolean))])
171 }
172}
173
174impl<N: Network> Parser for SignVerify<N> {
175 #[inline]
177 fn parse(string: &str) -> ParserResult<Self> {
178 let (string, _) = tag(*Self::opcode())(string)?;
180 let (string, _) = Sanitizer::parse_whitespaces(string)?;
182 let (string, first) = Operand::parse(string)?;
184 let (string, _) = Sanitizer::parse_whitespaces(string)?;
186 let (string, second) = Operand::parse(string)?;
188 let (string, _) = Sanitizer::parse_whitespaces(string)?;
190 let (string, third) = Operand::parse(string)?;
192 let (string, _) = Sanitizer::parse_whitespaces(string)?;
194 let (string, _) = tag("into")(string)?;
196 let (string, _) = Sanitizer::parse_whitespaces(string)?;
198 let (string, destination) = Register::parse(string)?;
200
201 Ok((string, Self { operands: vec![first, second, third], destination }))
202 }
203}
204
205impl<N: Network> FromStr for SignVerify<N> {
206 type Err = Error;
207
208 #[inline]
210 fn from_str(string: &str) -> Result<Self> {
211 match Self::parse(string) {
212 Ok((remainder, object)) => {
213 ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\"");
215 Ok(object)
217 }
218 Err(error) => bail!("Failed to parse string. {error}"),
219 }
220 }
221}
222
223impl<N: Network> Debug for SignVerify<N> {
224 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
226 Display::fmt(self, f)
227 }
228}
229
230impl<N: Network> Display for SignVerify<N> {
231 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
233 if self.operands.len() != 3 {
235 return Err(fmt::Error);
236 }
237 write!(f, "{} ", Self::opcode())?;
239 self.operands.iter().try_for_each(|operand| write!(f, "{operand} "))?;
240 write!(f, "into {}", self.destination)
241 }
242}
243
244impl<N: Network> FromBytes for SignVerify<N> {
245 fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
247 let mut operands = Vec::with_capacity(3);
249 for _ in 0..3 {
251 operands.push(Operand::read_le(&mut reader)?);
252 }
253 let destination = Register::read_le(&mut reader)?;
255
256 Ok(Self { operands, destination })
258 }
259}
260
261impl<N: Network> ToBytes for SignVerify<N> {
262 fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
264 if self.operands.len() != 3 {
266 return Err(error(format!("The number of operands must be 3, found {}", self.operands.len())));
267 }
268 self.operands.iter().try_for_each(|operand| operand.write_le(&mut writer))?;
270 self.destination.write_le(&mut writer)
272 }
273}
274
275#[cfg(test)]
276mod tests {
277 use super::*;
278 use console::network::MainnetV0;
279
280 type CurrentNetwork = MainnetV0;
281
282 #[test]
283 fn test_parse() {
284 let (string, is) = SignVerify::<CurrentNetwork>::parse("sign.verify r0 r1 r2 into r3").unwrap();
285 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'");
286 assert_eq!(is.operands.len(), 3, "The number of operands is incorrect");
287 assert_eq!(is.operands[0], Operand::Register(Register::Locator(0)), "The first operand is incorrect");
288 assert_eq!(is.operands[1], Operand::Register(Register::Locator(1)), "The second operand is incorrect");
289 assert_eq!(is.operands[2], Operand::Register(Register::Locator(2)), "The third operand is incorrect");
290 assert_eq!(is.destination, Register::Locator(3), "The destination register is incorrect");
291 }
292}