snarkvm_synthesizer_program/logic/instruction/
mod.rs

1// Copyright (c) 2019-2025 Provable Inc.
2// This file is part of the snarkVM library.
3
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at:
7
8// http://www.apache.org/licenses/LICENSE-2.0
9
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16mod opcode;
17pub use opcode::*;
18
19mod operand;
20pub use operand::*;
21
22mod operation;
23pub use operation::*;
24
25mod bytes;
26mod parse;
27
28use crate::{RegistersCircuit, RegistersSigner, RegistersTrait, StackTrait, instruction};
29use console::{
30    network::Network,
31    prelude::{
32        Debug,
33        Display,
34        Error,
35        Formatter,
36        FromBytes,
37        FromStr,
38        IoResult,
39        Parser,
40        ParserResult,
41        Read,
42        Result,
43        Sanitizer,
44        ToBytes,
45        Write,
46        alt,
47        bail,
48        ensure,
49        error,
50        fmt,
51        map,
52        tag,
53    },
54    program::{Register, RegisterType},
55};
56
57#[derive(Clone, PartialEq, Eq, Hash)]
58pub enum Instruction<N: Network> {
59    /// Compute the absolute value of `first`, checking for overflow, and storing the outcome in `destination`.
60    Abs(Abs<N>),
61    /// Compute the absolute value of `first`, wrapping around at the boundary of the type, and storing the outcome in `destination`.
62    AbsWrapped(AbsWrapped<N>),
63    /// Adds `first` with `second`, storing the outcome in `destination`.
64    Add(Add<N>),
65    /// Adds `first` with `second`, wrapping around at the boundary of the type, and storing the outcome in `destination`.
66    AddWrapped(AddWrapped<N>),
67    /// Performs a bitwise `and` operation on `first` and `second`, storing the outcome in `destination`.
68    And(And<N>),
69    /// Asserts `first` and `second` are equal.
70    AssertEq(AssertEq<N>),
71    /// Asserts `first` and `second` are **not** equal.
72    AssertNeq(AssertNeq<N>),
73    /// Calls a finalize asynchronously on the operands.
74    Async(Async<N>),
75    /// Calls a closure or function on the operands.
76    Call(Call<N>),
77    /// Casts the operands into the declared type.
78    Cast(Cast<N>),
79    /// Casts the operands into the declared type, with lossy truncation if applicable.
80    CastLossy(CastLossy<N>),
81    /// Performs a BHP commitment on inputs of 256-bit chunks.
82    CommitBHP256(CommitBHP256<N>),
83    /// Performs a BHP commitment on inputs of 512-bit chunks.
84    CommitBHP512(CommitBHP512<N>),
85    /// Performs a BHP commitment on inputs of 768-bit chunks.
86    CommitBHP768(CommitBHP768<N>),
87    /// Performs a BHP commitment on inputs of 1024-bit chunks.
88    CommitBHP1024(CommitBHP1024<N>),
89    /// Performs a Pedersen commitment on up to a 64-bit input.
90    CommitPED64(CommitPED64<N>),
91    /// Performs a Pedersen commitment on up to a 128-bit input.
92    CommitPED128(CommitPED128<N>),
93    /// Deserializes the bits into a value.
94    DeserializeBits(DeserializeBits<N>),
95    /// Deserializes the raw bits into a value.
96    DeserializeBitsRaw(DeserializeBitsRaw<N>),
97    /// Divides `first` by `second`, storing the outcome in `destination`.
98    Div(Div<N>),
99    /// Divides `first` by `second`, wrapping around at the boundary of the type, and storing the outcome in `destination`.
100    DivWrapped(DivWrapped<N>),
101    /// Doubles `first`, storing the outcome in `destination`.
102    Double(Double<N>),
103    /// Computes whether `signature` is valid for the given `signer` and `digest` using ECDSA.
104    ECDSAVerifyDigest(ECDSAVerifyDigest<N>),
105    /// Computes whether `signature` is valid for the given Ethereum `address` and `digest` using ECDSA.
106    ECDSAVerifyDigestEth(ECDSAVerifyDigestEth<N>),
107    /// Computes whether `signature` is valid for the given `signer` and `message` using ECDSA with Keccak256.
108    ECDSAVerifyKeccak256(ECDSAVerifyKeccak256<N>),
109    /// Computes whether `signature` is valid for the given `signer` and `message` using ECDSA with Keccak256 and raw inputs.
110    ECDSAVerifyKeccak256Raw(ECDSAVerifyKeccak256Raw<N>),
111    /// Computes whether `signature` is valid for the given Ethereum `address` and `message` using ECDSA with Keccak256 and raw inputs.
112    ECDSAVerifyKeccak256Eth(ECDSAVerifyKeccak256Eth<N>),
113    /// Computes whether `signature` is valid for the given `signer` and `message` using ECDSA with Keccak384.
114    ECDSAVerifyKeccak384(ECDSAVerifyKeccak384<N>),
115    /// Computes whether `signature` is valid for the given `signer` and `message` using ECDSA with Keccak384 and raw inputs.
116    ECDSAVerifyKeccak384Raw(ECDSAVerifyKeccak384Raw<N>),
117    /// Computes whether `signature` is valid for the given Ethereum `address` and `message` using ECDSA with Keccak384 and raw inputs.
118    ECDSAVerifyKeccak384Eth(ECDSAVerifyKeccak384Eth<N>),
119    /// Computes whether `signature` is valid for the given `signer` and `message` using ECDSA with Keccak512.
120    ECDSAVerifyKeccak512(ECDSAVerifyKeccak512<N>),
121    /// Computes whether `signature` is valid for the given `signer` and `message` using ECDSA with Keccak512 and raw inputs.
122    ECDSAVerifyKeccak512Raw(ECDSAVerifyKeccak512Raw<N>),
123    /// Computes whether `signature` is valid for the given Ethereum `address` and `message` using ECDSA with Keccak512 and raw inputs.
124    ECDSAVerifyKeccak512Eth(ECDSAVerifyKeccak512Eth<N>),
125    /// Computes whether `signature` is valid for the given `signer` and `message` using ECDSA with SHA3-256.
126    ECDSAVerifySha3_256(ECDSAVerifySha3_256<N>),
127    /// Computes whether `signature` is valid for the given `signer` and `message` using ECDSA with SHA3-256 and raw inputs.
128    ECDSAVerifySha3_256Raw(ECDSAVerifySha3_256Raw<N>),
129    /// Computes whether `signature` is valid for the given Ethereum `address` and `message` using ECDSA with SHA3-256 and raw inputs.
130    ECDSAVerifySha3_256Eth(ECDSAVerifySha3_256Eth<N>),
131    /// Computes whether `signature` is valid for the given `signer` and `message` using ECDSA with SHA3-384.
132    ECDSAVerifySha3_384(ECDSAVerifySha3_384<N>),
133    /// Computes whether `signature` is valid for the given `signer` and `message` using ECDSA with SHA3-384 and raw inputs.
134    ECDSAVerifySha3_384Raw(ECDSAVerifySha3_384Raw<N>),
135    /// Computes whether `signature` is valid for the given Ethereum `address` and `message` using ECDSA with SHA3-384 and raw inputs.
136    ECDSAVerifySha3_384Eth(ECDSAVerifySha3_384Eth<N>),
137    /// Computes whether `signature` is valid for the given `signer` and `message` using ECDSA with SHA3-512.
138    ECDSAVerifySha3_512(ECDSAVerifySha3_512<N>),
139    /// Computes whether `signature` is valid for the given `signer` and `message` using ECDSA with SHA3-512 and raw inputs.
140    ECDSAVerifySha3_512Raw(ECDSAVerifySha3_512Raw<N>),
141    /// Computes whether `signature` is valid for the given Ethereum `address` and `message` using ECDSA with SHA3-512 and raw inputs.
142    ECDSAVerifySha3_512Eth(ECDSAVerifySha3_512Eth<N>),
143    /// Computes whether `first` is greater than `second` as a boolean, storing the outcome in `destination`.
144    GreaterThan(GreaterThan<N>),
145    /// Computes whether `first` is greater than or equal to `second` as a boolean, storing the outcome in `destination`.
146    GreaterThanOrEqual(GreaterThanOrEqual<N>),
147    /// Performs a BHP hash on inputs of 256-bit chunks.
148    HashBHP256(HashBHP256<N>),
149    /// Performs a BHP hash on the input's raw bits in 256-bit chunks.  
150    HashBHP256Raw(HashBHP256Raw<N>),
151    /// Performs a BHP hash on inputs of 512-bit chunks.
152    HashBHP512(HashBHP512<N>),
153    /// Performs a BHP hash on the input's raw bits in 512-bit chunks.  
154    HashBHP512Raw(HashBHP512Raw<N>),
155    /// Performs a BHP hash on inputs of 768-bit chunks.
156    HashBHP768(HashBHP768<N>),
157    /// Performs a BHP hash on the input's raw bits in 768-bit chunks.  
158    HashBHP768Raw(HashBHP768Raw<N>),
159    /// Performs a BHP hash on inputs of 1024-bit chunks.
160    HashBHP1024(HashBHP1024<N>),
161    /// Performs a BHP hash on the input's raw bits in 1024-bit chunks.
162    HashBHP1024Raw(HashBHP1024Raw<N>),
163    /// Performs a Keccak hash on the input, outputting 256 bits, hashing the result with BHP256.
164    HashKeccak256(HashKeccak256<N>),
165    /// Performs a Keccak hash on the input's raw bits, hashing the result with BHP256.
166    HashKeccak256Raw(HashKeccak256Raw<N>),
167    /// Performs a Keccak hash on the input, outputting 256 bits.
168    HashKeccak256Native(HashKeccak256Native<N>),
169    /// Performs a Keccak hash on the input's raw bits, outputting 256 bits.
170    HashKeccak256NativeRaw(HashKeccak256NativeRaw<N>),
171    /// Performs a Keccak hash on the input, outputting 384 bits, hashing the result with BHP512.
172    HashKeccak384(HashKeccak384<N>),
173    /// Performs a Keccak hash on the input's raw bits, outputting 384 bits, hashing the result with BHP512.
174    HashKeccak384Raw(HashKeccak384Raw<N>),
175    /// Performs a Keccak hash on the input, outputting 384 bits.
176    HashKeccak384Native(HashKeccak384Native<N>),
177    /// Performs a Keccak hash on the input's raw bits, outputting 384 bits.
178    HashKeccak384NativeRaw(HashKeccak384NativeRaw<N>),
179    /// Performs a Keccak hash on the input, outputting 512 bits, hashing the result with BHP512.
180    HashKeccak512(HashKeccak512<N>),
181    /// Performs a Keccak hash on the input's raw bits, outputting 512 bits, hashing the result with BHP512.
182    HashKeccak512Raw(HashKeccak512Raw<N>),
183    /// Performs a Keccak hash on the input, outputting 512 bits.
184    HashKeccak512Native(HashKeccak512Native<N>),
185    /// Performs a Keccak hash on the input's raw bits, outputting 512 bits.
186    HashKeccak512NativeRaw(HashKeccak512NativeRaw<N>),
187    /// Performs a Pedersen hash on up to a 64-bit input.
188    HashPED64(HashPED64<N>),
189    /// Performs a Pedersen hash on the input's raw bits up to a 64-bit input.
190    HashPED64Raw(HashPED64Raw<N>),
191    /// Performs a Pedersen hash on up to a 128-bit input.
192    HashPED128(HashPED128<N>),
193    /// Performs a Pedersen hash on the input's raw bits up to a 128-bit input.
194    HashPED128Raw(HashPED128Raw<N>),
195    /// Performs a Poseidon hash with an input rate of 2.
196    HashPSD2(HashPSD2<N>),
197    /// Performs a Poseidon hash on the input's raw fields with an input rate of 2.
198    HashPSD2Raw(HashPSD2Raw<N>),
199    /// Performs a Poseidon hash with an input rate of 4.
200    HashPSD4(HashPSD4<N>),
201    /// Performs a Poseidon hash on the input's raw fields with an input rate of 4.
202    HashPSD4Raw(HashPSD4Raw<N>),
203    /// Performs a Poseidon hash with an input rate of 8.
204    HashPSD8(HashPSD8<N>),
205    /// Performs a Poseidon hash on the input's raw fields with an input rate of 8.
206    HashPSD8Raw(HashPSD8Raw<N>),
207    /// Performs a SHA-3 hash on the input, outputting 256 bits, hashing the result with BHP256.
208    HashSha3_256(HashSha3_256<N>),
209    /// Performs a SHA-3 hash on the input's raw bits, outputting 256 bits, hashing the result with BHP256.
210    HashSha3_256Raw(HashSha3_256Raw<N>),
211    /// Performs a SHA-3 hash on the input's bits, outputting 256 bits.
212    HashSha3_256Native(HashSha3_256Native<N>),
213    /// Performs a SHA-3 hash on the input's raw bits, outputting 256 bits.
214    HashSha3_256NativeRaw(HashSha3_256NativeRaw<N>),
215    /// Performs a SHA-3 hash on the input, outputting 384 bits, hashing the result with BHP512.
216    HashSha3_384(HashSha3_384<N>),
217    /// Performs a SHA-3 hash on the input's raw bits, outputting 384 bits, hashing the result with BHP512.
218    HashSha3_384Raw(HashSha3_384Raw<N>),
219    /// Performs a SHA-3 hash on the input's bits, outputting 384 bits.
220    HashSha3_384Native(HashSha3_384Native<N>),
221    /// Performs a SHA-3 hash on the input's raw bits, outputting 384 bits.
222    HashSha3_384NativeRaw(HashSha3_384NativeRaw<N>),
223    /// Performs a SHA-3 hash, outputting 512 bits, hashing the result with BHP512.
224    HashSha3_512(HashSha3_512<N>),
225    /// Performs a SHA-3 hash on the input's raw bits, outputting 512 bits, hashing the result with BHP512.
226    HashSha3_512Raw(HashSha3_512Raw<N>),
227    /// Performs a SHA-3 hash on the input's bits, outputting 512 bits.
228    HashSha3_512Native(HashSha3_512Native<N>),
229    /// Performs a SHA-3 hash on the input's raw bits, outputting 512 bits.
230    HashSha3_512NativeRaw(HashSha3_512NativeRaw<N>),
231    /// Performs a Poseidon hash with an input rate of 2.
232    HashManyPSD2(HashManyPSD2<N>),
233    /// Performs a Poseidon hash with an input rate of 4.
234    HashManyPSD4(HashManyPSD4<N>),
235    /// Performs a Poseidon hash with an input rate of 8.
236    HashManyPSD8(HashManyPSD8<N>),
237    /// Computes the multiplicative inverse of `first`, storing the outcome in `destination`.
238    Inv(Inv<N>),
239    /// Computes whether `first` equals `second` as a boolean, storing the outcome in `destination`.
240    IsEq(IsEq<N>),
241    /// Computes whether `first` does **not** equals `second` as a boolean, storing the outcome in `destination`.
242    IsNeq(IsNeq<N>),
243    /// Computes whether `first` is less than `second` as a boolean, storing the outcome in `destination`.
244    LessThan(LessThan<N>),
245    /// Computes whether `first` is less than or equal to `second` as a boolean, storing the outcome in `destination`.
246    LessThanOrEqual(LessThanOrEqual<N>),
247    /// Computes `first` mod `second`, storing the outcome in `destination`.
248    Modulo(Modulo<N>),
249    /// Multiplies `first` with `second`, storing the outcome in `destination`.
250    Mul(Mul<N>),
251    /// Multiplies `first` with `second`, wrapping around at the boundary of the type, and storing the outcome in `destination`.
252    MulWrapped(MulWrapped<N>),
253    /// Returns `false` if `first` and `second` are true, storing the outcome in `destination`.
254    Nand(Nand<N>),
255    /// Negates `first`, storing the outcome in `destination`.
256    Neg(Neg<N>),
257    /// Returns `true` if neither `first` nor `second` is `true`, storing the outcome in `destination`.
258    Nor(Nor<N>),
259    /// Flips each bit in the representation of `first`, storing the outcome in `destination`.
260    Not(Not<N>),
261    /// Performs a bitwise `or` on `first` and `second`, storing the outcome in `destination`.
262    Or(Or<N>),
263    /// Raises `first` to the power of `second`, storing the outcome in `destination`.
264    Pow(Pow<N>),
265    /// Raises `first` to the power of `second`, wrapping around at the boundary of the type, storing the outcome in `destination`.
266    PowWrapped(PowWrapped<N>),
267    /// Divides `first` by `second`, storing the remainder in `destination`.
268    Rem(Rem<N>),
269    /// Divides `first` by `second`, wrapping around at the boundary of the type, storing the remainder in `destination`.
270    RemWrapped(RemWrapped<N>),
271    /// Serializes the bits of the input.
272    SerializeBits(SerializeBits<N>),
273    /// Serializes the raw bits of the input.
274    SerializeBitsRaw(SerializeBitsRaw<N>),
275    /// Shifts `first` left by `second` bits, storing the outcome in `destination`.
276    Shl(Shl<N>),
277    /// Shifts `first` left by `second` bits, wrapping around at the boundary of the type, storing the outcome in `destination`.
278    ShlWrapped(ShlWrapped<N>),
279    /// Shifts `first` right by `second` bits, storing the outcome in `destination`.
280    Shr(Shr<N>),
281    /// Shifts `first` right by `second` bits, wrapping around at the boundary of the type, storing the outcome in `destination`.
282    ShrWrapped(ShrWrapped<N>),
283    /// Computes whether `signature` is valid for the given `address` and `message`.
284    SignVerify(SignVerify<N>),
285    /// Squares 'first', storing the outcome in `destination`.
286    Square(Square<N>),
287    /// Compute the square root of 'first', storing the outcome in `destination`.
288    SquareRoot(SquareRoot<N>),
289    /// Computes `first - second`, storing the outcome in `destination`.
290    Sub(Sub<N>),
291    /// Computes `first - second`, wrapping around at the boundary of the type, and storing the outcome in `destination`.
292    SubWrapped(SubWrapped<N>),
293    /// Selects `first`, if `condition` is true, otherwise selects `second`, storing the result in `destination`.
294    Ternary(Ternary<N>),
295    /// Performs a bitwise `xor` on `first` and `second`, storing the outcome in `destination`.
296    Xor(Xor<N>),
297}
298
299/// Creates a match statement that applies the given operation for each instruction.
300///
301/// ## Example
302/// This example will print the opcode and the instruction to the given stream.
303/// ```rust,ignore
304/// instruction!(self, |instruction| write!(f, "{} {};", self.opcode(), instruction))
305/// ```
306/// The above example is equivalent to the following logic:
307/// ```rust,ignore
308///     match self {
309///         Self::Add(instruction) => write!(f, "{} {};", self.opcode(), instruction),
310///         Self::Sub(instruction) => write!(f, "{} {};", self.opcode(), instruction),
311///         Self::Mul(instruction) => write!(f, "{} {};", self.opcode(), instruction),
312///         Self::Div(instruction) => write!(f, "{} {};", self.opcode(), instruction),
313///     }
314/// ```
315#[macro_export]
316macro_rules! instruction {
317    // A variant **with** curly braces:
318    // i.e. `instruction!(self, |instruction| { operation(instruction) })`.
319    ($object:expr, |$input:ident| $operation:block) => {{ $crate::instruction!(instruction, $object, |$input| $operation) }};
320    // A variant **without** curly braces:
321    // i.e. `instruction!(self, |instruction| operation(instruction))`.
322    ($object:expr, |$input:ident| $operation:expr) => {{ $crate::instruction!(instruction, $object, |$input| { $operation }) }};
323    // A variant **with** curly braces:
324    // i.e. `instruction!(custom_macro, self, |instruction| { operation(instruction) })`.
325    ($macro_:ident, $object:expr, |$input:ident| $operation:block) => {
326        $macro_!{$object, |$input| $operation, {
327            // The original opcodes.
328            Abs,
329            AbsWrapped,
330            Add,
331            AddWrapped,
332            And,
333            AssertEq,
334            AssertNeq,
335            Async,
336            Call,
337            Cast,
338            CastLossy,
339            CommitBHP256,
340            CommitBHP512,
341            CommitBHP768,
342            CommitBHP1024,
343            CommitPED64,
344            CommitPED128,
345            Div,
346            DivWrapped,
347            Double,
348            GreaterThan,
349            GreaterThanOrEqual,
350            HashBHP256,
351            HashBHP512,
352            HashBHP768,
353            HashBHP1024,
354            HashKeccak256,
355            HashKeccak384,
356            HashKeccak512,
357            HashPED64,
358            HashPED128,
359            HashPSD2,
360            HashPSD4,
361            HashPSD8,
362            HashSha3_256,
363            HashSha3_384,
364            HashSha3_512,
365            HashManyPSD2,
366            HashManyPSD4,
367            HashManyPSD8,
368            Inv,
369            IsEq,
370            IsNeq,
371            LessThan,
372            LessThanOrEqual,
373            Modulo,
374            Mul,
375            MulWrapped,
376            Nand,
377            Neg,
378            Nor,
379            Not,
380            Or,
381            Pow,
382            PowWrapped,
383            Rem,
384            RemWrapped,
385            Shl,
386            ShlWrapped,
387            Shr,
388            ShrWrapped,
389            SignVerify,
390            Square,
391            SquareRoot,
392            Sub,
393            SubWrapped,
394            Ternary,
395            Xor,
396
397            // New opcodes added in `ConsensusVersion::V11`
398            DeserializeBits,
399            DeserializeBitsRaw,
400            ECDSAVerifyDigest,
401            ECDSAVerifyDigestEth,
402            ECDSAVerifyKeccak256,
403            ECDSAVerifyKeccak256Raw,
404            ECDSAVerifyKeccak256Eth,
405            ECDSAVerifyKeccak384,
406            ECDSAVerifyKeccak384Raw,
407            ECDSAVerifyKeccak384Eth,
408            ECDSAVerifyKeccak512,
409            ECDSAVerifyKeccak512Raw,
410            ECDSAVerifyKeccak512Eth,
411            ECDSAVerifySha3_256,
412            ECDSAVerifySha3_256Raw,
413            ECDSAVerifySha3_256Eth,
414            ECDSAVerifySha3_384,
415            ECDSAVerifySha3_384Raw,
416            ECDSAVerifySha3_384Eth,
417            ECDSAVerifySha3_512,
418            ECDSAVerifySha3_512Raw,
419            ECDSAVerifySha3_512Eth,
420            HashBHP256Raw,
421            HashBHP512Raw,
422            HashBHP768Raw,
423            HashBHP1024Raw,
424            HashKeccak256Raw,
425            HashKeccak256Native,
426            HashKeccak256NativeRaw,
427            HashKeccak384Raw,
428            HashKeccak384Native,
429            HashKeccak384NativeRaw,
430            HashKeccak512Raw,
431            HashKeccak512Native,
432            HashKeccak512NativeRaw,
433            HashPED64Raw,
434            HashPED128Raw,
435            HashPSD2Raw,
436            HashPSD4Raw,
437            HashPSD8Raw,
438            HashSha3_256Raw,
439            HashSha3_256Native,
440            HashSha3_256NativeRaw,
441            HashSha3_384Raw,
442            HashSha3_384Native,
443            HashSha3_384NativeRaw,
444            HashSha3_512Raw,
445            HashSha3_512Native,
446            HashSha3_512NativeRaw,
447            SerializeBits,
448            SerializeBitsRaw,
449
450            // New opcodes should be added here, with a comment on which consensus version they were added in.
451        }}
452    };
453    // A variant **without** curly braces:
454    // i.e. `instruction!(custom_macro, self, |instruction| operation(instruction))`.
455    ($macro_:ident, $object:expr, |$input:ident| $operation:expr) => {{ $crate::instruction!($macro_, $object, |$input| { $operation }) }};
456    // A variant invoking a macro internally:
457    // i.e. `instruction!(instruction_to_bytes_le!(self, writer))`.
458    ($macro_:ident!($object:expr, $input:ident)) => {{ $crate::instruction!($macro_, $object, |$input| {}) }};
459
460    ////////////////////
461    // Private Macros //
462    ////////////////////
463
464    // A static variant **with** curly braces:
465    // i.e. `instruction!(self, |InstructionMember| { InstructionMember::opcode() })`.
466    ($object:expr, |InstructionMember| $operation:block, { $( $variant:ident, )+ }) => {{
467        // Build the match cases.
468        match $object {
469            $( Self::$variant(..) => {{
470                // Set the variant to be called `InstructionMember`.
471                type InstructionMember<N> = $variant<N>;
472                // Perform the operation.
473                $operation
474            }} ),+
475        }
476    }};
477    // A static variant **without** curly braces:
478    // i.e. `instruction!(self, |InstructionMember| InstructionMember::opcode())`.
479    ($object:expr, |InstructionMember| $operation:expr, { $( $variant:ident, )+ }) => {{
480        $crate::instruction!($object, |InstructionMember| { $operation }, { $( $variant, )+ })
481    }};
482    // A non-static variant **with** curly braces:
483    // i.e. `instruction!(self, |instruction| { operation(instruction) })`.
484    ($object:expr, |$instruction:ident| $operation:block, { $( $variant:ident, )+ }) => {{
485        // Build the match cases.
486        match $object { $( Self::$variant($instruction) => { $operation } ),+ }
487    }};
488    // A non-static variant **without** curly braces:
489    // i.e. `instruction!(self, |instruction| operation(instruction))`.
490    ($object:expr, |$instruction:ident| $operation:expr, { $( $variant:ident, )+ }) => {{
491        $crate::instruction!($object, |$instruction| { $operation }, { $( $variant, )+ })
492    }};
493}
494
495/// Derives `From<Operation>` for the instruction.
496///
497/// ## Example
498/// ```ignore
499/// derive_from_operation!(Instruction, |None| {}, { Add, Sub, Mul, Div })
500/// ```
501macro_rules! derive_from_operation {
502    ($_object:expr, |$_reader:ident| $_operation:block, { $( $variant:ident, )+ }) => {
503        $(impl<N: Network> From<$variant<N>> for Instruction<N> {
504            #[inline]
505            fn from(operation: $variant<N>) -> Self {
506                Self::$variant(operation)
507            }
508        })+
509    }
510}
511instruction!(derive_from_operation, Instruction, |None| {});
512
513/// Returns a slice of all instruction opcodes.
514///
515/// ## Example
516/// ```ignore
517/// opcodes!(Instruction, |None| {}, { Add, Sub, Mul, Div })
518/// ```
519macro_rules! opcodes {
520    ($_object:expr, |$_reader:ident| $_operation:block, { $( $variant:ident, )+ }) => { [$( $variant::<N>::opcode() ),+] }
521}
522
523impl<N: Network> Instruction<N> {
524    /// The list of all instruction opcodes.
525    pub const OPCODES: &'static [Opcode] = &instruction!(opcodes, Instruction, |None| {});
526
527    /// Returns `true` if the given name is a reserved opcode.
528    pub fn is_reserved_opcode(name: &str) -> bool {
529        // Check if the given name matches any opcode (in its entirety; including past the first '.' if it exists).
530        Instruction::<N>::OPCODES.iter().any(|opcode| **opcode == name)
531    }
532
533    /// Returns the operands of the instruction.
534    #[inline]
535    pub fn operands(&self) -> &[Operand<N>] {
536        instruction!(self, |instruction| instruction.operands())
537    }
538
539    /// Returns the destination registers of the instruction.
540    #[inline]
541    pub fn destinations(&self) -> Vec<Register<N>> {
542        instruction!(self, |instruction| instruction.destinations())
543    }
544
545    /// Returns the `CallOperator` if the instruction is a `call` instruction, otherwise `None`.
546    #[inline]
547    pub fn call_operator(&self) -> Option<&CallOperator<N>> {
548        match self {
549            Self::Call(call) => Some(call.operator()),
550            _ => None,
551        }
552    }
553
554    /// Returns the opcode of the instruction.
555    #[inline]
556    pub const fn opcode(&self) -> Opcode {
557        instruction!(self, |InstructionMember| InstructionMember::<N>::opcode())
558    }
559
560    /// Evaluates the instruction.
561    #[inline]
562    pub fn evaluate(&self, stack: &impl StackTrait<N>, registers: &mut impl RegistersSigner<N>) -> Result<()> {
563        instruction!(self, |instruction| instruction.evaluate(stack, registers))
564    }
565
566    /// Executes the instruction.
567    #[inline]
568    pub fn execute<A: circuit::Aleo<Network = N>>(
569        &self,
570        stack: &impl StackTrait<N>,
571        registers: &mut impl RegistersCircuit<N, A>,
572    ) -> Result<()> {
573        instruction!(self, |instruction| instruction.execute::<A>(stack, registers))
574    }
575
576    /// Finalizes the instruction.
577    #[inline]
578    pub fn finalize(&self, stack: &impl StackTrait<N>, registers: &mut impl RegistersTrait<N>) -> Result<()> {
579        instruction!(self, |instruction| instruction.finalize(stack, registers))
580    }
581
582    /// Returns the output type from the given input types.
583    #[inline]
584    pub fn output_types(
585        &self,
586        stack: &impl StackTrait<N>,
587        input_types: &[RegisterType<N>],
588    ) -> Result<Vec<RegisterType<N>>> {
589        instruction!(self, |instruction| instruction.output_types(stack, input_types))
590    }
591
592    /// Returns `true` if the instruction contains an array type with a size that exceeds the given maximum.
593    pub fn exceeds_max_array_size(&self, max_array_size: u32) -> bool {
594        // Only cast instructions may contain an explicit reference to an array.
595        // Calls may produce them, but they don't explicitly reference the type, and that's
596        // always been allowed.
597        match self {
598            Self::Cast(instruction) => instruction.cast_type().exceeds_max_array_size(max_array_size),
599            Self::SerializeBits(instruction) => instruction.destination_type().exceeds_max_array_size(max_array_size),
600            Self::SerializeBitsRaw(instruction) => {
601                instruction.destination_type().exceeds_max_array_size(max_array_size)
602            }
603            Self::DeserializeBits(instruction) => instruction.operand_type().exceeds_max_array_size(max_array_size),
604            Self::DeserializeBitsRaw(instruction) => instruction.operand_type().exceeds_max_array_size(max_array_size),
605            _ => false,
606        }
607    }
608}
609
610impl<N: Network> Debug for Instruction<N> {
611    /// Prints the instruction as a string.
612    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
613        Display::fmt(self, f)
614    }
615}
616
617impl<N: Network> Display for Instruction<N> {
618    /// Prints the instruction as a string.
619    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
620        instruction!(self, |instruction| write!(f, "{instruction};"))
621    }
622}
623
624#[cfg(test)]
625mod tests {
626    use super::*;
627    use console::network::MainnetV0;
628
629    type CurrentNetwork = MainnetV0;
630
631    #[test]
632    fn test_opcodes() {
633        // Sanity check the number of instructions is unchanged.
634        // Note that the number of opcodes **MUST NOT** exceed u16::MAX.
635        assert_eq!(
636            119,
637            Instruction::<CurrentNetwork>::OPCODES.len(),
638            "Update me if the number of instructions changes."
639        );
640    }
641}