brillig/
black_box.rs

1use crate::{HeapArray, MemoryAddress};
2use msgpack_tagged::MsgpackTagged;
3use serde::{Deserialize, Serialize};
4
5/// These opcodes provide an equivalent of ACIR blackbox functions.
6/// They are implemented as native functions in the VM.
7/// For more information, see the ACIR blackbox functions in acir::circuit::opcodes::BlackBoxFuncCall
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9#[derive(Serialize, Deserialize, MsgpackTagged)]
10#[cfg_attr(feature = "arb", derive(proptest_derive::Arbitrary))]
11pub enum BlackBoxOp {
12    /// Encrypts a message using AES-128.
13    #[tag(0)]
14    AES128Encrypt {
15        #[tag(0)]
16        inputs: HeapArray,
17        #[tag(1)]
18        iv: HeapArray,
19        #[tag(2)]
20        key: HeapArray,
21        #[tag(3)]
22        outputs: HeapArray,
23    },
24    /// Calculates the Blake2s hash of the inputs.
25    #[tag(1)]
26    Blake2s {
27        #[tag(0)]
28        message: HeapArray,
29        #[tag(1)]
30        output: HeapArray,
31    },
32    /// Calculates the Blake3 hash of the inputs.
33    #[tag(2)]
34    Blake3 {
35        #[tag(0)]
36        message: HeapArray,
37        #[tag(1)]
38        output: HeapArray,
39    },
40    /// Keccak permutation function of 1600 width.
41    #[tag(3)]
42    Keccakf1600 {
43        #[tag(0)]
44        input: HeapArray,
45        #[tag(1)]
46        output: HeapArray,
47    },
48    /// Verifies an ECDSA signature over the secp256k1 curve.
49    #[tag(4)]
50    EcdsaSecp256k1 {
51        #[tag(0)]
52        hashed_msg: HeapArray,
53        #[tag(1)]
54        public_key_x: HeapArray,
55        #[tag(2)]
56        public_key_y: HeapArray,
57        #[tag(3)]
58        signature: HeapArray,
59        #[tag(4)]
60        result: MemoryAddress,
61    },
62    /// Verifies an ECDSA signature over the secp256r1 curve.
63    #[tag(5)]
64    EcdsaSecp256r1 {
65        #[tag(0)]
66        hashed_msg: HeapArray,
67        #[tag(1)]
68        public_key_x: HeapArray,
69        #[tag(2)]
70        public_key_y: HeapArray,
71        #[tag(3)]
72        signature: HeapArray,
73        #[tag(4)]
74        result: MemoryAddress,
75    },
76    /// Performs multi scalar multiplication over the embedded curve.
77    #[tag(6)]
78    MultiScalarMul {
79        #[tag(0)]
80        points: HeapArray,
81        #[tag(1)]
82        scalars: HeapArray,
83        #[tag(2)]
84        outputs: HeapArray,
85    },
86    /// Performs addition over the embedded curve.
87    #[tag(7)]
88    EmbeddedCurveAdd {
89        #[tag(0)]
90        input1_x: MemoryAddress,
91        #[tag(1)]
92        input1_y: MemoryAddress,
93        #[tag(2)]
94        input2_x: MemoryAddress,
95        #[tag(3)]
96        input2_y: MemoryAddress,
97        #[tag(4)]
98        result: HeapArray,
99    },
100    /// Applies the Poseidon2 permutation function to the given state,
101    /// outputting the permuted state.
102    #[tag(8)]
103    Poseidon2Permutation {
104        #[tag(0)]
105        message: HeapArray,
106        #[tag(1)]
107        output: HeapArray,
108    },
109    /// Applies the SHA-256 compression function to the input message
110    #[tag(9)]
111    Sha256Compression {
112        #[tag(0)]
113        input: HeapArray,
114        #[tag(1)]
115        hash_values: HeapArray,
116        #[tag(2)]
117        output: HeapArray,
118    },
119    /// Returns a decomposition in `num_limbs` limbs of the given input over the given radix.
120    ///
121    /// - The value stored in `radix` must be in the range [2, 256]
122    /// - `num_limbs` must be at least one if the value stored in `input` is not zero.
123    /// - The value stored in `output_bits` must have a `bit_size` of one.
124    ///   That value specifies whether we should decompose into bits. The value stored in
125    ///   the `radix` address must be two if the value stored in `output_bits` is equal to one.
126    ///
127    /// Native to the Brillig VM and not supported as an ACIR black box function.
128    #[tag(10)]
129    ToRadix {
130        #[tag(0)]
131        input: MemoryAddress,
132        #[tag(1)]
133        radix: MemoryAddress,
134        #[tag(2)]
135        output_pointer: MemoryAddress,
136        #[tag(3)]
137        num_limbs: MemoryAddress,
138        #[tag(4)]
139        output_bits: MemoryAddress,
140    },
141}
142
143impl std::fmt::Display for BlackBoxOp {
144    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
145        match self {
146            BlackBoxOp::AES128Encrypt { inputs, iv, key, outputs } => {
147                write!(
148                    f,
149                    "aes_128_encrypt(inputs: {inputs}, iv: {iv}, key: {key}, outputs: {outputs})"
150                )
151            }
152            BlackBoxOp::Blake2s { message, output } => {
153                write!(f, "blake2s(message: {message}, output: {output})")
154            }
155            BlackBoxOp::Blake3 { message, output } => {
156                write!(f, "blake3(message: {message}, output: {output})")
157            }
158            BlackBoxOp::Keccakf1600 { input, output } => {
159                write!(f, "keccakf1600(input: {input}, output: {output})")
160            }
161            BlackBoxOp::EcdsaSecp256k1 {
162                hashed_msg,
163                public_key_x,
164                public_key_y,
165                signature,
166                result,
167            } => {
168                write!(
169                    f,
170                    "ecdsa_secp256k1(hashed_msg: {hashed_msg}, public_key_x: {public_key_x}, public_key_y: {public_key_y}, signature: {signature}, result: {result})"
171                )
172            }
173            BlackBoxOp::EcdsaSecp256r1 {
174                hashed_msg,
175                public_key_x,
176                public_key_y,
177                signature,
178                result,
179            } => {
180                write!(
181                    f,
182                    "ecdsa_secp256r1(hashed_msg: {hashed_msg}, public_key_x: {public_key_x}, public_key_y: {public_key_y}, signature: {signature}, result: {result})"
183                )
184            }
185            BlackBoxOp::MultiScalarMul { points, scalars, outputs } => {
186                write!(
187                    f,
188                    "multi_scalar_mul(points: {points}, scalars: {scalars}, outputs: {outputs})"
189                )
190            }
191            BlackBoxOp::EmbeddedCurveAdd { input1_x, input1_y, input2_x, input2_y, result } => {
192                write!(
193                    f,
194                    "embedded_curve_add(input1_x: {input1_x}, input1_y: {input1_y}, input2_x: {input2_x}, input2_y: {input2_y}, result: {result})"
195                )
196            }
197            BlackBoxOp::Poseidon2Permutation { message, output } => {
198                write!(f, "poseidon2_permutation(message: {message}, output: {output})")
199            }
200            BlackBoxOp::Sha256Compression { input, hash_values, output } => {
201                write!(
202                    f,
203                    "sha256_compression(input: {input}, hash_values: {hash_values}, output: {output})"
204                )
205            }
206            BlackBoxOp::ToRadix { input, radix, output_pointer, num_limbs, output_bits } => {
207                write!(
208                    f,
209                    "to_radix(input: {input}, radix: {radix}, num_limbs: {num_limbs}, output_pointer: {output_pointer}, output_bits: {output_bits})"
210                )
211            }
212        }
213    }
214}