@aztec/protocol-contracts 0.0.1-commit.2f68f620 → 0.0.1-commit.321f6a9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/artifacts/ContractClassRegistry.json +449 -197
- package/artifacts/ContractInstanceRegistry.json +646 -238
- package/artifacts/FeeJuice.json +706 -299
- package/dest/class-registry/contract_class_published_event.d.ts +1 -1
- package/dest/class-registry/contract_class_published_event.d.ts.map +1 -1
- package/dest/class-registry/contract_class_published_event.js +7 -1
- package/dest/class-registry/lazy.js +1 -1
- package/dest/fee-juice/lazy.js +1 -1
- package/dest/instance-registry/lazy.js +1 -1
- package/dest/protocol_contract.d.ts +4 -1
- package/dest/protocol_contract.d.ts.map +1 -1
- package/dest/protocol_contract.js +5 -1
- package/dest/protocol_contract_data.js +32 -32
- package/dest/scripts/generate_data.js +4 -4
- package/dest/tests/fixtures.js +2 -2
- package/package.json +4 -4
- package/src/class-registry/contract_class_published_event.ts +6 -1
- package/src/class-registry/lazy.ts +1 -1
- package/src/fee-juice/lazy.ts +1 -1
- package/src/instance-registry/lazy.ts +1 -1
- package/src/protocol_contract.ts +9 -1
- package/src/protocol_contract_data.ts +31 -31
- package/src/tests/fixtures.ts +2 -2
package/artifacts/FeeJuice.json
CHANGED
|
@@ -9,10 +9,14 @@
|
|
|
9
9
|
{
|
|
10
10
|
"name": "aes128_encrypt_padded_input",
|
|
11
11
|
"start": 824
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"name": "tests::encrypt",
|
|
15
|
+
"start": 921
|
|
12
16
|
}
|
|
13
17
|
],
|
|
14
18
|
"path": "std/aes128.nr",
|
|
15
|
-
"source": "// docs:start:aes128\n/// Given a plaintext as an array of bytes, returns the corresponding aes128 ciphertext (CBC mode). Input padding is performed using PKCS#7, so that the output length is `input.len() + (16 - input.len() % 16)`.\npub fn aes128_encrypt<let N: u32>(\n input: [u8; N],\n iv: [u8; 16],\n key: [u8; 16],\n) -> [u8; N + 16 - N % 16] {\n let padding_length = (16 - N % 16) as u8;\n let mut padded_input: [u8; N + 16 - N % 16] = [0; N + 16 - N % 16];\n for i in 0..N {\n padded_input[i] = input[i];\n }\n for i in N..N + 16 - N % 16 {\n padded_input[i] = padding_length;\n }\n let output = aes128_encrypt_padded_input(padded_input, iv, key);\n output\n}\n\n#[foreign(aes128_encrypt)]\nfn aes128_encrypt_padded_input<let N: u32>(input: [u8; N], iv: [u8; 16], key: [u8; 16]) -> [u8; N] {}\n\n// docs:end:aes128\n"
|
|
19
|
+
"source": "// docs:start:aes128\n/// Given a plaintext as an array of bytes, returns the corresponding aes128 ciphertext (CBC mode). Input padding is performed using PKCS#7, so that the output length is `input.len() + (16 - input.len() % 16)`.\npub fn aes128_encrypt<let N: u32>(\n input: [u8; N],\n iv: [u8; 16],\n key: [u8; 16],\n) -> [u8; N + 16 - N % 16] {\n let padding_length = (16 - N % 16) as u8;\n let mut padded_input: [u8; N + 16 - N % 16] = [0; N + 16 - N % 16];\n for i in 0..N {\n padded_input[i] = input[i];\n }\n for i in N..N + 16 - N % 16 {\n padded_input[i] = padding_length;\n }\n let output = aes128_encrypt_padded_input(padded_input, iv, key);\n output\n}\n\n#[foreign(aes128_encrypt)]\nfn aes128_encrypt_padded_input<let N: u32>(input: [u8; N], iv: [u8; 16], key: [u8; 16]) -> [u8; N] {}\n\n// docs:end:aes128\n\nmod tests {\n use super::aes128_encrypt;\n\n #[test]\n fn encrypt() {\n let input = \"kevlovesrust\".as_bytes();\n let iv = \"0000000000000000\".as_bytes();\n let key = \"0000000000000000\".as_bytes();\n let output = [244, 14, 126, 172, 171, 40, 208, 186, 173, 184, 226, 105, 238, 122, 205, 191];\n assert_eq(aes128_encrypt(input, iv, key), output);\n }\n}\n"
|
|
16
20
|
},
|
|
17
21
|
"16": {
|
|
18
22
|
"function_locations": [
|
|
@@ -58,183 +62,235 @@
|
|
|
58
62
|
},
|
|
59
63
|
{
|
|
60
64
|
"name": "Field::from_le_bytes",
|
|
61
|
-
"start":
|
|
65
|
+
"start": 8073
|
|
62
66
|
},
|
|
63
67
|
{
|
|
64
68
|
"name": "Field::from_be_bytes",
|
|
65
|
-
"start":
|
|
69
|
+
"start": 8820
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"name": "Field::from_le_bytes_checked",
|
|
73
|
+
"start": 9611
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"name": "Field::from_be_bytes_checked",
|
|
77
|
+
"start": 10620
|
|
66
78
|
},
|
|
67
79
|
{
|
|
68
80
|
"name": "__assert_max_bit_size",
|
|
69
|
-
"start":
|
|
81
|
+
"start": 11202
|
|
70
82
|
},
|
|
71
83
|
{
|
|
72
84
|
"name": "__to_le_radix",
|
|
73
|
-
"start":
|
|
85
|
+
"start": 11330
|
|
74
86
|
},
|
|
75
87
|
{
|
|
76
88
|
"name": "__to_be_radix",
|
|
77
|
-
"start":
|
|
89
|
+
"start": 11458
|
|
78
90
|
},
|
|
79
91
|
{
|
|
80
92
|
"name": "__to_le_bits",
|
|
81
|
-
"start":
|
|
93
|
+
"start": 12179
|
|
82
94
|
},
|
|
83
95
|
{
|
|
84
96
|
"name": "__to_be_bits",
|
|
85
|
-
"start":
|
|
97
|
+
"start": 12897
|
|
86
98
|
},
|
|
87
99
|
{
|
|
88
100
|
"name": "modulus_num_bits",
|
|
89
|
-
"start":
|
|
101
|
+
"start": 12972
|
|
90
102
|
},
|
|
91
103
|
{
|
|
92
104
|
"name": "modulus_be_bits",
|
|
93
|
-
"start":
|
|
105
|
+
"start": 13048
|
|
94
106
|
},
|
|
95
107
|
{
|
|
96
108
|
"name": "modulus_le_bits",
|
|
97
|
-
"start":
|
|
109
|
+
"start": 13124
|
|
98
110
|
},
|
|
99
111
|
{
|
|
100
112
|
"name": "modulus_be_bytes",
|
|
101
|
-
"start":
|
|
113
|
+
"start": 13200
|
|
102
114
|
},
|
|
103
115
|
{
|
|
104
116
|
"name": "modulus_le_bytes",
|
|
105
|
-
"start":
|
|
117
|
+
"start": 13276
|
|
106
118
|
},
|
|
107
119
|
{
|
|
108
120
|
"name": "__field_less_than",
|
|
109
|
-
"start":
|
|
121
|
+
"start": 13437
|
|
110
122
|
},
|
|
111
123
|
{
|
|
112
124
|
"name": "field_less_than",
|
|
113
|
-
"start":
|
|
114
|
-
},
|
|
115
|
-
{
|
|
116
|
-
"name": "bytes32_to_field",
|
|
117
|
-
"start": 11210
|
|
125
|
+
"start": 13513
|
|
118
126
|
},
|
|
119
127
|
{
|
|
120
128
|
"name": "lt_fallback",
|
|
121
|
-
"start":
|
|
129
|
+
"start": 13589
|
|
122
130
|
},
|
|
123
131
|
{
|
|
124
132
|
"name": "tests::test_to_be_bits",
|
|
125
|
-
"start":
|
|
133
|
+
"start": 14551
|
|
126
134
|
},
|
|
127
135
|
{
|
|
128
136
|
"name": "tests::test_to_le_bits",
|
|
129
|
-
"start":
|
|
137
|
+
"start": 14824
|
|
130
138
|
},
|
|
131
139
|
{
|
|
132
140
|
"name": "tests::test_to_be_bytes",
|
|
133
|
-
"start":
|
|
141
|
+
"start": 15099
|
|
134
142
|
},
|
|
135
143
|
{
|
|
136
144
|
"name": "tests::test_to_le_bytes",
|
|
137
|
-
"start":
|
|
145
|
+
"start": 15405
|
|
138
146
|
},
|
|
139
147
|
{
|
|
140
148
|
"name": "tests::test_to_be_radix",
|
|
141
|
-
"start":
|
|
149
|
+
"start": 15711
|
|
142
150
|
},
|
|
143
151
|
{
|
|
144
152
|
"name": "tests::test_to_le_radix",
|
|
145
|
-
"start":
|
|
153
|
+
"start": 16293
|
|
146
154
|
},
|
|
147
155
|
{
|
|
148
156
|
"name": "tests::test_to_le_radix_1",
|
|
149
|
-
"start":
|
|
157
|
+
"start": 16893
|
|
150
158
|
},
|
|
151
159
|
{
|
|
152
160
|
"name": "tests::test_to_le_radix_brillig_1",
|
|
153
|
-
"start":
|
|
161
|
+
"start": 17346
|
|
154
162
|
},
|
|
155
163
|
{
|
|
156
164
|
"name": "tests::test_to_le_radix_3",
|
|
157
|
-
"start":
|
|
165
|
+
"start": 17700
|
|
158
166
|
},
|
|
159
167
|
{
|
|
160
168
|
"name": "tests::test_to_le_radix_brillig_3",
|
|
161
|
-
"start":
|
|
169
|
+
"start": 18011
|
|
162
170
|
},
|
|
163
171
|
{
|
|
164
172
|
"name": "tests::test_to_le_radix_512",
|
|
165
|
-
"start":
|
|
173
|
+
"start": 18439
|
|
166
174
|
},
|
|
167
175
|
{
|
|
168
176
|
"name": "tests::not_enough_limbs_brillig",
|
|
169
|
-
"start":
|
|
177
|
+
"start": 18848
|
|
170
178
|
},
|
|
171
179
|
{
|
|
172
180
|
"name": "tests::not_enough_limbs",
|
|
173
|
-
"start":
|
|
181
|
+
"start": 19044
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
"name": "tests::non_zero_field_to_le_bytes_zero_limbs",
|
|
185
|
+
"start": 19274
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
"name": "tests::non_zero_field_to_be_bytes_zero_limbs",
|
|
189
|
+
"start": 19469
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
"name": "tests::zero_field_to_bytes_zero_limbs_unconstrained",
|
|
193
|
+
"start": 19600
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
"name": "tests::zero_field_to_bytes_zero_limbs_constrained",
|
|
197
|
+
"start": 19915
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
"name": "tests::zero_field_to_bytes_zero_limbs_comptime",
|
|
201
|
+
"start": 20227
|
|
174
202
|
},
|
|
175
203
|
{
|
|
176
204
|
"name": "tests::test_field_less_than",
|
|
177
|
-
"start":
|
|
205
|
+
"start": 20558
|
|
178
206
|
},
|
|
179
207
|
{
|
|
180
208
|
"name": "tests::test_large_field_values_unconstrained",
|
|
181
|
-
"start":
|
|
209
|
+
"start": 20813
|
|
182
210
|
},
|
|
183
211
|
{
|
|
184
212
|
"name": "tests::test_large_field_values",
|
|
185
|
-
"start":
|
|
213
|
+
"start": 21266
|
|
186
214
|
},
|
|
187
215
|
{
|
|
188
216
|
"name": "tests::test_decomposition_edge_cases",
|
|
189
|
-
"start":
|
|
217
|
+
"start": 21713
|
|
190
218
|
},
|
|
191
219
|
{
|
|
192
220
|
"name": "tests::test_pow_32",
|
|
193
|
-
"start":
|
|
221
|
+
"start": 22303
|
|
194
222
|
},
|
|
195
223
|
{
|
|
196
224
|
"name": "tests::test_sgn0",
|
|
197
|
-
"start":
|
|
225
|
+
"start": 22632
|
|
198
226
|
},
|
|
199
227
|
{
|
|
200
228
|
"name": "tests::test_bit_decomposition_overflow",
|
|
201
|
-
"start":
|
|
229
|
+
"start": 23054
|
|
202
230
|
},
|
|
203
231
|
{
|
|
204
232
|
"name": "tests::test_byte_decomposition_overflow",
|
|
205
|
-
"start":
|
|
233
|
+
"start": 23336
|
|
206
234
|
},
|
|
207
235
|
{
|
|
208
236
|
"name": "tests::test_to_from_be_bytes_bn254_edge_cases",
|
|
209
|
-
"start":
|
|
237
|
+
"start": 23553
|
|
210
238
|
},
|
|
211
239
|
{
|
|
212
240
|
"name": "tests::test_to_from_le_bytes_bn254_edge_cases",
|
|
213
|
-
"start":
|
|
241
|
+
"start": 25504
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
"name": "tests::test_from_le_bytes_checked_accepts_modulus_minus_one",
|
|
245
|
+
"start": 27439
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
"name": "tests::test_from_le_bytes_checked_rejects_modulus",
|
|
249
|
+
"start": 27918
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
"name": "tests::test_from_le_bytes_checked_rejects_modulus_plus_one",
|
|
253
|
+
"start": 28303
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
"name": "tests::test_from_be_bytes_checked_accepts_modulus_minus_one",
|
|
257
|
+
"start": 28758
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
"name": "tests::test_from_be_bytes_checked_rejects_modulus",
|
|
261
|
+
"start": 29247
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
"name": "tests::test_from_be_bytes_checked_rejects_modulus_plus_one",
|
|
265
|
+
"start": 29632
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
"name": "tests::test_from_bytes_checked_small_n",
|
|
269
|
+
"start": 30076
|
|
214
270
|
},
|
|
215
271
|
{
|
|
216
272
|
"name": "tests::from_le_bits",
|
|
217
|
-
"start":
|
|
273
|
+
"start": 30721
|
|
218
274
|
},
|
|
219
275
|
{
|
|
220
276
|
"name": "tests::from_be_bits",
|
|
221
|
-
"start":
|
|
277
|
+
"start": 31268
|
|
222
278
|
},
|
|
223
279
|
{
|
|
224
280
|
"name": "tests::test_to_from_be_bits_bn254_edge_cases",
|
|
225
|
-
"start":
|
|
281
|
+
"start": 31514
|
|
226
282
|
},
|
|
227
283
|
{
|
|
228
284
|
"name": "tests::test_to_from_le_bits_bn254_edge_cases",
|
|
229
|
-
"start":
|
|
285
|
+
"start": 33447
|
|
230
286
|
},
|
|
231
287
|
{
|
|
232
288
|
"name": "tests::max_bit_size_too_large",
|
|
233
|
-
"start":
|
|
289
|
+
"start": 35379
|
|
234
290
|
}
|
|
235
291
|
],
|
|
236
292
|
"path": "std/field/mod.nr",
|
|
237
|
-
"source": "pub mod bn254;\nuse crate::{runtime::is_unconstrained, static_assert};\nuse bn254::lt as bn254_lt;\n\nimpl Field {\n /// Asserts that `self` can be represented in `bit_size` bits.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^{bit_size}`.\n // docs:start:assert_max_bit_size\n pub fn assert_max_bit_size<let BIT_SIZE: u32>(self) {\n // docs:end:assert_max_bit_size\n static_assert(\n BIT_SIZE < modulus_num_bits() as u32,\n \"BIT_SIZE must be less than modulus_num_bits\",\n );\n __assert_max_bit_size(self, BIT_SIZE);\n }\n\n /// Decomposes `self` into its little endian bit decomposition as a `[bool; N]` array.\n /// This array will be zero padded should not all bits be necessary to represent `self`.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting array will not\n /// be able to represent the original `Field`.\n ///\n /// # Safety\n /// The bit decomposition returned is canonical and is guaranteed to not overflow the modulus.\n // docs:start:to_le_bits\n pub fn to_le_bits<let N: u32>(self: Self) -> [bool; N] {\n // docs:end:to_le_bits\n let bits = __to_le_bits(self);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_le_bits();\n assert(bits.len() <= p.len());\n let mut ok = bits.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bits[N - 1 - i] != p[N - 1 - i]) {\n assert(p[N - 1 - i]);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bits\n }\n\n /// Decomposes `self` into its big endian bit decomposition as a `[bool; N]` array.\n /// This array will be zero padded should not all bits be necessary to represent `self`.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting array will not\n /// be able to represent the original `Field`.\n ///\n /// # Safety\n /// The bit decomposition returned is canonical and is guaranteed to not overflow the modulus.\n // docs:start:to_be_bits\n pub fn to_be_bits<let N: u32>(self: Self) -> [bool; N] {\n // docs:end:to_be_bits\n let bits = __to_be_bits(self);\n\n if !is_unconstrained() {\n // Ensure that the decomposition does not overflow the modulus\n let p = modulus_be_bits();\n assert(bits.len() <= p.len());\n let mut ok = bits.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bits[i] != p[i]) {\n assert(p[i]);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bits\n }\n\n /// Decomposes `self` into its little endian byte decomposition as a `[u8;N]` array\n /// This array will be zero padded should not all bytes be necessary to represent `self`.\n ///\n /// # Failures\n /// The length N of the array must be big enough to contain all the bytes of the 'self',\n /// and no more than the number of bytes required to represent the field modulus\n ///\n /// # Safety\n /// The result is ensured to be the canonical decomposition of the field element\n // docs:start:to_le_bytes\n pub fn to_le_bytes<let N: u32>(self: Self) -> [u8; N] {\n // docs:end:to_le_bytes\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n // Compute the byte decomposition\n let bytes = self.to_le_radix(256);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_le_bytes();\n assert(bytes.len() <= p.len());\n let mut ok = bytes.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bytes[N - 1 - i] != p[N - 1 - i]) {\n assert(bytes[N - 1 - i] < p[N - 1 - i]);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bytes\n }\n\n /// Decomposes `self` into its big endian byte decomposition as a `[u8;N]` array of length required to represent the field modulus\n /// This array will be zero padded should not all bytes be necessary to represent `self`.\n ///\n /// # Failures\n /// The length N of the array must be big enough to contain all the bytes of the 'self',\n /// and no more than the number of bytes required to represent the field modulus\n ///\n /// # Safety\n /// The result is ensured to be the canonical decomposition of the field element\n // docs:start:to_be_bytes\n pub fn to_be_bytes<let N: u32>(self: Self) -> [u8; N] {\n // docs:end:to_be_bytes\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n // Compute the byte decomposition\n let bytes = self.to_be_radix(256);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_be_bytes();\n assert(bytes.len() <= p.len());\n let mut ok = bytes.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bytes[i] != p[i]) {\n assert(bytes[i] < p[i]);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bytes\n }\n\n fn to_le_radix<let N: u32>(self: Self, radix: u32) -> [u8; N] {\n // Brillig does not need an immediate radix\n if !crate::runtime::is_unconstrained() {\n static_assert(1 < radix, \"radix must be greater than 1\");\n static_assert(radix <= 256, \"radix must be less than or equal to 256\");\n static_assert(radix & (radix - 1) == 0, \"radix must be a power of 2\");\n }\n __to_le_radix(self, radix)\n }\n\n fn to_be_radix<let N: u32>(self: Self, radix: u32) -> [u8; N] {\n // Brillig does not need an immediate radix\n if !crate::runtime::is_unconstrained() {\n static_assert(1 < radix, \"radix must be greater than 1\");\n static_assert(radix <= 256, \"radix must be less than or equal to 256\");\n static_assert(radix & (radix - 1) == 0, \"radix must be a power of 2\");\n }\n __to_be_radix(self, radix)\n }\n\n // Returns self to the power of the given exponent value.\n // Caution: we assume the exponent fits into 32 bits\n // using a bigger bit size impacts negatively the performance and should be done only if the exponent does not fit in 32 bits\n pub fn pow_32(self, exponent: Field) -> Field {\n let mut r: Field = 1;\n let b: [bool; 32] = exponent.to_le_bits();\n\n for i in 1..33 {\n r *= r;\n r = (b[32 - i] as Field) * (r * self) + (1 - b[32 - i] as Field) * r;\n }\n r\n }\n\n // Parity of (prime) Field element, i.e. sgn0(x mod p) = false if x `elem` {0, ..., p-1} is even, otherwise sgn0(x mod p) = true.\n pub fn sgn0(self) -> bool {\n (self as u8) % 2 == 1\n }\n\n pub fn lt(self, another: Field) -> bool {\n if crate::compat::is_bn254() {\n bn254_lt(self, another)\n } else {\n lt_fallback(self, another)\n }\n }\n\n /// Convert a little endian byte array to a field element.\n /// If the provided byte array overflows the field modulus then the Field will silently wrap around.\n pub fn from_le_bytes<let N: u32>(bytes: [u8; N]) -> Field {\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bytes[i] as Field) * v;\n v = v * 256;\n }\n result\n }\n\n /// Convert a big endian byte array to a field element.\n /// If the provided byte array overflows the field modulus then the Field will silently wrap around.\n pub fn from_be_bytes<let N: u32>(bytes: [u8; N]) -> Field {\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bytes[N - 1 - i] as Field) * v;\n v = v * 256;\n }\n result\n }\n}\n\n#[builtin(apply_range_constraint)]\nfn __assert_max_bit_size(value: Field, bit_size: u32) {}\n\n// `_radix` must be less than 256\n#[builtin(to_le_radix)]\nfn __to_le_radix<let N: u32>(value: Field, radix: u32) -> [u8; N] {}\n\n// `_radix` must be less than 256\n#[builtin(to_be_radix)]\nfn __to_be_radix<let N: u32>(value: Field, radix: u32) -> [u8; N] {}\n\n/// Decomposes `self` into its little endian bit decomposition as a `[bool; N]` array.\n/// This array will be zero padded should not all bits be necessary to represent `self`.\n///\n/// # Failures\n/// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting array will not\n/// be able to represent the original `Field`.\n///\n/// # Safety\n/// Values of `N` equal to or greater than the number of bits necessary to represent the `Field` modulus\n/// (e.g. 254 for the BN254 field) allow for multiple bit decompositions. This is due to how the `Field` will\n/// wrap around due to overflow when verifying the decomposition.\n#[builtin(to_le_bits)]\nfn __to_le_bits<let N: u32>(value: Field) -> [bool; N] {}\n\n/// Decomposes `self` into its big endian bit decomposition as a `[bool; N]` array.\n/// This array will be zero padded should not all bits be necessary to represent `self`.\n///\n/// # Failures\n/// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting array will not\n/// be able to represent the original `Field`.\n///\n/// # Safety\n/// Values of `N` equal to or greater than the number of bits necessary to represent the `Field` modulus\n/// (e.g. 254 for the BN254 field) allow for multiple bit decompositions. This is due to how the `Field` will\n/// wrap around due to overflow when verifying the decomposition.\n#[builtin(to_be_bits)]\nfn __to_be_bits<let N: u32>(value: Field) -> [bool; N] {}\n\n#[builtin(modulus_num_bits)]\npub comptime fn modulus_num_bits() -> u64 {}\n\n#[builtin(modulus_be_bits)]\npub comptime fn modulus_be_bits() -> [bool] {}\n\n#[builtin(modulus_le_bits)]\npub comptime fn modulus_le_bits() -> [bool] {}\n\n#[builtin(modulus_be_bytes)]\npub comptime fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub comptime fn modulus_le_bytes() -> [u8] {}\n\n/// An unconstrained only built in to efficiently compare fields.\n#[builtin(field_less_than)]\nunconstrained fn __field_less_than(x: Field, y: Field) -> bool {}\n\npub(crate) unconstrained fn field_less_than(x: Field, y: Field) -> bool {\n __field_less_than(x, y)\n}\n\n// Convert a 32 byte array to a field element by modding\npub fn bytes32_to_field(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..16 {\n high = high + (bytes32[15 - i] as Field) * v;\n low = low + (bytes32[16 + 15 - i] as Field) * v;\n v = v * 256;\n }\n // Abuse that a % p + b % p = (a + b) % p and that low < p\n low + high * v\n}\n\nfn lt_fallback(x: Field, y: Field) -> bool {\n if is_unconstrained() {\n // Safety: unconstrained context\n unsafe {\n field_less_than(x, y)\n }\n } else {\n let x_bytes: [u8; 32] = x.to_le_bytes();\n let y_bytes: [u8; 32] = y.to_le_bytes();\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..32 {\n if (!done) {\n let x_byte = x_bytes[32 - 1 - i] as u8;\n let y_byte = y_bytes[32 - 1 - i] as u8;\n let bytes_match = x_byte == y_byte;\n if !bytes_match {\n x_is_lt = x_byte < y_byte;\n done = true;\n }\n }\n }\n x_is_lt\n }\n}\n\nmod tests {\n use crate::{panic::panic, runtime, static_assert};\n use super::{\n field_less_than, modulus_be_bits, modulus_be_bytes, modulus_le_bits, modulus_le_bytes,\n };\n\n #[test]\n // docs:start:to_be_bits_example\n fn test_to_be_bits() {\n let field = 2;\n let bits: [bool; 8] = field.to_be_bits();\n assert_eq(bits, [false, false, false, false, false, false, true, false]);\n }\n // docs:end:to_be_bits_example\n\n #[test]\n // docs:start:to_le_bits_example\n fn test_to_le_bits() {\n let field = 2;\n let bits: [bool; 8] = field.to_le_bits();\n assert_eq(bits, [false, true, false, false, false, false, false, false]);\n }\n // docs:end:to_le_bits_example\n\n #[test]\n // docs:start:to_be_bytes_example\n fn test_to_be_bytes() {\n let field = 2;\n let bytes: [u8; 8] = field.to_be_bytes();\n assert_eq(bytes, [0, 0, 0, 0, 0, 0, 0, 2]);\n assert_eq(Field::from_be_bytes::<8>(bytes), field);\n }\n // docs:end:to_be_bytes_example\n\n #[test]\n // docs:start:to_le_bytes_example\n fn test_to_le_bytes() {\n let field = 2;\n let bytes: [u8; 8] = field.to_le_bytes();\n assert_eq(bytes, [2, 0, 0, 0, 0, 0, 0, 0]);\n assert_eq(Field::from_le_bytes::<8>(bytes), field);\n }\n // docs:end:to_le_bytes_example\n\n #[test]\n // docs:start:to_be_radix_example\n fn test_to_be_radix() {\n // 259, in base 256, big endian, is [1, 3].\n // i.e. 3 * 256^0 + 1 * 256^1\n let field = 259;\n\n // The radix (in this example, 256) must be a power of 2.\n // The length of the returned byte array can be specified to be\n // >= the amount of space needed.\n let bytes: [u8; 8] = field.to_be_radix(256);\n assert_eq(bytes, [0, 0, 0, 0, 0, 0, 1, 3]);\n assert_eq(Field::from_be_bytes::<8>(bytes), field);\n }\n // docs:end:to_be_radix_example\n\n #[test]\n // docs:start:to_le_radix_example\n fn test_to_le_radix() {\n // 259, in base 256, little endian, is [3, 1].\n // i.e. 3 * 256^0 + 1 * 256^1\n let field = 259;\n\n // The radix (in this example, 256) must be a power of 2.\n // The length of the returned byte array can be specified to be\n // >= the amount of space needed.\n let bytes: [u8; 8] = field.to_le_radix(256);\n assert_eq(bytes, [3, 1, 0, 0, 0, 0, 0, 0]);\n assert_eq(Field::from_le_bytes::<8>(bytes), field);\n }\n // docs:end:to_le_radix_example\n\n #[test(should_fail_with = \"radix must be greater than 1\")]\n fn test_to_le_radix_1() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(1);\n } else {\n panic(\"radix must be greater than 1\");\n }\n }\n\n // Updated test to account for Brillig restriction that radix must be greater than 2\n #[test(should_fail_with = \"radix must be greater than 1\")]\n fn test_to_le_radix_brillig_1() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 1;\n let _: [u8; 8] = field.to_le_radix(1);\n } else {\n panic(\"radix must be greater than 1\");\n }\n }\n\n #[test(should_fail_with = \"radix must be a power of 2\")]\n fn test_to_le_radix_3() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(3);\n } else {\n panic(\"radix must be a power of 2\");\n }\n }\n\n #[test]\n fn test_to_le_radix_brillig_3() {\n // this test should only fail in constrained mode\n if runtime::is_unconstrained() {\n let field = 1;\n let out: [u8; 8] = field.to_le_radix(3);\n let mut expected = [0; 8];\n expected[0] = 1;\n assert(out == expected, \"unexpected result\");\n }\n }\n\n #[test(should_fail_with = \"radix must be less than or equal to 256\")]\n fn test_to_le_radix_512() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(512);\n } else {\n panic(\"radix must be less than or equal to 256\")\n }\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 16 limbs\")]\n unconstrained fn not_enough_limbs_brillig() {\n let _: [u8; 16] = 0x100000000000000000000000000000000.to_le_bytes();\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 16 limbs\")]\n fn not_enough_limbs() {\n let _: [u8; 16] = 0x100000000000000000000000000000000.to_le_bytes();\n }\n\n #[test]\n unconstrained fn test_field_less_than() {\n assert(field_less_than(0, 1));\n assert(field_less_than(0, 0x100));\n assert(field_less_than(0x100, 0 - 1));\n assert(!field_less_than(0 - 1, 0));\n }\n\n #[test]\n unconstrained fn test_large_field_values_unconstrained() {\n let large_field = 0xffffffffffffffff;\n\n let bits: [bool; 64] = large_field.to_le_bits();\n assert_eq(bits[0], true);\n\n let bytes: [u8; 8] = large_field.to_le_bytes();\n assert_eq(Field::from_le_bytes::<8>(bytes), large_field);\n\n let radix_bytes: [u8; 8] = large_field.to_le_radix(256);\n assert_eq(Field::from_le_bytes::<8>(radix_bytes), large_field);\n }\n\n #[test]\n fn test_large_field_values() {\n let large_val = 0xffffffffffffffff;\n\n let bits: [bool; 64] = large_val.to_le_bits();\n assert_eq(bits[0], true);\n\n let bytes: [u8; 8] = large_val.to_le_bytes();\n assert_eq(Field::from_le_bytes::<8>(bytes), large_val);\n\n let radix_bytes: [u8; 8] = large_val.to_le_radix(256);\n assert_eq(Field::from_le_bytes::<8>(radix_bytes), large_val);\n }\n\n #[test]\n fn test_decomposition_edge_cases() {\n let zero_bits: [bool; 8] = 0.to_le_bits();\n assert_eq(zero_bits, [false; 8]);\n\n let zero_bytes: [u8; 8] = 0.to_le_bytes();\n assert_eq(zero_bytes, [0; 8]);\n\n let one_bits: [bool; 8] = 1.to_le_bits();\n let expected: [bool; 8] = [true, false, false, false, false, false, false, false];\n assert_eq(one_bits, expected);\n\n let pow2_bits: [bool; 8] = 4.to_le_bits();\n let expected: [bool; 8] = [false, false, true, false, false, false, false, false];\n assert_eq(pow2_bits, expected);\n }\n\n #[test]\n fn test_pow_32() {\n assert_eq(2.pow_32(3), 8);\n assert_eq(3.pow_32(2), 9);\n assert_eq(5.pow_32(0), 1);\n assert_eq(7.pow_32(1), 7);\n\n assert_eq(2.pow_32(10), 1024);\n\n assert_eq(0.pow_32(5), 0);\n assert_eq(0.pow_32(0), 1);\n\n assert_eq(1.pow_32(100), 1);\n }\n\n #[test]\n fn test_sgn0() {\n assert_eq(0.sgn0(), false);\n assert_eq(2.sgn0(), false);\n assert_eq(4.sgn0(), false);\n assert_eq(100.sgn0(), false);\n\n assert_eq(1.sgn0(), true);\n assert_eq(3.sgn0(), true);\n assert_eq(5.sgn0(), true);\n assert_eq(101.sgn0(), true);\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 8 limbs\")]\n fn test_bit_decomposition_overflow() {\n // 8 bits can't represent large field values\n let large_val = 0x1000000000000000;\n let _: [bool; 8] = large_val.to_le_bits();\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 4 limbs\")]\n fn test_byte_decomposition_overflow() {\n // 4 bytes can't represent large field values\n let large_val = 0x1000000000000000;\n let _: [u8; 4] = large_val.to_le_bytes();\n }\n\n #[test]\n fn test_to_from_be_bytes_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this byte produces the expected 32 BE bytes for (modulus - 1)\n let mut p_minus_1_bytes: [u8; 32] = modulus_be_bytes().as_array();\n assert(p_minus_1_bytes[32 - 1] > 0);\n p_minus_1_bytes[32 - 1] -= 1;\n\n let p_minus_1 = Field::from_be_bytes::<32>(p_minus_1_bytes);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 32 BE bytes produces the same bytes\n let p_minus_1_converted_bytes: [u8; 32] = p_minus_1.to_be_bytes();\n assert_eq(p_minus_1_converted_bytes, p_minus_1_bytes);\n\n // checking that incrementing this byte produces 32 BE bytes for (modulus + 1)\n let mut p_plus_1_bytes: [u8; 32] = modulus_be_bytes().as_array();\n assert(p_plus_1_bytes[32 - 1] < 255);\n p_plus_1_bytes[32 - 1] += 1;\n\n let p_plus_1 = Field::from_be_bytes::<32>(p_plus_1_bytes);\n assert_eq(p_plus_1, 1);\n\n // checking that converting p_plus_1 to 32 BE bytes produces the same\n // byte set to 1 as p_plus_1_bytes and otherwise zeroes\n let mut p_plus_1_converted_bytes: [u8; 32] = p_plus_1.to_be_bytes();\n assert_eq(p_plus_1_converted_bytes[32 - 1], 1);\n p_plus_1_converted_bytes[32 - 1] = 0;\n assert_eq(p_plus_1_converted_bytes, [0; 32]);\n\n // checking that Field::from_be_bytes::<32> on the Field modulus produces 0\n assert_eq(modulus_be_bytes().len(), 32);\n let p = Field::from_be_bytes::<32>(modulus_be_bytes().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 32 BE bytes produces 32 zeroes\n let p_bytes: [u8; 32] = 0.to_be_bytes();\n assert_eq(p_bytes, [0; 32]);\n }\n }\n\n #[test]\n fn test_to_from_le_bytes_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this byte produces the expected 32 LE bytes for (modulus - 1)\n let mut p_minus_1_bytes: [u8; 32] = modulus_le_bytes().as_array();\n assert(p_minus_1_bytes[0] > 0);\n p_minus_1_bytes[0] -= 1;\n\n let p_minus_1 = Field::from_le_bytes::<32>(p_minus_1_bytes);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 32 BE bytes produces the same bytes\n let p_minus_1_converted_bytes: [u8; 32] = p_minus_1.to_le_bytes();\n assert_eq(p_minus_1_converted_bytes, p_minus_1_bytes);\n\n // checking that incrementing this byte produces 32 LE bytes for (modulus + 1)\n let mut p_plus_1_bytes: [u8; 32] = modulus_le_bytes().as_array();\n assert(p_plus_1_bytes[0] < 255);\n p_plus_1_bytes[0] += 1;\n\n let p_plus_1 = Field::from_le_bytes::<32>(p_plus_1_bytes);\n assert_eq(p_plus_1, 1);\n\n // checking that converting p_plus_1 to 32 LE bytes produces the same\n // byte set to 1 as p_plus_1_bytes and otherwise zeroes\n let mut p_plus_1_converted_bytes: [u8; 32] = p_plus_1.to_le_bytes();\n assert_eq(p_plus_1_converted_bytes[0], 1);\n p_plus_1_converted_bytes[0] = 0;\n assert_eq(p_plus_1_converted_bytes, [0; 32]);\n\n // checking that Field::from_le_bytes::<32> on the Field modulus produces 0\n assert_eq(modulus_le_bytes().len(), 32);\n let p = Field::from_le_bytes::<32>(modulus_le_bytes().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 32 LE bytes produces 32 zeroes\n let p_bytes: [u8; 32] = 0.to_le_bytes();\n assert_eq(p_bytes, [0; 32]);\n }\n }\n\n /// Convert a little endian bit array to a field element.\n /// If the provided bit array overflows the field modulus then the Field will silently wrap around.\n fn from_le_bits<let N: u32>(bits: [bool; N]) -> Field {\n static_assert(\n N <= modulus_le_bits().len(),\n \"N must be less than or equal to modulus_le_bits().len()\",\n );\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bits[i] as Field) * v;\n v = v * 2;\n }\n result\n }\n\n /// Convert a big endian bit array to a field element.\n /// If the provided bit array overflows the field modulus then the Field will silently wrap around.\n fn from_be_bits<let N: u32>(bits: [bool; N]) -> Field {\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bits[N - 1 - i] as Field) * v;\n v = v * 2;\n }\n result\n }\n\n #[test]\n fn test_to_from_be_bits_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this bit produces the expected 254 BE bits for (modulus - 1)\n let mut p_minus_1_bits: [bool; 254] = modulus_be_bits().as_array();\n assert(p_minus_1_bits[254 - 1]);\n p_minus_1_bits[254 - 1] = false;\n\n let p_minus_1 = from_be_bits::<254>(p_minus_1_bits);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 254 BE bits produces the same bits\n let p_minus_1_converted_bits: [bool; 254] = p_minus_1.to_be_bits();\n assert_eq(p_minus_1_converted_bits, p_minus_1_bits);\n\n // checking that incrementing this bit produces 254 BE bits for (modulus + 4)\n let mut p_plus_4_bits: [bool; 254] = modulus_be_bits().as_array();\n assert(!p_plus_4_bits[254 - 3]);\n p_plus_4_bits[254 - 3] = true;\n\n let p_plus_4 = from_be_bits::<254>(p_plus_4_bits);\n assert_eq(p_plus_4, 4);\n\n // checking that converting p_plus_4 to 254 BE bits produces the same\n // bit set to 1 as p_plus_4_bits and otherwise zeroes\n let mut p_plus_4_converted_bits: [bool; 254] = p_plus_4.to_be_bits();\n assert(p_plus_4_converted_bits[254 - 3]);\n p_plus_4_converted_bits[254 - 3] = false;\n assert_eq(p_plus_4_converted_bits, [false; 254]);\n\n // checking that Field::from_be_bits::<254> on the Field modulus produces 0\n assert_eq(modulus_be_bits().len(), 254);\n let p = from_be_bits::<254>(modulus_be_bits().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 254 BE bits produces 254 false values\n let p_bits: [bool; 254] = 0.to_be_bits();\n assert_eq(p_bits, [false; 254]);\n }\n }\n\n #[test]\n fn test_to_from_le_bits_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this bit produces the expected 254 LE bits for (modulus - 1)\n let mut p_minus_1_bits: [bool; 254] = modulus_le_bits().as_array();\n assert(p_minus_1_bits[0]);\n p_minus_1_bits[0] = false;\n\n let p_minus_1 = from_le_bits::<254>(p_minus_1_bits);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 254 BE bits produces the same bits\n let p_minus_1_converted_bits: [bool; 254] = p_minus_1.to_le_bits();\n assert_eq(p_minus_1_converted_bits, p_minus_1_bits);\n\n // checking that incrementing this bit produces 254 LE bits for (modulus + 4)\n let mut p_plus_4_bits: [bool; 254] = modulus_le_bits().as_array();\n assert(!p_plus_4_bits[2]);\n p_plus_4_bits[2] = true;\n\n let p_plus_4 = from_le_bits::<254>(p_plus_4_bits);\n assert_eq(p_plus_4, 4);\n\n // checking that converting p_plus_4 to 254 LE bits produces the same\n // bit set to 1 as p_plus_4_bits and otherwise zeroes\n let mut p_plus_4_converted_bits: [bool; 254] = p_plus_4.to_le_bits();\n assert(p_plus_4_converted_bits[2]);\n p_plus_4_converted_bits[2] = false;\n assert_eq(p_plus_4_converted_bits, [false; 254]);\n\n // checking that Field::from_le_bits::<254> on the Field modulus produces 0\n assert_eq(modulus_le_bits().len(), 254);\n let p = from_le_bits::<254>(modulus_le_bits().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 254 LE bits produces 254 false values\n let p_bits: [bool; 254] = 0.to_le_bits();\n assert_eq(p_bits, [false; 254]);\n }\n }\n\n #[test(should_fail_with = \"call to assert_max_bit_size\")]\n fn max_bit_size_too_large() {\n let x: Field = 0x010000;\n x.assert_max_bit_size::<16>();\n }\n\n}\n"
|
|
293
|
+
"source": "pub mod bn254;\nuse crate::{runtime::is_unconstrained, static_assert};\nuse bn254::lt as bn254_lt;\n\nimpl Field {\n /// Asserts that `self` can be represented in `bit_size` bits.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^{bit_size}`.\n // docs:start:assert_max_bit_size\n pub fn assert_max_bit_size<let BIT_SIZE: u32>(self) {\n // docs:end:assert_max_bit_size\n static_assert(\n BIT_SIZE < modulus_num_bits() as u32,\n \"BIT_SIZE must be less than modulus_num_bits\",\n );\n __assert_max_bit_size(self, BIT_SIZE);\n }\n\n /// Decomposes `self` into its little endian bit decomposition as a `[bool; N]` array.\n /// This array will be zero padded should not all bits be necessary to represent `self`.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting array will not\n /// be able to represent the original `Field`.\n ///\n /// # Safety\n /// The bit decomposition returned is canonical and is guaranteed to not overflow the modulus.\n // docs:start:to_le_bits\n pub fn to_le_bits<let N: u32>(self: Self) -> [bool; N] {\n // docs:end:to_le_bits\n let bits = __to_le_bits(self);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_le_bits();\n assert(bits.len() <= p.len());\n let mut ok = bits.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bits[N - 1 - i] != p[N - 1 - i]) {\n assert(p[N - 1 - i]);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bits\n }\n\n /// Decomposes `self` into its big endian bit decomposition as a `[bool; N]` array.\n /// This array will be zero padded should not all bits be necessary to represent `self`.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting array will not\n /// be able to represent the original `Field`.\n ///\n /// # Safety\n /// The bit decomposition returned is canonical and is guaranteed to not overflow the modulus.\n // docs:start:to_be_bits\n pub fn to_be_bits<let N: u32>(self: Self) -> [bool; N] {\n // docs:end:to_be_bits\n let bits = __to_be_bits(self);\n\n if !is_unconstrained() {\n // Ensure that the decomposition does not overflow the modulus\n let p = modulus_be_bits();\n assert(bits.len() <= p.len());\n let mut ok = bits.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bits[i] != p[i]) {\n assert(p[i]);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bits\n }\n\n /// Decomposes `self` into its little endian byte decomposition as a `[u8;N]` array\n /// This array will be zero padded should not all bytes be necessary to represent `self`.\n ///\n /// # Failures\n /// The length N of the array must be big enough to contain all the bytes of the 'self',\n /// and no more than the number of bytes required to represent the field modulus\n ///\n /// # Safety\n /// The result is ensured to be the canonical decomposition of the field element\n // docs:start:to_le_bytes\n pub fn to_le_bytes<let N: u32>(self: Self) -> [u8; N] {\n // docs:end:to_le_bytes\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n // Compute the byte decomposition\n let bytes = self.to_le_radix(256);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_le_bytes();\n assert(bytes.len() <= p.len());\n let mut ok = bytes.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bytes[N - 1 - i] != p[N - 1 - i]) {\n assert(bytes[N - 1 - i] < p[N - 1 - i]);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bytes\n }\n\n /// Decomposes `self` into its big endian byte decomposition as a `[u8;N]` array of length required to represent the field modulus\n /// This array will be zero padded should not all bytes be necessary to represent `self`.\n ///\n /// # Failures\n /// The length N of the array must be big enough to contain all the bytes of the 'self',\n /// and no more than the number of bytes required to represent the field modulus\n ///\n /// # Safety\n /// The result is ensured to be the canonical decomposition of the field element\n // docs:start:to_be_bytes\n pub fn to_be_bytes<let N: u32>(self: Self) -> [u8; N] {\n // docs:end:to_be_bytes\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n // Compute the byte decomposition\n let bytes = self.to_be_radix(256);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_be_bytes();\n assert(bytes.len() <= p.len());\n let mut ok = bytes.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bytes[i] != p[i]) {\n assert(bytes[i] < p[i]);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bytes\n }\n\n fn to_le_radix<let N: u32>(self: Self, radix: u32) -> [u8; N] {\n // Brillig does not need an immediate radix\n if !crate::runtime::is_unconstrained() {\n static_assert(1 < radix, \"radix must be greater than 1\");\n static_assert(radix <= 256, \"radix must be less than or equal to 256\");\n static_assert(radix & (radix - 1) == 0, \"radix must be a power of 2\");\n }\n __to_le_radix(self, radix)\n }\n\n fn to_be_radix<let N: u32>(self: Self, radix: u32) -> [u8; N] {\n // Brillig does not need an immediate radix\n if !crate::runtime::is_unconstrained() {\n static_assert(1 < radix, \"radix must be greater than 1\");\n static_assert(radix <= 256, \"radix must be less than or equal to 256\");\n static_assert(radix & (radix - 1) == 0, \"radix must be a power of 2\");\n }\n __to_be_radix(self, radix)\n }\n\n // Returns self to the power of the given exponent value.\n // Caution: we assume the exponent fits into 32 bits\n // using a bigger bit size impacts negatively the performance and should be done only if the exponent does not fit in 32 bits\n pub fn pow_32(self, exponent: Field) -> Field {\n let mut r: Field = 1;\n let b: [bool; 32] = exponent.to_le_bits();\n\n for i in 1..33 {\n r *= r;\n r = (b[32 - i] as Field) * (r * self) + (1 - b[32 - i] as Field) * r;\n }\n r\n }\n\n // Parity of (prime) Field element, i.e. sgn0(x mod p) = false if x `elem` {0, ..., p-1} is even, otherwise sgn0(x mod p) = true.\n pub fn sgn0(self) -> bool {\n (self as u8) % 2 == 1\n }\n\n pub fn lt(self, another: Field) -> bool {\n if crate::compat::is_bn254() {\n bn254_lt(self, another)\n } else {\n lt_fallback(self, another)\n }\n }\n\n /// Convert a little endian byte array to a field element.\n /// If the provided byte array overflows the field modulus then the Field will silently wrap around.\n ///\n /// # Failures\n /// `N` must be no greater than the number of bytes required to represent the field modulus\n // docs:start:from_le_bytes\n pub fn from_le_bytes<let N: u32>(bytes: [u8; N]) -> Field {\n // docs:end:from_le_bytes\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bytes[i] as Field) * v;\n v = v * 256;\n }\n result\n }\n\n /// Convert a big endian byte array to a field element.\n /// If the provided byte array overflows the field modulus then the Field will silently wrap around.\n ///\n /// # Failures\n /// `N` must be no greater than the number of bytes required to represent the field modulus\n // docs:start:from_be_bytes\n pub fn from_be_bytes<let N: u32>(bytes: [u8; N]) -> Field {\n // docs:end:from_be_bytes\n static_assert(\n N <= modulus_be_bytes().len(),\n \"N must be less than or equal to modulus_be_bytes().len()\",\n );\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bytes[N - 1 - i] as Field) * v;\n v = v * 256;\n }\n result\n }\n\n /// Convert a little endian byte array to a field element, asserting that the input is a\n /// canonical representation (strictly less than the field modulus).\n ///\n /// # Failures\n /// Causes a constraint failure if `bytes` encodes a value greater than or equal to the\n /// field modulus.\n // docs:start:from_le_bytes_checked\n pub fn from_le_bytes_checked<let N: u32>(bytes: [u8; N]) -> Field {\n // docs:end:from_le_bytes_checked\n let p = modulus_le_bytes();\n let mut ok = N != p.len();\n for i in 0..N {\n if !ok {\n if bytes[N - 1 - i] != p[N - 1 - i] {\n assert(\n bytes[N - 1 - i] < p[N - 1 - i],\n \"input bytes are not a canonical field representation\",\n );\n ok = true;\n }\n }\n }\n assert(ok, \"input bytes are not a canonical field representation\");\n Field::from_le_bytes(bytes)\n }\n\n /// Convert a big endian byte array to a field element, asserting that the input is a\n /// canonical representation (strictly less than the field modulus).\n ///\n /// # Failures\n /// Causes a constraint failure if `bytes` encodes a value greater than or equal to the\n /// field modulus.\n // docs:start:from_be_bytes_checked\n pub fn from_be_bytes_checked<let N: u32>(bytes: [u8; N]) -> Field {\n // docs:end:from_be_bytes_checked\n let p = modulus_be_bytes();\n let mut ok = N != p.len();\n for i in 0..N {\n if !ok {\n if bytes[i] != p[i] {\n assert(bytes[i] < p[i], \"input bytes are not a canonical field representation\");\n ok = true;\n }\n }\n }\n assert(ok, \"input bytes are not a canonical field representation\");\n Field::from_be_bytes(bytes)\n }\n}\n\n#[builtin(apply_range_constraint)]\nfn __assert_max_bit_size(value: Field, bit_size: u32) {}\n\n// `_radix` must be less than 256\n#[builtin(to_le_radix)]\nfn __to_le_radix<let N: u32>(value: Field, radix: u32) -> [u8; N] {}\n\n// `_radix` must be less than 256\n#[builtin(to_be_radix)]\nfn __to_be_radix<let N: u32>(value: Field, radix: u32) -> [u8; N] {}\n\n/// Decomposes `self` into its little endian bit decomposition as a `[bool; N]` array.\n/// This array will be zero padded should not all bits be necessary to represent `self`.\n///\n/// # Failures\n/// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting array will not\n/// be able to represent the original `Field`.\n///\n/// # Safety\n/// Values of `N` equal to or greater than the number of bits necessary to represent the `Field` modulus\n/// (e.g. 254 for the BN254 field) allow for multiple bit decompositions. This is due to how the `Field` will\n/// wrap around due to overflow when verifying the decomposition.\n#[builtin(to_le_bits)]\nfn __to_le_bits<let N: u32>(value: Field) -> [bool; N] {}\n\n/// Decomposes `self` into its big endian bit decomposition as a `[bool; N]` array.\n/// This array will be zero padded should not all bits be necessary to represent `self`.\n///\n/// # Failures\n/// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting array will not\n/// be able to represent the original `Field`.\n///\n/// # Safety\n/// Values of `N` equal to or greater than the number of bits necessary to represent the `Field` modulus\n/// (e.g. 254 for the BN254 field) allow for multiple bit decompositions. This is due to how the `Field` will\n/// wrap around due to overflow when verifying the decomposition.\n#[builtin(to_be_bits)]\nfn __to_be_bits<let N: u32>(value: Field) -> [bool; N] {}\n\n#[builtin(modulus_num_bits)]\npub comptime fn modulus_num_bits() -> u64 {}\n\n#[builtin(modulus_be_bits)]\npub comptime fn modulus_be_bits() -> [bool] {}\n\n#[builtin(modulus_le_bits)]\npub comptime fn modulus_le_bits() -> [bool] {}\n\n#[builtin(modulus_be_bytes)]\npub comptime fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub comptime fn modulus_le_bytes() -> [u8] {}\n\n/// An unconstrained only built in to efficiently compare fields.\n#[builtin(field_less_than)]\nunconstrained fn __field_less_than(x: Field, y: Field) -> bool {}\n\npub(crate) unconstrained fn field_less_than(x: Field, y: Field) -> bool {\n __field_less_than(x, y)\n}\n\nfn lt_fallback(x: Field, y: Field) -> bool {\n if is_unconstrained() {\n // Safety: unconstrained context\n unsafe {\n field_less_than(x, y)\n }\n } else {\n let x_bytes: [u8; 32] = x.to_le_bytes();\n let y_bytes: [u8; 32] = y.to_le_bytes();\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..32 {\n if (!done) {\n let x_byte = x_bytes[32 - 1 - i] as u8;\n let y_byte = y_bytes[32 - 1 - i] as u8;\n let bytes_match = x_byte == y_byte;\n if !bytes_match {\n x_is_lt = x_byte < y_byte;\n done = true;\n }\n }\n }\n x_is_lt\n }\n}\n\nmod tests {\n use crate::{panic::panic, runtime, static_assert};\n use super::{\n field_less_than, modulus_be_bits, modulus_be_bytes, modulus_le_bits, modulus_le_bytes,\n };\n\n #[test]\n // docs:start:to_be_bits_example\n fn test_to_be_bits() {\n let field = 2;\n let bits: [bool; 8] = field.to_be_bits();\n assert_eq(bits, [false, false, false, false, false, false, true, false]);\n }\n // docs:end:to_be_bits_example\n\n #[test]\n // docs:start:to_le_bits_example\n fn test_to_le_bits() {\n let field = 2;\n let bits: [bool; 8] = field.to_le_bits();\n assert_eq(bits, [false, true, false, false, false, false, false, false]);\n }\n // docs:end:to_le_bits_example\n\n #[test]\n // docs:start:to_be_bytes_example\n fn test_to_be_bytes() {\n let field = 2;\n let bytes: [u8; 8] = field.to_be_bytes();\n assert_eq(bytes, [0, 0, 0, 0, 0, 0, 0, 2]);\n assert_eq(Field::from_be_bytes::<8>(bytes), field);\n }\n // docs:end:to_be_bytes_example\n\n #[test]\n // docs:start:to_le_bytes_example\n fn test_to_le_bytes() {\n let field = 2;\n let bytes: [u8; 8] = field.to_le_bytes();\n assert_eq(bytes, [2, 0, 0, 0, 0, 0, 0, 0]);\n assert_eq(Field::from_le_bytes::<8>(bytes), field);\n }\n // docs:end:to_le_bytes_example\n\n #[test]\n // docs:start:to_be_radix_example\n fn test_to_be_radix() {\n // 259, in base 256, big endian, is [1, 3].\n // i.e. 3 * 256^0 + 1 * 256^1\n let field = 259;\n\n // The radix (in this example, 256) must be a power of 2.\n // The length of the returned byte array can be specified to be\n // >= the amount of space needed.\n let bytes: [u8; 8] = field.to_be_radix(256);\n assert_eq(bytes, [0, 0, 0, 0, 0, 0, 1, 3]);\n assert_eq(Field::from_be_bytes::<8>(bytes), field);\n }\n // docs:end:to_be_radix_example\n\n #[test]\n // docs:start:to_le_radix_example\n fn test_to_le_radix() {\n // 259, in base 256, little endian, is [3, 1].\n // i.e. 3 * 256^0 + 1 * 256^1\n let field = 259;\n\n // The radix (in this example, 256) must be a power of 2.\n // The length of the returned byte array can be specified to be\n // >= the amount of space needed.\n let bytes: [u8; 8] = field.to_le_radix(256);\n assert_eq(bytes, [3, 1, 0, 0, 0, 0, 0, 0]);\n assert_eq(Field::from_le_bytes::<8>(bytes), field);\n }\n // docs:end:to_le_radix_example\n\n #[test(should_fail_with = \"radix must be greater than 1\")]\n fn test_to_le_radix_1() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(1);\n } else {\n panic(\"radix must be greater than 1\");\n }\n }\n\n // Updated test to account for Brillig restriction that radix must be greater than 2\n #[test(should_fail_with = \"radix must be greater than 1\")]\n fn test_to_le_radix_brillig_1() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 1;\n let _: [u8; 8] = field.to_le_radix(1);\n } else {\n panic(\"radix must be greater than 1\");\n }\n }\n\n #[test(should_fail_with = \"radix must be a power of 2\")]\n fn test_to_le_radix_3() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(3);\n } else {\n panic(\"radix must be a power of 2\");\n }\n }\n\n #[test]\n fn test_to_le_radix_brillig_3() {\n // this test should only fail in constrained mode\n if runtime::is_unconstrained() {\n let field = 1;\n let out: [u8; 8] = field.to_le_radix(3);\n let mut expected = [0; 8];\n expected[0] = 1;\n assert(out == expected, \"unexpected result\");\n }\n }\n\n #[test(should_fail_with = \"radix must be less than or equal to 256\")]\n fn test_to_le_radix_512() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(512);\n } else {\n panic(\"radix must be less than or equal to 256\")\n }\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 16 limbs\")]\n unconstrained fn not_enough_limbs_brillig() {\n let _: [u8; 16] = 0x100000000000000000000000000000000.to_le_bytes();\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 16 limbs\")]\n fn not_enough_limbs() {\n let _: [u8; 16] = 0x100000000000000000000000000000000.to_le_bytes();\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 0 limbs\")]\n unconstrained fn non_zero_field_to_le_bytes_zero_limbs() {\n let _: [u8; 0] = 5.to_le_bytes();\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 0 limbs\")]\n unconstrained fn non_zero_field_to_be_bytes_zero_limbs() {\n let _: [u8; 0] = 5.to_be_bytes();\n }\n\n #[test]\n unconstrained fn zero_field_to_bytes_zero_limbs_unconstrained() {\n assert_eq((0 as Field).to_le_bytes::<0>().len(), 0);\n assert_eq((0 as Field).to_be_bytes::<0>().len(), 0);\n assert_eq((0 as Field).to_le_bits::<0>().len(), 0);\n assert_eq((0 as Field).to_be_bits::<0>().len(), 0);\n }\n\n #[test]\n fn zero_field_to_bytes_zero_limbs_constrained() {\n assert_eq((0 as Field).to_le_bytes::<0>().len(), 0);\n assert_eq((0 as Field).to_be_bytes::<0>().len(), 0);\n assert_eq((0 as Field).to_le_bits::<0>().len(), 0);\n assert_eq((0 as Field).to_be_bits::<0>().len(), 0);\n }\n\n #[test]\n fn zero_field_to_bytes_zero_limbs_comptime() {\n let _: [u8; 0] = comptime { (0 as Field).to_le_bytes() };\n let _: [u8; 0] = comptime { (0 as Field).to_be_bytes() };\n let _: [bool; 0] = comptime { (0 as Field).to_le_bits() };\n let _: [bool; 0] = comptime { (0 as Field).to_be_bits() };\n }\n\n #[test]\n unconstrained fn test_field_less_than() {\n assert(field_less_than(0, 1));\n assert(field_less_than(0, 0x100));\n assert(field_less_than(0x100, 0 - 1));\n assert(!field_less_than(0 - 1, 0));\n }\n\n #[test]\n unconstrained fn test_large_field_values_unconstrained() {\n let large_field = 0xffffffffffffffff;\n\n let bits: [bool; 64] = large_field.to_le_bits();\n assert_eq(bits[0], true);\n\n let bytes: [u8; 8] = large_field.to_le_bytes();\n assert_eq(Field::from_le_bytes::<8>(bytes), large_field);\n\n let radix_bytes: [u8; 8] = large_field.to_le_radix(256);\n assert_eq(Field::from_le_bytes::<8>(radix_bytes), large_field);\n }\n\n #[test]\n fn test_large_field_values() {\n let large_val = 0xffffffffffffffff;\n\n let bits: [bool; 64] = large_val.to_le_bits();\n assert_eq(bits[0], true);\n\n let bytes: [u8; 8] = large_val.to_le_bytes();\n assert_eq(Field::from_le_bytes::<8>(bytes), large_val);\n\n let radix_bytes: [u8; 8] = large_val.to_le_radix(256);\n assert_eq(Field::from_le_bytes::<8>(radix_bytes), large_val);\n }\n\n #[test]\n fn test_decomposition_edge_cases() {\n let zero_bits: [bool; 8] = 0.to_le_bits();\n assert_eq(zero_bits, [false; 8]);\n\n let zero_bytes: [u8; 8] = 0.to_le_bytes();\n assert_eq(zero_bytes, [0; 8]);\n\n let one_bits: [bool; 8] = 1.to_le_bits();\n let expected: [bool; 8] = [true, false, false, false, false, false, false, false];\n assert_eq(one_bits, expected);\n\n let pow2_bits: [bool; 8] = 4.to_le_bits();\n let expected: [bool; 8] = [false, false, true, false, false, false, false, false];\n assert_eq(pow2_bits, expected);\n }\n\n #[test]\n fn test_pow_32() {\n assert_eq(2.pow_32(3), 8);\n assert_eq(3.pow_32(2), 9);\n assert_eq(5.pow_32(0), 1);\n assert_eq(7.pow_32(1), 7);\n\n assert_eq(2.pow_32(10), 1024);\n\n assert_eq(0.pow_32(5), 0);\n assert_eq(0.pow_32(0), 1);\n\n assert_eq(1.pow_32(100), 1);\n }\n\n #[test]\n fn test_sgn0() {\n assert_eq(0.sgn0(), false);\n assert_eq(2.sgn0(), false);\n assert_eq(4.sgn0(), false);\n assert_eq(100.sgn0(), false);\n\n assert_eq(1.sgn0(), true);\n assert_eq(3.sgn0(), true);\n assert_eq(5.sgn0(), true);\n assert_eq(101.sgn0(), true);\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 8 limbs\")]\n fn test_bit_decomposition_overflow() {\n // 8 bits can't represent large field values\n let large_val = 0x1000000000000000;\n let _: [bool; 8] = large_val.to_le_bits();\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 4 limbs\")]\n fn test_byte_decomposition_overflow() {\n // 4 bytes can't represent large field values\n let large_val = 0x1000000000000000;\n let _: [u8; 4] = large_val.to_le_bytes();\n }\n\n #[test]\n fn test_to_from_be_bytes_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this byte produces the expected 32 BE bytes for (modulus - 1)\n let mut p_minus_1_bytes: [u8; 32] = modulus_be_bytes().as_array();\n assert(p_minus_1_bytes[32 - 1] > 0);\n p_minus_1_bytes[32 - 1] -= 1;\n\n let p_minus_1 = Field::from_be_bytes::<32>(p_minus_1_bytes);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 32 BE bytes produces the same bytes\n let p_minus_1_converted_bytes: [u8; 32] = p_minus_1.to_be_bytes();\n assert_eq(p_minus_1_converted_bytes, p_minus_1_bytes);\n\n // checking that incrementing this byte produces 32 BE bytes for (modulus + 1)\n let mut p_plus_1_bytes: [u8; 32] = modulus_be_bytes().as_array();\n assert(p_plus_1_bytes[32 - 1] < 255);\n p_plus_1_bytes[32 - 1] += 1;\n\n let p_plus_1 = Field::from_be_bytes::<32>(p_plus_1_bytes);\n assert_eq(p_plus_1, 1);\n\n // checking that converting p_plus_1 to 32 BE bytes produces the same\n // byte set to 1 as p_plus_1_bytes and otherwise zeroes\n let mut p_plus_1_converted_bytes: [u8; 32] = p_plus_1.to_be_bytes();\n assert_eq(p_plus_1_converted_bytes[32 - 1], 1);\n p_plus_1_converted_bytes[32 - 1] = 0;\n assert_eq(p_plus_1_converted_bytes, [0; 32]);\n\n // checking that Field::from_be_bytes::<32> on the Field modulus produces 0\n assert_eq(modulus_be_bytes().len(), 32);\n let p = Field::from_be_bytes::<32>(modulus_be_bytes().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 32 BE bytes produces 32 zeroes\n let p_bytes: [u8; 32] = 0.to_be_bytes();\n assert_eq(p_bytes, [0; 32]);\n }\n }\n\n #[test]\n fn test_to_from_le_bytes_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this byte produces the expected 32 LE bytes for (modulus - 1)\n let mut p_minus_1_bytes: [u8; 32] = modulus_le_bytes().as_array();\n assert(p_minus_1_bytes[0] > 0);\n p_minus_1_bytes[0] -= 1;\n\n let p_minus_1 = Field::from_le_bytes::<32>(p_minus_1_bytes);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 32 BE bytes produces the same bytes\n let p_minus_1_converted_bytes: [u8; 32] = p_minus_1.to_le_bytes();\n assert_eq(p_minus_1_converted_bytes, p_minus_1_bytes);\n\n // checking that incrementing this byte produces 32 LE bytes for (modulus + 1)\n let mut p_plus_1_bytes: [u8; 32] = modulus_le_bytes().as_array();\n assert(p_plus_1_bytes[0] < 255);\n p_plus_1_bytes[0] += 1;\n\n let p_plus_1 = Field::from_le_bytes::<32>(p_plus_1_bytes);\n assert_eq(p_plus_1, 1);\n\n // checking that converting p_plus_1 to 32 LE bytes produces the same\n // byte set to 1 as p_plus_1_bytes and otherwise zeroes\n let mut p_plus_1_converted_bytes: [u8; 32] = p_plus_1.to_le_bytes();\n assert_eq(p_plus_1_converted_bytes[0], 1);\n p_plus_1_converted_bytes[0] = 0;\n assert_eq(p_plus_1_converted_bytes, [0; 32]);\n\n // checking that Field::from_le_bytes::<32> on the Field modulus produces 0\n assert_eq(modulus_le_bytes().len(), 32);\n let p = Field::from_le_bytes::<32>(modulus_le_bytes().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 32 LE bytes produces 32 zeroes\n let p_bytes: [u8; 32] = 0.to_le_bytes();\n assert_eq(p_bytes, [0; 32]);\n }\n }\n\n #[test]\n fn test_from_le_bytes_checked_accepts_modulus_minus_one() {\n if crate::compat::is_bn254() {\n let mut p_minus_1_bytes: [u8; 32] = modulus_le_bytes().as_array();\n assert(p_minus_1_bytes[0] > 0);\n p_minus_1_bytes[0] -= 1;\n let p_minus_1 = Field::from_le_bytes_checked::<32>(p_minus_1_bytes);\n assert_eq(p_minus_1 + 1, 0);\n }\n }\n\n #[test(should_fail_with = \"input bytes are not a canonical field representation\")]\n fn test_from_le_bytes_checked_rejects_modulus() {\n if crate::compat::is_bn254() {\n let _ = Field::from_le_bytes_checked::<32>(modulus_le_bytes().as_array());\n } else {\n panic(\"input bytes are not a canonical field representation\");\n }\n }\n\n #[test(should_fail_with = \"input bytes are not a canonical field representation\")]\n fn test_from_le_bytes_checked_rejects_modulus_plus_one() {\n if crate::compat::is_bn254() {\n let mut p_plus_1_bytes: [u8; 32] = modulus_le_bytes().as_array();\n assert(p_plus_1_bytes[0] < 255);\n p_plus_1_bytes[0] += 1;\n let _ = Field::from_le_bytes_checked::<32>(p_plus_1_bytes);\n } else {\n panic(\"input bytes are not a canonical field representation\");\n }\n }\n\n #[test]\n fn test_from_be_bytes_checked_accepts_modulus_minus_one() {\n if crate::compat::is_bn254() {\n let mut p_minus_1_bytes: [u8; 32] = modulus_be_bytes().as_array();\n assert(p_minus_1_bytes[32 - 1] > 0);\n p_minus_1_bytes[32 - 1] -= 1;\n let p_minus_1 = Field::from_be_bytes_checked::<32>(p_minus_1_bytes);\n assert_eq(p_minus_1 + 1, 0);\n }\n }\n\n #[test(should_fail_with = \"input bytes are not a canonical field representation\")]\n fn test_from_be_bytes_checked_rejects_modulus() {\n if crate::compat::is_bn254() {\n let _ = Field::from_be_bytes_checked::<32>(modulus_be_bytes().as_array());\n } else {\n panic(\"input bytes are not a canonical field representation\");\n }\n }\n\n #[test(should_fail_with = \"input bytes are not a canonical field representation\")]\n fn test_from_be_bytes_checked_rejects_modulus_plus_one() {\n if crate::compat::is_bn254() {\n let mut p_plus_1_bytes: [u8; 32] = modulus_be_bytes().as_array();\n assert(p_plus_1_bytes[32 - 1] < 255);\n p_plus_1_bytes[32 - 1] += 1;\n let _ = Field::from_be_bytes_checked::<32>(p_plus_1_bytes);\n } else {\n panic(\"input bytes are not a canonical field representation\");\n }\n }\n\n #[test]\n fn test_from_bytes_checked_small_n() {\n // For N < modulus_bytes().len(), the input cannot overflow the modulus, so the checked\n // variants behave identically to the unchecked ones.\n let le_bytes: [u8; 8] = [3, 1, 0, 0, 0, 0, 0, 0];\n assert_eq(Field::from_le_bytes_checked::<8>(le_bytes), 259);\n let be_bytes: [u8; 8] = [0, 0, 0, 0, 0, 0, 1, 3];\n assert_eq(Field::from_be_bytes_checked::<8>(be_bytes), 259);\n }\n\n /// Convert a little endian bit array to a field element.\n /// If the provided bit array overflows the field modulus then the Field will silently wrap around.\n fn from_le_bits<let N: u32>(bits: [bool; N]) -> Field {\n static_assert(\n N <= modulus_le_bits().len(),\n \"N must be less than or equal to modulus_le_bits().len()\",\n );\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bits[i] as Field) * v;\n v = v * 2;\n }\n result\n }\n\n /// Convert a big endian bit array to a field element.\n /// If the provided bit array overflows the field modulus then the Field will silently wrap around.\n fn from_be_bits<let N: u32>(bits: [bool; N]) -> Field {\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bits[N - 1 - i] as Field) * v;\n v = v * 2;\n }\n result\n }\n\n #[test]\n fn test_to_from_be_bits_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this bit produces the expected 254 BE bits for (modulus - 1)\n let mut p_minus_1_bits: [bool; 254] = modulus_be_bits().as_array();\n assert(p_minus_1_bits[254 - 1]);\n p_minus_1_bits[254 - 1] = false;\n\n let p_minus_1 = from_be_bits::<254>(p_minus_1_bits);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 254 BE bits produces the same bits\n let p_minus_1_converted_bits: [bool; 254] = p_minus_1.to_be_bits();\n assert_eq(p_minus_1_converted_bits, p_minus_1_bits);\n\n // checking that incrementing this bit produces 254 BE bits for (modulus + 4)\n let mut p_plus_4_bits: [bool; 254] = modulus_be_bits().as_array();\n assert(!p_plus_4_bits[254 - 3]);\n p_plus_4_bits[254 - 3] = true;\n\n let p_plus_4 = from_be_bits::<254>(p_plus_4_bits);\n assert_eq(p_plus_4, 4);\n\n // checking that converting p_plus_4 to 254 BE bits produces the same\n // bit set to 1 as p_plus_4_bits and otherwise zeroes\n let mut p_plus_4_converted_bits: [bool; 254] = p_plus_4.to_be_bits();\n assert(p_plus_4_converted_bits[254 - 3]);\n p_plus_4_converted_bits[254 - 3] = false;\n assert_eq(p_plus_4_converted_bits, [false; 254]);\n\n // checking that Field::from_be_bits::<254> on the Field modulus produces 0\n assert_eq(modulus_be_bits().len(), 254);\n let p = from_be_bits::<254>(modulus_be_bits().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 254 BE bits produces 254 false values\n let p_bits: [bool; 254] = 0.to_be_bits();\n assert_eq(p_bits, [false; 254]);\n }\n }\n\n #[test]\n fn test_to_from_le_bits_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this bit produces the expected 254 LE bits for (modulus - 1)\n let mut p_minus_1_bits: [bool; 254] = modulus_le_bits().as_array();\n assert(p_minus_1_bits[0]);\n p_minus_1_bits[0] = false;\n\n let p_minus_1 = from_le_bits::<254>(p_minus_1_bits);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 254 BE bits produces the same bits\n let p_minus_1_converted_bits: [bool; 254] = p_minus_1.to_le_bits();\n assert_eq(p_minus_1_converted_bits, p_minus_1_bits);\n\n // checking that incrementing this bit produces 254 LE bits for (modulus + 4)\n let mut p_plus_4_bits: [bool; 254] = modulus_le_bits().as_array();\n assert(!p_plus_4_bits[2]);\n p_plus_4_bits[2] = true;\n\n let p_plus_4 = from_le_bits::<254>(p_plus_4_bits);\n assert_eq(p_plus_4, 4);\n\n // checking that converting p_plus_4 to 254 LE bits produces the same\n // bit set to 1 as p_plus_4_bits and otherwise zeroes\n let mut p_plus_4_converted_bits: [bool; 254] = p_plus_4.to_le_bits();\n assert(p_plus_4_converted_bits[2]);\n p_plus_4_converted_bits[2] = false;\n assert_eq(p_plus_4_converted_bits, [false; 254]);\n\n // checking that Field::from_le_bits::<254> on the Field modulus produces 0\n assert_eq(modulus_le_bits().len(), 254);\n let p = from_le_bits::<254>(modulus_le_bits().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 254 LE bits produces 254 false values\n let p_bits: [bool; 254] = 0.to_le_bits();\n assert_eq(p_bits, [false; 254]);\n }\n }\n\n #[test(should_fail_with = \"call to assert_max_bit_size\")]\n fn max_bit_size_too_large() {\n let x: Field = 0x010000;\n x.assert_max_bit_size::<16>();\n }\n\n}\n"
|
|
238
294
|
},
|
|
239
295
|
"17": {
|
|
240
296
|
"function_locations": [
|
|
@@ -246,149 +302,181 @@
|
|
|
246
302
|
"name": "keccakf1600",
|
|
247
303
|
"start": 707
|
|
248
304
|
},
|
|
249
|
-
{
|
|
250
|
-
"name": "keccak::keccakf1600",
|
|
251
|
-
"start": 882
|
|
252
|
-
},
|
|
253
305
|
{
|
|
254
306
|
"name": "blake2s",
|
|
255
|
-
"start":
|
|
307
|
+
"start": 852
|
|
256
308
|
},
|
|
257
309
|
{
|
|
258
310
|
"name": "blake3",
|
|
259
|
-
"start":
|
|
311
|
+
"start": 950
|
|
260
312
|
},
|
|
261
313
|
{
|
|
262
314
|
"name": "__blake3",
|
|
263
|
-
"start":
|
|
315
|
+
"start": 1437
|
|
264
316
|
},
|
|
265
317
|
{
|
|
266
318
|
"name": "pedersen_commitment",
|
|
267
|
-
"start":
|
|
319
|
+
"start": 1555
|
|
268
320
|
},
|
|
269
321
|
{
|
|
270
322
|
"name": "pedersen_commitment_with_separator",
|
|
271
|
-
"start":
|
|
323
|
+
"start": 1784
|
|
272
324
|
},
|
|
273
325
|
{
|
|
274
326
|
"name": "pedersen_hash",
|
|
275
|
-
"start":
|
|
327
|
+
"start": 2188
|
|
276
328
|
},
|
|
277
329
|
{
|
|
278
330
|
"name": "pedersen_hash_with_separator",
|
|
279
|
-
"start":
|
|
331
|
+
"start": 2345
|
|
280
332
|
},
|
|
281
333
|
{
|
|
282
334
|
"name": "derive_generators",
|
|
283
|
-
"start":
|
|
335
|
+
"start": 3339
|
|
284
336
|
},
|
|
285
337
|
{
|
|
286
338
|
"name": "__derive_generators",
|
|
287
|
-
"start":
|
|
339
|
+
"start": 3698
|
|
288
340
|
},
|
|
289
341
|
{
|
|
290
342
|
"name": "poseidon2_permutation",
|
|
291
|
-
"start":
|
|
343
|
+
"start": 3776
|
|
292
344
|
},
|
|
293
345
|
{
|
|
294
346
|
"name": "poseidon2_permutation_internal",
|
|
295
|
-
"start":
|
|
347
|
+
"start": 4132
|
|
296
348
|
},
|
|
297
349
|
{
|
|
298
350
|
"name": "poseidon2_config_state_size",
|
|
299
|
-
"start":
|
|
351
|
+
"start": 4225
|
|
300
352
|
},
|
|
301
353
|
{
|
|
302
354
|
"name": "derive_hash",
|
|
303
|
-
"start":
|
|
355
|
+
"start": 4536
|
|
356
|
+
},
|
|
357
|
+
{
|
|
358
|
+
"name": "Hasher::finish_ref",
|
|
359
|
+
"start": 5327
|
|
304
360
|
},
|
|
305
361
|
{
|
|
306
362
|
"name": "<impl BuildHasher for BuildHasherDefault<H>>::build_hasher",
|
|
307
|
-
"start":
|
|
363
|
+
"start": 5761
|
|
308
364
|
},
|
|
309
365
|
{
|
|
310
366
|
"name": "<impl Default for BuildHasherDefault<H>>::default",
|
|
311
|
-
"start":
|
|
367
|
+
"start": 5893
|
|
312
368
|
},
|
|
313
369
|
{
|
|
314
370
|
"name": "<impl Hash for Field>::hash",
|
|
315
|
-
"start":
|
|
371
|
+
"start": 6025
|
|
316
372
|
},
|
|
317
373
|
{
|
|
318
374
|
"name": "<impl Hash for u8>::hash",
|
|
319
|
-
"start":
|
|
375
|
+
"start": 6155
|
|
320
376
|
},
|
|
321
377
|
{
|
|
322
378
|
"name": "<impl Hash for u16>::hash",
|
|
323
|
-
"start":
|
|
379
|
+
"start": 6295
|
|
324
380
|
},
|
|
325
381
|
{
|
|
326
382
|
"name": "<impl Hash for u32>::hash",
|
|
327
|
-
"start":
|
|
383
|
+
"start": 6435
|
|
328
384
|
},
|
|
329
385
|
{
|
|
330
386
|
"name": "<impl Hash for u64>::hash",
|
|
331
|
-
"start":
|
|
387
|
+
"start": 6575
|
|
332
388
|
},
|
|
333
389
|
{
|
|
334
390
|
"name": "<impl Hash for u128>::hash",
|
|
335
|
-
"start":
|
|
391
|
+
"start": 6716
|
|
336
392
|
},
|
|
337
393
|
{
|
|
338
394
|
"name": "<impl Hash for i8>::hash",
|
|
339
|
-
"start":
|
|
395
|
+
"start": 6855
|
|
340
396
|
},
|
|
341
397
|
{
|
|
342
398
|
"name": "<impl Hash for i16>::hash",
|
|
343
|
-
"start":
|
|
399
|
+
"start": 7001
|
|
344
400
|
},
|
|
345
401
|
{
|
|
346
402
|
"name": "<impl Hash for i32>::hash",
|
|
347
|
-
"start":
|
|
403
|
+
"start": 7148
|
|
348
404
|
},
|
|
349
405
|
{
|
|
350
406
|
"name": "<impl Hash for i64>::hash",
|
|
351
|
-
"start":
|
|
407
|
+
"start": 7295
|
|
352
408
|
},
|
|
353
409
|
{
|
|
354
410
|
"name": "<impl Hash for bool>::hash",
|
|
355
|
-
"start":
|
|
411
|
+
"start": 7443
|
|
356
412
|
},
|
|
357
413
|
{
|
|
358
414
|
"name": "<impl Hash for ()>::hash",
|
|
359
|
-
"start":
|
|
415
|
+
"start": 7590
|
|
360
416
|
},
|
|
361
417
|
{
|
|
362
418
|
"name": "<impl Hash for [T; N]>::hash",
|
|
363
|
-
"start":
|
|
419
|
+
"start": 7722
|
|
364
420
|
},
|
|
365
421
|
{
|
|
366
422
|
"name": "<impl Hash for [T]>::hash",
|
|
367
|
-
"start":
|
|
423
|
+
"start": 7911
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
"name": "<impl Hash for (A,)>::hash",
|
|
427
|
+
"start": 8133
|
|
368
428
|
},
|
|
369
429
|
{
|
|
370
430
|
"name": "<impl Hash for (A, B)>::hash",
|
|
371
|
-
"start":
|
|
431
|
+
"start": 8302
|
|
372
432
|
},
|
|
373
433
|
{
|
|
374
434
|
"name": "<impl Hash for (A, B, C)>::hash",
|
|
375
|
-
"start":
|
|
435
|
+
"start": 8518
|
|
376
436
|
},
|
|
377
437
|
{
|
|
378
438
|
"name": "<impl Hash for (A, B, C, D)>::hash",
|
|
379
|
-
"start":
|
|
439
|
+
"start": 8781
|
|
380
440
|
},
|
|
381
441
|
{
|
|
382
442
|
"name": "<impl Hash for (A, B, C, D, E)>::hash",
|
|
383
|
-
"start":
|
|
443
|
+
"start": 9091
|
|
444
|
+
},
|
|
445
|
+
{
|
|
446
|
+
"name": "<impl Hash for (A, B, C, D, E, F)>::hash",
|
|
447
|
+
"start": 9448
|
|
448
|
+
},
|
|
449
|
+
{
|
|
450
|
+
"name": "<impl Hash for (A, B, C, D, E, F, G)>::hash",
|
|
451
|
+
"start": 9852
|
|
452
|
+
},
|
|
453
|
+
{
|
|
454
|
+
"name": "<impl Hash for (A, B, C, D, E, F, G, H_)>::hash",
|
|
455
|
+
"start": 10306
|
|
456
|
+
},
|
|
457
|
+
{
|
|
458
|
+
"name": "<impl Hash for (A, B, C, D, E, F, G, H_, I)>::hash",
|
|
459
|
+
"start": 10807
|
|
460
|
+
},
|
|
461
|
+
{
|
|
462
|
+
"name": "<impl Hash for (A, B, C, D, E, F, G, H_, I, J)>::hash",
|
|
463
|
+
"start": 11355
|
|
464
|
+
},
|
|
465
|
+
{
|
|
466
|
+
"name": "<impl Hash for (A, B, C, D, E, F, G, H_, I, J, K)>::hash",
|
|
467
|
+
"start": 11950
|
|
468
|
+
},
|
|
469
|
+
{
|
|
470
|
+
"name": "<impl Hash for (A, B, C, D, E, F, G, H_, I, J, K, L)>::hash",
|
|
471
|
+
"start": 12593
|
|
384
472
|
},
|
|
385
473
|
{
|
|
386
474
|
"name": "assert_pedersen",
|
|
387
|
-
"start":
|
|
475
|
+
"start": 13187
|
|
388
476
|
}
|
|
389
477
|
],
|
|
390
478
|
"path": "std/hash/mod.nr",
|
|
391
|
-
"source": "// Exposed only for usage in `std::meta`\npub(crate) mod poseidon2;\n\nuse crate::default::Default;\nuse crate::embedded_curve_ops::{\n EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul, multi_scalar_mul_array_return,\n};\nuse crate::meta::derive_via;\nuse crate::static_assert;\n\n/// The size of the state accepted by the backend in `poseidon2_permutation`.\nglobal POSEIDON2_CONFIG_STATE_SIZE: u32 = poseidon2_config_state_size();\n\n#[foreign(sha256_compression)]\n// docs:start:sha256_compression\npub fn sha256_compression(input: [u32; 16], state: [u32; 8]) -> [u32; 8] {}\n// docs:end:sha256_compression\n\n#[foreign(keccakf1600)]\n// docs:start:keccakf1600\npub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {}\n// docs:end:keccakf1600\n\npub mod keccak {\n #[deprecated(\"This function has been moved to std::hash::keccakf1600\")]\n pub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {\n super::keccakf1600(input)\n }\n}\n\n#[foreign(blake2s)]\n// docs:start:blake2s\npub fn blake2s<let N: u32>(input: [u8; N]) -> [u8; 32]\n// docs:end:blake2s\n{}\n\n// docs:start:blake3\npub fn blake3<let N: u32>(input: [u8; N]) -> [u8; 32]\n// docs:end:blake3\n{\n if crate::runtime::is_unconstrained() {\n // Temporary measure while Barretenberg is main proving system.\n // Please open an issue if you're working on another proving system and running into problems due to this.\n crate::static_assert(\n N <= 1024,\n \"Barretenberg cannot prove blake3 hashes with inputs larger than 1024 bytes\",\n );\n }\n __blake3(input)\n}\n\n#[foreign(blake3)]\nfn __blake3<let N: u32>(input: [u8; N]) -> [u8; 32] {}\n\n// docs:start:pedersen_commitment\npub fn pedersen_commitment<let N: u32>(input: [Field; N]) -> EmbeddedCurvePoint {\n // docs:end:pedersen_commitment\n pedersen_commitment_with_separator(input, 0)\n}\n\n#[inline_always]\npub fn pedersen_commitment_with_separator<let N: u32>(\n input: [Field; N],\n separator: u32,\n) -> EmbeddedCurvePoint {\n let mut points = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N];\n for i in 0..N {\n points[i] = EmbeddedCurveScalar::from_field(input[i]);\n }\n let generators = derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n multi_scalar_mul(generators, points)\n}\n\n// docs:start:pedersen_hash\npub fn pedersen_hash<let N: u32>(input: [Field; N]) -> Field\n// docs:end:pedersen_hash\n{\n pedersen_hash_with_separator(input, 0)\n}\n\n#[no_predicates]\npub fn pedersen_hash_with_separator<let N: u32>(input: [Field; N], separator: u32) -> Field {\n let mut scalars: [EmbeddedCurveScalar; N + 1] = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N + 1];\n let mut generators: [EmbeddedCurvePoint; N + 1] =\n [EmbeddedCurvePoint::point_at_infinity(); N + 1];\n crate::assert_constant(separator);\n let domain_generators: [EmbeddedCurvePoint; N] =\n derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n\n for i in 0..N {\n scalars[i] = EmbeddedCurveScalar::from_field(input[i]);\n generators[i] = domain_generators[i];\n }\n scalars[N] = EmbeddedCurveScalar { lo: N as Field, hi: 0 as Field };\n\n let length_generator: [EmbeddedCurvePoint; 1] =\n derive_generators(\"pedersen_hash_length\".as_bytes(), 0);\n generators[N] = length_generator[0];\n multi_scalar_mul_array_return(generators, scalars, true)[0].x\n}\n\n#[field(bn254)]\n#[inline_always]\npub fn derive_generators<let N: u32, let M: u32>(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {\n crate::assert_constant(domain_separator_bytes);\n crate::assert_constant(starting_index);\n __derive_generators(domain_separator_bytes, starting_index)\n}\n\n#[builtin(derive_pedersen_generators)]\n#[field(bn254)]\nfn __derive_generators<let N: u32, let M: u32>(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {}\n\npub fn poseidon2_permutation<let N: u32>(input: [Field; N]) -> [Field; N] {\n static_assert(\n N == POSEIDON2_CONFIG_STATE_SIZE,\n f\"the input length must equal the state size in the Poseidon2 config; expected {POSEIDON2_CONFIG_STATE_SIZE}, got {N}\",\n );\n poseidon2_permutation_internal(input)\n}\n\n#[foreign(poseidon2_permutation)]\nfn poseidon2_permutation_internal<let N: u32>(input: [Field; N]) -> [Field; N] {}\n\n#[foreign(poseidon2_config_state_size)]\ncomptime fn poseidon2_config_state_size() -> u32 {}\n\n// Generic hashing support.\n// Partially ported and impacted by rust.\n\n// Hash trait shall be implemented per type.\n#[derive_via(derive_hash)]\npub trait Hash {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher;\n}\n\n// docs:start:derive_hash\ncomptime fn derive_hash(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::hash::Hash };\n let signature = quote { fn hash<H>(_self: Self, _state: &mut H) where H: $crate::hash::Hasher };\n let for_each_field = |name| quote { _self.$name.hash(_state); };\n crate::meta::make_trait_impl(\n s,\n name,\n signature,\n for_each_field,\n quote {},\n |fields| fields,\n )\n}\n// docs:end:derive_hash\n\n// Hasher trait shall be implemented by algorithms to provide hash-agnostic means.\n// TODO: consider making the types generic here ([u8], [Field], etc.)\npub trait Hasher {\n fn finish(self) -> Field;\n\n /// Returns the hash value without consuming the hasher.\n /// Override this for more efficient implementations that avoid copying.\n /// TODO: deprecate finish() and replace it\n fn finish_ref(&self) -> Field {\n (*self).finish()\n }\n\n fn write(&mut self, input: Field);\n}\n\n// BuildHasher is a factory trait, responsible for production of specific Hasher.\npub trait BuildHasher {\n type H: Hasher;\n\n fn build_hasher(self) -> H;\n}\n\npub struct BuildHasherDefault<H>;\n\nimpl<H> BuildHasher for BuildHasherDefault<H>\nwhere\n H: Hasher + Default,\n{\n type H = H;\n\n fn build_hasher(_self: Self) -> H {\n H::default()\n }\n}\n\nimpl<H> Default for BuildHasherDefault<H>\nwhere\n H: Hasher + Default,\n{\n fn default() -> Self {\n BuildHasherDefault {}\n }\n}\n\nimpl Hash for Field {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self);\n }\n}\n\nimpl Hash for u8 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u16 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u32 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u64 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u128 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i8 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u8 as Field);\n }\n}\n\nimpl Hash for i16 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u16 as Field);\n }\n}\n\nimpl Hash for i32 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u32 as Field);\n }\n}\n\nimpl Hash for i64 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u64 as Field);\n }\n}\n\nimpl Hash for bool {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for () {\n fn hash<H>(_self: Self, _state: &mut H)\n where\n H: Hasher,\n {}\n}\n\nimpl<T, let N: u32> Hash for [T; N]\nwhere\n T: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl<T> Hash for [T]\nwhere\n T: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.len().hash(state);\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl<A, B> Hash for (A, B)\nwhere\n A: Hash,\n B: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n }\n}\n\nimpl<A, B, C> Hash for (A, B, C)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n }\n}\n\nimpl<A, B, C, D> Hash for (A, B, C, D)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n }\n}\n\nimpl<A, B, C, D, E> Hash for (A, B, C, D, E)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n E: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n }\n}\n\n// Some test vectors for Pedersen hash and Pedersen Commitment.\n// They have been generated using the same functions so the tests are for now useless\n// but they will be useful when we switch to Noir implementation.\n#[test]\nfn assert_pedersen() {\n assert_eq(\n pedersen_hash_with_separator([1], 1),\n 0x1b3f4b1a83092a13d8d1a59f7acb62aba15e7002f4440f2275edb99ebbc2305f,\n );\n assert_eq(\n pedersen_commitment_with_separator([1], 1),\n EmbeddedCurvePoint {\n x: 0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402,\n y: 0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126,\n },\n );\n\n assert_eq(\n pedersen_hash_with_separator([1, 2], 2),\n 0x26691c129448e9ace0c66d11f0a16d9014a9e8498ee78f4d69f0083168188255,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2], 2),\n EmbeddedCurvePoint {\n x: 0x2e2b3b191e49541fe468ec6877721d445dcaffe41728df0a0eafeb15e87b0753,\n y: 0x2ff4482400ad3a6228be17a2af33e2bcdf41be04795f9782bd96efe7e24f8778,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3], 3),\n 0x0bc694b7a1f8d10d2d8987d07433f26bd616a2d351bc79a3c540d85b6206dbe4,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3], 3),\n EmbeddedCurvePoint {\n x: 0x1fee4e8cf8d2f527caa2684236b07c4b1bad7342c01b0f75e9a877a71827dc85,\n y: 0x2f9fedb9a090697ab69bf04c8bc15f7385b3e4b68c849c1536e5ae15ff138fd1,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4], 4),\n 0xdae10fb32a8408521803905981a2b300d6a35e40e798743e9322b223a5eddc,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4], 4),\n EmbeddedCurvePoint {\n x: 0x07ae3e202811e1fca39c2d81eabe6f79183978e6f12be0d3b8eda095b79bdbc9,\n y: 0x0afc6f892593db6fbba60f2da558517e279e0ae04f95758587760ba193145014,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5], 5),\n 0xfc375b062c4f4f0150f7100dfb8d9b72a6d28582dd9512390b0497cdad9c22,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5], 5),\n EmbeddedCurvePoint {\n x: 0x1754b12bd475a6984a1094b5109eeca9838f4f81ac89c5f0a41dbce53189bb29,\n y: 0x2da030e3cfcdc7ddad80eaf2599df6692cae0717d4e9f7bfbee8d073d5d278f7,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6], 6),\n 0x1696ed13dc2730062a98ac9d8f9de0661bb98829c7582f699d0273b18c86a572,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6], 6),\n EmbeddedCurvePoint {\n x: 0x190f6c0e97ad83e1e28da22a98aae156da083c5a4100e929b77e750d3106a697,\n y: 0x1f4b60f34ef91221a0b49756fa0705da93311a61af73d37a0c458877706616fb,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n 0x128c0ff144fc66b6cb60eeac8a38e23da52992fc427b92397a7dffd71c45ede3,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n EmbeddedCurvePoint {\n x: 0x015441e9d29491b06563fac16fc76abf7a9534c715421d0de85d20dbe2965939,\n y: 0x1d2575b0276f4e9087e6e07c2cb75aa1baafad127af4be5918ef8a2ef2fea8fc,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n 0x2f960e117482044dfc99d12fece2ef6862fba9242be4846c7c9a3e854325a55c,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n EmbeddedCurvePoint {\n x: 0x1657737676968887fceb6dd516382ea13b3a2c557f509811cd86d5d1199bc443,\n y: 0x1f39f0cb569040105fa1e2f156521e8b8e08261e635a2b210bdc94e8d6d65f77,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n 0x0c96db0790602dcb166cc4699e2d306c479a76926b81c2cb2aaa92d249ec7be7,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n EmbeddedCurvePoint {\n x: 0x0a3ceae42d14914a432aa60ec7fded4af7dad7dd4acdbf2908452675ec67e06d,\n y: 0xfc19761eaaf621ad4aec9a8b2e84a4eceffdba78f60f8b9391b0bd9345a2f2,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n 0x2cd37505871bc460a62ea1e63c7fe51149df5d0801302cf1cbc48beb8dff7e94,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n EmbeddedCurvePoint {\n x: 0x2fb3f8b3d41ddde007c8c3c62550f9a9380ee546fcc639ffbb3fd30c8d8de30c,\n y: 0x300783be23c446b11a4c0fabf6c91af148937cea15fcf5fb054abf7f752ee245,\n },\n );\n}\n"
|
|
479
|
+
"source": "// Exposed only for usage in `std::meta`\npub(crate) mod poseidon2;\n\nuse crate::default::Default;\nuse crate::embedded_curve_ops::{\n EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul, multi_scalar_mul_array_return,\n};\nuse crate::meta::derive_via;\nuse crate::static_assert;\n\n/// The size of the state accepted by the backend in `poseidon2_permutation`.\nglobal POSEIDON2_CONFIG_STATE_SIZE: u32 = poseidon2_config_state_size();\n\n#[foreign(sha256_compression)]\n// docs:start:sha256_compression\npub fn sha256_compression(input: [u32; 16], state: [u32; 8]) -> [u32; 8] {}\n// docs:end:sha256_compression\n\n#[foreign(keccakf1600)]\n// docs:start:keccakf1600\npub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {}\n// docs:end:keccakf1600\n\n#[foreign(blake2s)]\n// docs:start:blake2s\npub fn blake2s<let N: u32>(input: [u8; N]) -> [u8; 32]\n// docs:end:blake2s\n{}\n\n// docs:start:blake3\npub fn blake3<let N: u32>(input: [u8; N]) -> [u8; 32]\n// docs:end:blake3\n{\n if crate::runtime::is_unconstrained() {\n // Temporary measure while Barretenberg is main proving system.\n // Please open an issue if you're working on another proving system and running into problems due to this.\n crate::static_assert(\n N <= 1024,\n \"Barretenberg cannot prove blake3 hashes with inputs larger than 1024 bytes\",\n );\n }\n __blake3(input)\n}\n\n#[foreign(blake3)]\nfn __blake3<let N: u32>(input: [u8; N]) -> [u8; 32] {}\n\n// docs:start:pedersen_commitment\npub fn pedersen_commitment<let N: u32>(input: [Field; N]) -> EmbeddedCurvePoint {\n // docs:end:pedersen_commitment\n pedersen_commitment_with_separator(input, 0)\n}\n\n#[inline_always]\npub fn pedersen_commitment_with_separator<let N: u32>(\n input: [Field; N],\n separator: u32,\n) -> EmbeddedCurvePoint {\n let mut points = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N];\n for i in 0..N {\n points[i] = EmbeddedCurveScalar::from_field(input[i]);\n }\n let generators = derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n multi_scalar_mul(generators, points)\n}\n\n// docs:start:pedersen_hash\npub fn pedersen_hash<let N: u32>(input: [Field; N]) -> Field\n// docs:end:pedersen_hash\n{\n pedersen_hash_with_separator(input, 0)\n}\n\n#[no_predicates]\npub fn pedersen_hash_with_separator<let N: u32>(input: [Field; N], separator: u32) -> Field {\n let mut scalars: [EmbeddedCurveScalar; N + 1] = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N + 1];\n let mut generators: [EmbeddedCurvePoint; N + 1] =\n [EmbeddedCurvePoint::point_at_infinity(); N + 1];\n crate::assert_constant(separator);\n let domain_generators: [EmbeddedCurvePoint; N] =\n derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n\n for i in 0..N {\n scalars[i] = EmbeddedCurveScalar::from_field(input[i]);\n generators[i] = domain_generators[i];\n }\n scalars[N] = EmbeddedCurveScalar { lo: N as Field, hi: 0 as Field };\n\n let length_generator: [EmbeddedCurvePoint; 1] =\n derive_generators(\"pedersen_hash_length\".as_bytes(), 0);\n generators[N] = length_generator[0];\n multi_scalar_mul_array_return(generators, scalars, true)[0].x\n}\n\n#[field(bn254)]\n#[inline_always]\npub fn derive_generators<let N: u32, let M: u32>(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {\n crate::assert_constant(domain_separator_bytes);\n crate::assert_constant(starting_index);\n __derive_generators(domain_separator_bytes, starting_index)\n}\n\n#[builtin(derive_pedersen_generators)]\n#[field(bn254)]\nfn __derive_generators<let N: u32, let M: u32>(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {}\n\npub fn poseidon2_permutation<let N: u32>(input: [Field; N]) -> [Field; N] {\n static_assert(\n N == POSEIDON2_CONFIG_STATE_SIZE,\n f\"the input length must equal the state size in the Poseidon2 config; expected {POSEIDON2_CONFIG_STATE_SIZE}, got {N}\",\n );\n poseidon2_permutation_internal(input)\n}\n\n#[foreign(poseidon2_permutation)]\nfn poseidon2_permutation_internal<let N: u32>(input: [Field; N]) -> [Field; N] {}\n\n#[foreign(poseidon2_config_state_size)]\ncomptime fn poseidon2_config_state_size() -> u32 {}\n\n// Generic hashing support.\n// Partially ported and impacted by rust.\n\n// Hash trait shall be implemented per type.\n#[derive_via(derive_hash)]\npub trait Hash {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher;\n}\n\n// docs:start:derive_hash\ncomptime fn derive_hash(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::hash::Hash };\n let signature = quote { fn hash<H>(_self: Self, _state: &mut H) where H: $crate::hash::Hasher };\n let for_each_field = |name| quote { _self.$name.hash(_state); };\n crate::meta::make_trait_impl(\n s,\n name,\n signature,\n for_each_field,\n quote {},\n |fields| fields,\n )\n}\n// docs:end:derive_hash\n\n// Hasher trait shall be implemented by algorithms to provide hash-agnostic means.\n// TODO: consider making the types generic here ([u8], [Field], etc.)\npub trait Hasher {\n fn finish(self) -> Field;\n\n /// Returns the hash value without consuming the hasher.\n /// Override this for more efficient implementations that avoid copying.\n /// TODO: deprecate finish() and replace it\n fn finish_ref(&self) -> Field {\n (*self).finish()\n }\n\n fn write(&mut self, input: Field);\n}\n\n// BuildHasher is a factory trait, responsible for production of specific Hasher.\npub trait BuildHasher {\n type H: Hasher;\n\n fn build_hasher(self) -> H;\n}\n\npub struct BuildHasherDefault<H>;\n\nimpl<H> BuildHasher for BuildHasherDefault<H>\nwhere\n H: Hasher + Default,\n{\n type H = H;\n\n fn build_hasher(_self: Self) -> H {\n H::default()\n }\n}\n\nimpl<H> Default for BuildHasherDefault<H>\nwhere\n H: Hasher + Default,\n{\n fn default() -> Self {\n BuildHasherDefault {}\n }\n}\n\nimpl Hash for Field {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self);\n }\n}\n\nimpl Hash for u8 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u16 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u32 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u64 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u128 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i8 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u8 as Field);\n }\n}\n\nimpl Hash for i16 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u16 as Field);\n }\n}\n\nimpl Hash for i32 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u32 as Field);\n }\n}\n\nimpl Hash for i64 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u64 as Field);\n }\n}\n\nimpl Hash for bool {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for () {\n fn hash<H>(_self: Self, _state: &mut H)\n where\n H: Hasher,\n {}\n}\n\nimpl<T, let N: u32> Hash for [T; N]\nwhere\n T: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl<T> Hash for [T]\nwhere\n T: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.len().hash(state);\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl<A> Hash for (A,)\nwhere\n A: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n }\n}\n\nimpl<A, B> Hash for (A, B)\nwhere\n A: Hash,\n B: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n }\n}\n\nimpl<A, B, C> Hash for (A, B, C)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n }\n}\n\nimpl<A, B, C, D> Hash for (A, B, C, D)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n }\n}\n\nimpl<A, B, C, D, E> Hash for (A, B, C, D, E)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n E: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n }\n}\n\nimpl<A, B, C, D, E, F> Hash for (A, B, C, D, E, F)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n E: Hash,\n F: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n self.5.hash(state);\n }\n}\n\nimpl<A, B, C, D, E, F, G> Hash for (A, B, C, D, E, F, G)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n E: Hash,\n F: Hash,\n G: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n self.5.hash(state);\n self.6.hash(state);\n }\n}\n\nimpl<A, B, C, D, E, F, G, H_> Hash for (A, B, C, D, E, F, G, H_)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n E: Hash,\n F: Hash,\n G: Hash,\n H_: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n self.5.hash(state);\n self.6.hash(state);\n self.7.hash(state);\n }\n}\n\nimpl<A, B, C, D, E, F, G, H_, I> Hash for (A, B, C, D, E, F, G, H_, I)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n E: Hash,\n F: Hash,\n G: Hash,\n H_: Hash,\n I: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n self.5.hash(state);\n self.6.hash(state);\n self.7.hash(state);\n self.8.hash(state);\n }\n}\n\nimpl<A, B, C, D, E, F, G, H_, I, J> Hash for (A, B, C, D, E, F, G, H_, I, J)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n E: Hash,\n F: Hash,\n G: Hash,\n H_: Hash,\n I: Hash,\n J: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n self.5.hash(state);\n self.6.hash(state);\n self.7.hash(state);\n self.8.hash(state);\n self.9.hash(state);\n }\n}\n\nimpl<A, B, C, D, E, F, G, H_, I, J, K> Hash for (A, B, C, D, E, F, G, H_, I, J, K)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n E: Hash,\n F: Hash,\n G: Hash,\n H_: Hash,\n I: Hash,\n J: Hash,\n K: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n self.5.hash(state);\n self.6.hash(state);\n self.7.hash(state);\n self.8.hash(state);\n self.9.hash(state);\n self.10.hash(state);\n }\n}\n\nimpl<A, B, C, D, E, F, G, H_, I, J, K, L> Hash for (A, B, C, D, E, F, G, H_, I, J, K, L)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n E: Hash,\n F: Hash,\n G: Hash,\n H_: Hash,\n I: Hash,\n J: Hash,\n K: Hash,\n L: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n self.5.hash(state);\n self.6.hash(state);\n self.7.hash(state);\n self.8.hash(state);\n self.9.hash(state);\n self.10.hash(state);\n self.11.hash(state);\n }\n}\n\n// Some test vectors for Pedersen hash and Pedersen Commitment.\n// They have been generated using the same functions so the tests are for now useless\n// but they will be useful when we switch to Noir implementation.\n#[test]\nfn assert_pedersen() {\n assert_eq(\n pedersen_hash_with_separator([1], 1),\n 0x1b3f4b1a83092a13d8d1a59f7acb62aba15e7002f4440f2275edb99ebbc2305f,\n );\n assert_eq(\n pedersen_commitment_with_separator([1], 1),\n EmbeddedCurvePoint {\n x: 0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402,\n y: 0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126,\n },\n );\n\n assert_eq(\n pedersen_hash_with_separator([1, 2], 2),\n 0x26691c129448e9ace0c66d11f0a16d9014a9e8498ee78f4d69f0083168188255,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2], 2),\n EmbeddedCurvePoint {\n x: 0x2e2b3b191e49541fe468ec6877721d445dcaffe41728df0a0eafeb15e87b0753,\n y: 0x2ff4482400ad3a6228be17a2af33e2bcdf41be04795f9782bd96efe7e24f8778,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3], 3),\n 0x0bc694b7a1f8d10d2d8987d07433f26bd616a2d351bc79a3c540d85b6206dbe4,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3], 3),\n EmbeddedCurvePoint {\n x: 0x1fee4e8cf8d2f527caa2684236b07c4b1bad7342c01b0f75e9a877a71827dc85,\n y: 0x2f9fedb9a090697ab69bf04c8bc15f7385b3e4b68c849c1536e5ae15ff138fd1,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4], 4),\n 0xdae10fb32a8408521803905981a2b300d6a35e40e798743e9322b223a5eddc,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4], 4),\n EmbeddedCurvePoint {\n x: 0x07ae3e202811e1fca39c2d81eabe6f79183978e6f12be0d3b8eda095b79bdbc9,\n y: 0x0afc6f892593db6fbba60f2da558517e279e0ae04f95758587760ba193145014,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5], 5),\n 0xfc375b062c4f4f0150f7100dfb8d9b72a6d28582dd9512390b0497cdad9c22,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5], 5),\n EmbeddedCurvePoint {\n x: 0x1754b12bd475a6984a1094b5109eeca9838f4f81ac89c5f0a41dbce53189bb29,\n y: 0x2da030e3cfcdc7ddad80eaf2599df6692cae0717d4e9f7bfbee8d073d5d278f7,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6], 6),\n 0x1696ed13dc2730062a98ac9d8f9de0661bb98829c7582f699d0273b18c86a572,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6], 6),\n EmbeddedCurvePoint {\n x: 0x190f6c0e97ad83e1e28da22a98aae156da083c5a4100e929b77e750d3106a697,\n y: 0x1f4b60f34ef91221a0b49756fa0705da93311a61af73d37a0c458877706616fb,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n 0x128c0ff144fc66b6cb60eeac8a38e23da52992fc427b92397a7dffd71c45ede3,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n EmbeddedCurvePoint {\n x: 0x015441e9d29491b06563fac16fc76abf7a9534c715421d0de85d20dbe2965939,\n y: 0x1d2575b0276f4e9087e6e07c2cb75aa1baafad127af4be5918ef8a2ef2fea8fc,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n 0x2f960e117482044dfc99d12fece2ef6862fba9242be4846c7c9a3e854325a55c,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n EmbeddedCurvePoint {\n x: 0x1657737676968887fceb6dd516382ea13b3a2c557f509811cd86d5d1199bc443,\n y: 0x1f39f0cb569040105fa1e2f156521e8b8e08261e635a2b210bdc94e8d6d65f77,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n 0x0c96db0790602dcb166cc4699e2d306c479a76926b81c2cb2aaa92d249ec7be7,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n EmbeddedCurvePoint {\n x: 0x0a3ceae42d14914a432aa60ec7fded4af7dad7dd4acdbf2908452675ec67e06d,\n y: 0xfc19761eaaf621ad4aec9a8b2e84a4eceffdba78f60f8b9391b0bd9345a2f2,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n 0x2cd37505871bc460a62ea1e63c7fe51149df5d0801302cf1cbc48beb8dff7e94,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n EmbeddedCurvePoint {\n x: 0x2fb3f8b3d41ddde007c8c3c62550f9a9380ee546fcc639ffbb3fd30c8d8de30c,\n y: 0x300783be23c446b11a4c0fabf6c91af148937cea15fcf5fb054abf7f752ee245,\n },\n );\n}\n"
|
|
392
480
|
},
|
|
393
481
|
"180": {
|
|
394
482
|
"function_locations": [
|
|
@@ -540,39 +628,55 @@
|
|
|
540
628
|
},
|
|
541
629
|
{
|
|
542
630
|
"name": "<impl Empty for MerkleTree<N>>::empty",
|
|
543
|
-
"start":
|
|
631
|
+
"start": 2148
|
|
544
632
|
},
|
|
545
633
|
{
|
|
546
634
|
"name": "MerkleTree<N>::new",
|
|
547
|
-
"start":
|
|
635
|
+
"start": 2292
|
|
548
636
|
},
|
|
549
637
|
{
|
|
550
638
|
"name": "MerkleTree<N>::new_with_hasher",
|
|
551
|
-
"start":
|
|
639
|
+
"start": 2496
|
|
552
640
|
},
|
|
553
641
|
{
|
|
554
642
|
"name": "MerkleTree<N>::new_sha",
|
|
555
|
-
"start":
|
|
643
|
+
"start": 2652
|
|
556
644
|
},
|
|
557
645
|
{
|
|
558
646
|
"name": "MerkleTree<N>::get_root",
|
|
559
|
-
"start":
|
|
647
|
+
"start": 2805
|
|
560
648
|
},
|
|
561
649
|
{
|
|
562
650
|
"name": "MerkleTree<N>::get_sibling_path",
|
|
563
|
-
"start":
|
|
651
|
+
"start": 2917
|
|
564
652
|
},
|
|
565
653
|
{
|
|
566
654
|
"name": "sibling_index",
|
|
567
|
-
"start":
|
|
655
|
+
"start": 3654
|
|
568
656
|
},
|
|
569
657
|
{
|
|
570
658
|
"name": "compute_merkle_tree_nodes",
|
|
571
|
-
"start":
|
|
659
|
+
"start": 4832
|
|
660
|
+
},
|
|
661
|
+
{
|
|
662
|
+
"name": "tests::add_hasher",
|
|
663
|
+
"start": 5667
|
|
664
|
+
},
|
|
665
|
+
{
|
|
666
|
+
"name": "tests::leaves_and_internal_nodes_share_one_hasher",
|
|
667
|
+
"start": 5761
|
|
668
|
+
},
|
|
669
|
+
{
|
|
670
|
+
"name": "tests::internal_node_value_hashes_identically_as_a_leaf",
|
|
671
|
+
"start": 6024
|
|
672
|
+
},
|
|
673
|
+
{
|
|
674
|
+
"name": "tests::merkle_tree_root_is_last_node",
|
|
675
|
+
"start": 6512
|
|
572
676
|
}
|
|
573
677
|
],
|
|
574
678
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/merkle_tree.nr",
|
|
575
|
-
"source": "use crate::{\n constants::{\n DOM_SEP__MERKLE_HASH, DOM_SEP__NULLIFIER_MERKLE, DOM_SEP__PUBLIC_DATA_MERKLE,\n DOM_SEP__RETRIEVED_BYTECODES_MERKLE, DOM_SEP__WRITTEN_SLOTS_MERKLE,\n },\n hash::{accumulate_sha256, poseidon2_hash_with_separator},\n traits::Empty,\n utils::math::is_power_of_2_u32,\n};\n\n/// Merkle-node hash used by append-only trees.\npub fn merkle_hash(left: Field, right: Field) -> Field {\n poseidon2_hash_with_separator([left, right], DOM_SEP__MERKLE_HASH)\n}\n\n/// Merkle-node hash for the nullifier tree's sibling paths.\npub fn nullifier_merkle_hash(left: Field, right: Field) -> Field {\n poseidon2_hash_with_separator([left, right], DOM_SEP__NULLIFIER_MERKLE)\n}\n\n/// Merkle-node hash for the public-data tree's sibling paths.\npub fn public_data_merkle_hash(left: Field, right: Field) -> Field {\n poseidon2_hash_with_separator([left, right], DOM_SEP__PUBLIC_DATA_MERKLE)\n}\n\n/// Merkle-node hash for the AVM-internal written-public-data-slots tree's sibling paths.\npub fn written_slots_merkle_hash(left: Field, right: Field) -> Field {\n poseidon2_hash_with_separator([left, right], DOM_SEP__WRITTEN_SLOTS_MERKLE)\n}\n\n/// Merkle-node hash for the AVM-internal retrieved-bytecodes (class-id) tree's sibling paths.\npub fn retrieved_bytecodes_merkle_hash(left: Field, right: Field) -> Field {\n poseidon2_hash_with_separator([left, right], DOM_SEP__RETRIEVED_BYTECODES_MERKLE)\n}\n\npub fn sha_merkle_hash(left: Field, right: Field) -> Field {\n accumulate_sha256(left, right)\n}\n\n#[derive(Eq)]\npub struct MerkleTree<let N: u32> {\n pub leaves: [Field; N],\n pub nodes: [Field; N - 1],\n}\n\nimpl<let N: u32> Empty for MerkleTree<N> {\n fn empty() -> Self {\n MerkleTree { leaves: [0; N], nodes: [0; N - 1] }\n }\n}\n\nimpl<let N: u32> MerkleTree<N> {\n pub fn new(leaves: [Field; N]) -> Self {\n let nodes = compute_merkle_tree_nodes(leaves, merkle_hash);\n MerkleTree { leaves, nodes }\n }\n\n pub fn new_with_hasher(leaves: [Field; N], hasher: fn(Field, Field) -> Field) -> Self {\n let nodes = compute_merkle_tree_nodes(leaves, hasher);\n MerkleTree { leaves, nodes }\n }\n\n pub fn new_sha(leaves: [Field; N]) -> Self {\n let nodes = compute_merkle_tree_nodes(leaves, sha_merkle_hash);\n MerkleTree { leaves, nodes }\n }\n\n pub fn get_root(self) -> Field {\n self.nodes[N - 2]\n }\n\n pub fn get_sibling_path<let K: u32>(self, leaf_index: u32) -> [Field; K] {\n assert_eq(2.pow_32(K as Field), N as Field, \"Invalid path length\");\n\n let mut path = [0; K];\n let mut current_index = leaf_index;\n let mut subtree_width = N;\n\n let mut current_sibling_index = sibling_index(current_index);\n\n path[0] = self.leaves[current_sibling_index];\n\n let mut subtree_offset: u32 = 0;\n\n for i in 1..K {\n current_index = current_index / 2;\n subtree_width = subtree_width / 2;\n\n current_sibling_index = sibling_index(current_index);\n\n path[i] = self.nodes[subtree_offset + current_sibling_index];\n\n subtree_offset += subtree_width;\n }\n\n path\n }\n}\n\npub fn sibling_index(index: u32) -> u32 {\n if index % 2 == 0 {\n index + 1\n } else {\n index - 1\n }\n}\n\npub fn compute_merkle_tree_nodes<let N: u32>(\n leaves: [Field; N],\n hasher: fn(Field, Field) -> Field,\n) -> [Field; N - 1] {\n // Note: `N` must be a power of 2.\n std::static_assert(is_power_of_2_u32(N), \"N must be a power of 2\");\n std::static_assert(N != 1, \"2 must divide N\");\n\n let mut nodes = [0; N - 1];\n\n let total_nodes = N - 1;\n let half_size = N / 2;\n\n // Hash base layer.\n for i in 0..half_size {\n nodes[i] = hasher(leaves[2 * i], leaves[2 * i + 1]);\n }\n\n // Hash the other layers.\n for i in 0..(total_nodes - half_size) {\n nodes[half_size + i] = hasher(nodes[2 * i], nodes[2 * i + 1]);\n }\n\n nodes\n}\n"
|
|
679
|
+
"source": "use crate::{\n constants::{\n DOM_SEP__MERKLE_HASH, DOM_SEP__NULLIFIER_MERKLE, DOM_SEP__PUBLIC_DATA_MERKLE,\n DOM_SEP__RETRIEVED_BYTECODES_MERKLE, DOM_SEP__WRITTEN_SLOTS_MERKLE,\n },\n hash::{accumulate_sha256, poseidon2_hash_with_separator},\n traits::Empty,\n utils::math::is_power_of_2_u32,\n};\n\n/// Merkle-node hash used by append-only trees.\npub fn merkle_hash(left: Field, right: Field) -> Field {\n poseidon2_hash_with_separator([left, right], DOM_SEP__MERKLE_HASH)\n}\n\n/// Merkle-node hash for the nullifier tree's sibling paths.\npub fn nullifier_merkle_hash(left: Field, right: Field) -> Field {\n poseidon2_hash_with_separator([left, right], DOM_SEP__NULLIFIER_MERKLE)\n}\n\n/// Merkle-node hash for the public-data tree's sibling paths.\npub fn public_data_merkle_hash(left: Field, right: Field) -> Field {\n poseidon2_hash_with_separator([left, right], DOM_SEP__PUBLIC_DATA_MERKLE)\n}\n\n/// Merkle-node hash for the AVM-internal written-public-data-slots tree's sibling paths.\npub fn written_slots_merkle_hash(left: Field, right: Field) -> Field {\n poseidon2_hash_with_separator([left, right], DOM_SEP__WRITTEN_SLOTS_MERKLE)\n}\n\n/// Merkle-node hash for the AVM-internal retrieved-bytecodes (class-id) tree's sibling paths.\npub fn retrieved_bytecodes_merkle_hash(left: Field, right: Field) -> Field {\n poseidon2_hash_with_separator([left, right], DOM_SEP__RETRIEVED_BYTECODES_MERKLE)\n}\n\npub fn sha_merkle_hash(left: Field, right: Field) -> Field {\n accumulate_sha256(left, right)\n}\n\n/// A balanced Merkle tree over `N` leaves (`N` must be a power of 2).\n///\n/// Leaves are stored and consumed as-is; the internal nodes are built by `compute_merkle_tree_nodes`,\n/// which applies `hasher` at every layer with no domain separation between the leaf layer and the\n/// internal-node layers. Callers must therefore pass leaves that are already domain-separated from the\n/// node hashes (see the warning on `compute_merkle_tree_nodes`).\n#[derive(Eq)]\npub struct MerkleTree<let N: u32> {\n pub leaves: [Field; N],\n pub nodes: [Field; N - 1],\n}\n\nimpl<let N: u32> Empty for MerkleTree<N> {\n fn empty() -> Self {\n MerkleTree { leaves: [0; N], nodes: [0; N - 1] }\n }\n}\n\nimpl<let N: u32> MerkleTree<N> {\n pub fn new(leaves: [Field; N]) -> Self {\n let nodes = compute_merkle_tree_nodes(leaves, merkle_hash);\n MerkleTree { leaves, nodes }\n }\n\n pub fn new_with_hasher(leaves: [Field; N], hasher: fn(Field, Field) -> Field) -> Self {\n let nodes = compute_merkle_tree_nodes(leaves, hasher);\n MerkleTree { leaves, nodes }\n }\n\n pub fn new_sha(leaves: [Field; N]) -> Self {\n let nodes = compute_merkle_tree_nodes(leaves, sha_merkle_hash);\n MerkleTree { leaves, nodes }\n }\n\n pub fn get_root(self) -> Field {\n self.nodes[N - 2]\n }\n\n pub fn get_sibling_path<let K: u32>(self, leaf_index: u32) -> [Field; K] {\n assert_eq(2.pow_32(K as Field), N as Field, \"Invalid path length\");\n\n let mut path = [0; K];\n let mut current_index = leaf_index;\n let mut subtree_width = N;\n\n let mut current_sibling_index = sibling_index(current_index);\n\n path[0] = self.leaves[current_sibling_index];\n\n let mut subtree_offset: u32 = 0;\n\n for i in 1..K {\n current_index = current_index / 2;\n subtree_width = subtree_width / 2;\n\n current_sibling_index = sibling_index(current_index);\n\n path[i] = self.nodes[subtree_offset + current_sibling_index];\n\n subtree_offset += subtree_width;\n }\n\n path\n }\n}\n\npub fn sibling_index(index: u32) -> u32 {\n if index % 2 == 0 {\n index + 1\n } else {\n index - 1\n }\n}\n\n/// Computes the `N - 1` internal nodes of a balanced Merkle tree from its `N` leaves (root last);\n/// `N` must be a power of 2 greater than 1.\n///\n/// Leaves are consumed as-is: this helper does not hash leaf preimages, it only hashes pairs upward.\n/// The same `hasher` is applied at every layer (the leaf/base layer and all internal-node layers\n/// alike), so there is NO domain separation between the leaf hashing and the internal-node hashing. An\n/// internal node is therefore just `hasher(left, right)`, indistinguishable in form from a leaf.\n///\n/// WARNING: because of this, callers MUST pass leaves that are already domain-separated from this\n/// helper's internal-node hashes (i.e. produced by a hash whose domain differs from `hasher`), so that\n/// an internal-node value can never be a valid leaf. (Per-tree domain separation of the node hashing\n/// itself is likewise the caller's choice: pass the tree-specific hasher, e.g. `nullifier_merkle_hash`.)\npub fn compute_merkle_tree_nodes<let N: u32>(\n leaves: [Field; N],\n hasher: fn(Field, Field) -> Field,\n) -> [Field; N - 1] {\n // Note: `N` must be a power of 2.\n std::static_assert(is_power_of_2_u32(N), \"N must be a power of 2\");\n std::static_assert(N != 1, \"2 must divide N\");\n\n let mut nodes = [0; N - 1];\n\n let total_nodes = N - 1;\n let half_size = N / 2;\n\n // Hash base layer.\n for i in 0..half_size {\n nodes[i] = hasher(leaves[2 * i], leaves[2 * i + 1]);\n }\n\n // Hash the other layers.\n for i in 0..(total_nodes - half_size) {\n nodes[half_size + i] = hasher(nodes[2 * i], nodes[2 * i + 1]);\n }\n\n nodes\n}\n\nmod tests {\n use super::{compute_merkle_tree_nodes, MerkleTree};\n\n // A trivial, collision-prone hasher that makes the absence of leaf/internal-node domain separation\n // observable: each node is simply the sum of its two children.\n fn add_hasher(left: Field, right: Field) -> Field {\n left + right\n }\n\n #[test]\n fn leaves_and_internal_nodes_share_one_hasher() {\n // base layer: 1+2=3, 3+4=7 ; internal layer (root last): 3+7=10\n let nodes = compute_merkle_tree_nodes([1, 2, 3, 4], add_hasher);\n assert_eq(nodes, [3, 7, 10]);\n }\n\n #[test]\n fn internal_node_value_hashes_identically_as_a_leaf() {\n // Feeding the internal-node values 3 and 7 back in as *leaves* yields the same root (10): the\n // helper hashes the leaf layer and the internal-node layers with one hasher, so an internal\n // node is indistinguishable in form from a leaf. Callers must pass domain-separated leaves.\n let nodes = compute_merkle_tree_nodes([3, 7, 0, 0], add_hasher);\n assert_eq(nodes[nodes.len() - 1], 3 + 7);\n }\n\n #[test]\n fn merkle_tree_root_is_last_node() {\n let tree = MerkleTree::new_with_hasher([1, 2, 3, 4], add_hasher);\n assert_eq(tree.get_root(), 10);\n assert_eq(tree.get_root(), tree.nodes[tree.nodes.len() - 1]);\n }\n}\n"
|
|
576
680
|
},
|
|
577
681
|
"190": {
|
|
578
682
|
"function_locations": [
|
|
@@ -642,127 +746,147 @@
|
|
|
642
746
|
},
|
|
643
747
|
{
|
|
644
748
|
"name": "<impl Packable for bool>::unpack",
|
|
645
|
-
"start":
|
|
749
|
+
"start": 946
|
|
646
750
|
},
|
|
647
751
|
{
|
|
648
752
|
"name": "<impl Packable for u8>::pack",
|
|
649
|
-
"start":
|
|
753
|
+
"start": 1397
|
|
650
754
|
},
|
|
651
755
|
{
|
|
652
756
|
"name": "<impl Packable for u8>::unpack",
|
|
653
|
-
"start":
|
|
757
|
+
"start": 1499
|
|
654
758
|
},
|
|
655
759
|
{
|
|
656
760
|
"name": "<impl Packable for u16>::pack",
|
|
657
|
-
"start":
|
|
761
|
+
"start": 1651
|
|
658
762
|
},
|
|
659
763
|
{
|
|
660
764
|
"name": "<impl Packable for u16>::unpack",
|
|
661
|
-
"start":
|
|
765
|
+
"start": 1753
|
|
662
766
|
},
|
|
663
767
|
{
|
|
664
768
|
"name": "<impl Packable for u32>::pack",
|
|
665
|
-
"start":
|
|
769
|
+
"start": 1906
|
|
666
770
|
},
|
|
667
771
|
{
|
|
668
772
|
"name": "<impl Packable for u32>::unpack",
|
|
669
|
-
"start":
|
|
773
|
+
"start": 2008
|
|
670
774
|
},
|
|
671
775
|
{
|
|
672
776
|
"name": "<impl Packable for u64>::pack",
|
|
673
|
-
"start":
|
|
777
|
+
"start": 2161
|
|
674
778
|
},
|
|
675
779
|
{
|
|
676
780
|
"name": "<impl Packable for u64>::unpack",
|
|
677
|
-
"start":
|
|
781
|
+
"start": 2263
|
|
678
782
|
},
|
|
679
783
|
{
|
|
680
784
|
"name": "<impl Packable for u128>::pack",
|
|
681
|
-
"start":
|
|
785
|
+
"start": 2418
|
|
682
786
|
},
|
|
683
787
|
{
|
|
684
788
|
"name": "<impl Packable for u128>::unpack",
|
|
685
|
-
"start":
|
|
789
|
+
"start": 2520
|
|
686
790
|
},
|
|
687
791
|
{
|
|
688
792
|
"name": "<impl Packable for Field>::pack",
|
|
689
|
-
"start":
|
|
793
|
+
"start": 2678
|
|
690
794
|
},
|
|
691
795
|
{
|
|
692
796
|
"name": "<impl Packable for Field>::unpack",
|
|
693
|
-
"start":
|
|
797
|
+
"start": 2771
|
|
694
798
|
},
|
|
695
799
|
{
|
|
696
800
|
"name": "<impl Packable for i8>::pack",
|
|
697
|
-
"start":
|
|
801
|
+
"start": 2915
|
|
698
802
|
},
|
|
699
803
|
{
|
|
700
804
|
"name": "<impl Packable for i8>::unpack",
|
|
701
|
-
"start":
|
|
805
|
+
"start": 3023
|
|
702
806
|
},
|
|
703
807
|
{
|
|
704
808
|
"name": "<impl Packable for i16>::pack",
|
|
705
|
-
"start":
|
|
809
|
+
"start": 3181
|
|
706
810
|
},
|
|
707
811
|
{
|
|
708
812
|
"name": "<impl Packable for i16>::unpack",
|
|
709
|
-
"start":
|
|
813
|
+
"start": 3290
|
|
710
814
|
},
|
|
711
815
|
{
|
|
712
816
|
"name": "<impl Packable for i32>::pack",
|
|
713
|
-
"start":
|
|
817
|
+
"start": 3450
|
|
714
818
|
},
|
|
715
819
|
{
|
|
716
820
|
"name": "<impl Packable for i32>::unpack",
|
|
717
|
-
"start":
|
|
821
|
+
"start": 3559
|
|
718
822
|
},
|
|
719
823
|
{
|
|
720
824
|
"name": "<impl Packable for i64>::pack",
|
|
721
|
-
"start":
|
|
825
|
+
"start": 3719
|
|
722
826
|
},
|
|
723
827
|
{
|
|
724
828
|
"name": "<impl Packable for i64>::unpack",
|
|
725
|
-
"start":
|
|
829
|
+
"start": 3828
|
|
726
830
|
},
|
|
727
831
|
{
|
|
728
832
|
"name": "<impl Packable for super::point::EmbeddedCurvePoint>::pack",
|
|
729
|
-
"start":
|
|
833
|
+
"start": 3997
|
|
730
834
|
},
|
|
731
835
|
{
|
|
732
836
|
"name": "<impl Packable for super::point::EmbeddedCurvePoint>::unpack",
|
|
733
|
-
"start":
|
|
837
|
+
"start": 4079
|
|
734
838
|
},
|
|
735
839
|
{
|
|
736
840
|
"name": "<impl Packable for [T; M]>::pack",
|
|
737
|
-
"start":
|
|
841
|
+
"start": 4290
|
|
738
842
|
},
|
|
739
843
|
{
|
|
740
844
|
"name": "<impl Packable for [T; M]>::unpack",
|
|
741
|
-
"start":
|
|
845
|
+
"start": 4652
|
|
742
846
|
},
|
|
743
847
|
{
|
|
744
848
|
"name": "test_u16_packing",
|
|
745
|
-
"start":
|
|
849
|
+
"start": 4897
|
|
746
850
|
},
|
|
747
851
|
{
|
|
748
852
|
"name": "test_i8_packing",
|
|
749
|
-
"start":
|
|
853
|
+
"start": 4993
|
|
750
854
|
},
|
|
751
855
|
{
|
|
752
856
|
"name": "test_i16_packing",
|
|
753
|
-
"start":
|
|
857
|
+
"start": 5089
|
|
754
858
|
},
|
|
755
859
|
{
|
|
756
860
|
"name": "test_i32_packing",
|
|
757
|
-
"start":
|
|
861
|
+
"start": 5187
|
|
758
862
|
},
|
|
759
863
|
{
|
|
760
864
|
"name": "test_i64_packing",
|
|
761
|
-
"start":
|
|
865
|
+
"start": 5285
|
|
866
|
+
},
|
|
867
|
+
{
|
|
868
|
+
"name": "test_bool_unpack_accepts_canonical_values",
|
|
869
|
+
"start": 5408
|
|
870
|
+
},
|
|
871
|
+
{
|
|
872
|
+
"name": "test_bool_unpack_rejects_even_non_bool",
|
|
873
|
+
"start": 5594
|
|
874
|
+
},
|
|
875
|
+
{
|
|
876
|
+
"name": "test_bool_unpack_rejects_odd_non_bool",
|
|
877
|
+
"start": 5827
|
|
878
|
+
},
|
|
879
|
+
{
|
|
880
|
+
"name": "test_bool_unpack_rejects_large_field",
|
|
881
|
+
"start": 6058
|
|
882
|
+
},
|
|
883
|
+
{
|
|
884
|
+
"name": "test_bool_pack_unpack_roundtrip",
|
|
885
|
+
"start": 6145
|
|
762
886
|
}
|
|
763
887
|
],
|
|
764
888
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-protocol-circuits/crates/types/src/type_packing.nr",
|
|
765
|
-
"source": "use crate::traits::{Deserialize, Packable, Serialize};\n\nglobal BOOL_PACKED_LEN: u32 = 1;\nglobal U8_PACKED_LEN: u32 = 1;\nglobal U16_PACKED_LEN: u32 = 1;\nglobal U32_PACKED_LEN: u32 = 1;\nglobal U64_PACKED_LEN: u32 = 1;\nglobal U128_PACKED_LEN: u32 = 1;\nglobal FIELD_PACKED_LEN: u32 = 1;\nglobal I8_PACKED_LEN: u32 = 1;\nglobal I16_PACKED_LEN: u32 = 1;\nglobal I32_PACKED_LEN: u32 = 1;\nglobal I64_PACKED_LEN: u32 = 1;\nglobal POINT_PACKED_LEN: u32 = 2;\n\nimpl Packable for bool {\n let N: u32 = BOOL_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> bool {\n
|
|
889
|
+
"source": "use crate::traits::{Deserialize, Packable, Serialize};\n\nglobal BOOL_PACKED_LEN: u32 = 1;\nglobal U8_PACKED_LEN: u32 = 1;\nglobal U16_PACKED_LEN: u32 = 1;\nglobal U32_PACKED_LEN: u32 = 1;\nglobal U64_PACKED_LEN: u32 = 1;\nglobal U128_PACKED_LEN: u32 = 1;\nglobal FIELD_PACKED_LEN: u32 = 1;\nglobal I8_PACKED_LEN: u32 = 1;\nglobal I16_PACKED_LEN: u32 = 1;\nglobal I32_PACKED_LEN: u32 = 1;\nglobal I64_PACKED_LEN: u32 = 1;\nglobal POINT_PACKED_LEN: u32 = 2;\n\nimpl Packable for bool {\n let N: u32 = BOOL_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n /// Unpacks a `bool`, constraining the field to be a canonical boolean. A field outside `{0, 1}` is\n /// rejected (rather than silently reinterpreted), so an arbitrary-origin field cannot be misread.\n /// `pack` always emits `0` or `1`, so round-tripping is unaffected.\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> bool {\n let v = fields[0];\n // v * v == v holds iff v is 0 or 1: a single degree-2 constraint that both validates the field\n // is a canonical bool and avoids the byte-range decomposition that a cast to u8 would require.\n assert(v * v == v, \"Packable::unpack: bool field must be 0 or 1\");\n v == 1\n }\n}\n\nimpl Packable for u8 {\n let N: u32 = U8_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u8\n }\n}\n\nimpl Packable for u16 {\n let N: u32 = U16_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u16\n }\n}\n\nimpl Packable for u32 {\n let N: u32 = U32_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u32\n }\n}\n\nimpl Packable for u64 {\n let N: u32 = U64_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u64\n }\n}\n\nimpl Packable for u128 {\n let N: u32 = U128_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u128\n }\n}\n\nimpl Packable for Field {\n let N: u32 = FIELD_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0]\n }\n}\n\nimpl Packable for i8 {\n let N: u32 = I8_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as u8 as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u8 as i8\n }\n}\n\nimpl Packable for i16 {\n let N: u32 = I16_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as u16 as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u16 as i16\n }\n}\n\nimpl Packable for i32 {\n let N: u32 = I32_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as u32 as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u32 as i32\n }\n}\n\nimpl Packable for i64 {\n let N: u32 = I64_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as u64 as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u64 as i64\n }\n}\n\nimpl Packable for super::point::EmbeddedCurvePoint {\n let N: u32 = POINT_PACKED_LEN;\n fn pack(self) -> [Field; Self::N] {\n self.serialize()\n }\n\n fn unpack(packed: [Field; Self::N]) -> Self {\n Self::deserialize(packed)\n }\n}\n\nimpl<T, let M: u32> Packable for [T; M]\nwhere\n T: Packable,\n{\n let N: u32 = M * <T as Packable>::N;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n let mut result: [Field; Self::N] = std::mem::zeroed();\n for i in 0..M {\n let serialized = self[i].pack();\n for j in 0..<T as Packable>::N {\n result[i * <T as Packable>::N + j] = serialized[j];\n }\n }\n result\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n let mut reader = crate::utils::reader::Reader::new(fields);\n let result: [T; M] = std::mem::zeroed();\n reader.read_struct_array::<T, <T as Packable>::N, M>(Packable::unpack, result)\n }\n}\n\n#[test]\nfn test_u16_packing() {\n let a: u16 = 10;\n assert_eq(a, u16::unpack(a.pack()));\n}\n\n#[test]\nfn test_i8_packing() {\n let a: i8 = -10;\n assert_eq(a, i8::unpack(a.pack()));\n}\n\n#[test]\nfn test_i16_packing() {\n let a: i16 = -10;\n assert_eq(a, i16::unpack(a.pack()));\n}\n\n#[test]\nfn test_i32_packing() {\n let a: i32 = -10;\n assert_eq(a, i32::unpack(a.pack()));\n}\n\n#[test]\nfn test_i64_packing() {\n let a: i64 = -10;\n assert_eq(a, i64::unpack(a.pack()));\n}\n\n#[test]\nfn test_bool_unpack_accepts_canonical_values() {\n assert_eq(bool::unpack([0]), false);\n assert_eq(bool::unpack([1]), true);\n}\n\n#[test(should_fail_with = \"bool field must be 0 or 1\")]\nfn test_bool_unpack_rejects_even_non_bool() {\n // 2 has LSB 0, so the previous LSB-based unpack silently returned false; now it is rejected.\n let _ = bool::unpack([2]);\n}\n\n#[test(should_fail_with = \"bool field must be 0 or 1\")]\nfn test_bool_unpack_rejects_odd_non_bool() {\n // 3 has LSB 1, so the previous LSB-based unpack silently returned true; now it is rejected.\n let _ = bool::unpack([3]);\n}\n\n#[test(should_fail_with = \"bool field must be 0 or 1\")]\nfn test_bool_unpack_rejects_large_field() {\n let _ = bool::unpack([1000000]);\n}\n\n#[test]\nfn test_bool_pack_unpack_roundtrip() {\n // `pack` always emits 0 or 1, so it round-trips through the canonical-bool check in `unpack`.\n assert_eq(true.pack(), [1]);\n assert_eq(false.pack(), [0]);\n assert_eq(bool::unpack(true.pack()), true);\n assert_eq(bool::unpack(false.pack()), false);\n}\n"
|
|
766
890
|
},
|
|
767
891
|
"240": {
|
|
768
892
|
"function_locations": [
|
|
@@ -864,23 +988,23 @@
|
|
|
864
988
|
},
|
|
865
989
|
{
|
|
866
990
|
"name": "derive_deserialize",
|
|
867
|
-
"start":
|
|
991
|
+
"start": 7208
|
|
868
992
|
},
|
|
869
993
|
{
|
|
870
994
|
"name": "get_params_len_quote",
|
|
871
|
-
"start":
|
|
995
|
+
"start": 10934
|
|
872
996
|
},
|
|
873
997
|
{
|
|
874
998
|
"name": "get_generics_declarations",
|
|
875
|
-
"start":
|
|
999
|
+
"start": 11393
|
|
876
1000
|
},
|
|
877
1001
|
{
|
|
878
1002
|
"name": "get_where_trait_clause",
|
|
879
|
-
"start":
|
|
1003
|
+
"start": 12477
|
|
880
1004
|
}
|
|
881
1005
|
],
|
|
882
1006
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-protocol-circuits/crates/serde/src/serialization.nr",
|
|
883
|
-
"source": "use crate::{reader::Reader, writer::Writer};\n\n/// Trait for serializing Noir types into arrays of Fields.\n///\n/// An implementation of the Serialize trait has to follow Noir's intrinsic serialization (each member of a struct\n/// converted directly into one or more Fields without any packing or compression). This trait (and Deserialize) are\n/// typically used to communicate between Noir and TypeScript (via oracles and function arguments).\n///\n/// # On Following Noir's Intrinsic Serialization\n/// When calling a Noir function from TypeScript (TS), first the function arguments are serialized into an array\n/// of fields. This array is then included in the initial witness. Noir's intrinsic serialization is then used\n/// to deserialize the arguments from the witness. When the same Noir function is called from Noir this Serialize trait\n/// is used instead of the serialization in TS. For this reason we need to have a match between TS serialization,\n/// Noir's intrinsic serialization and the implementation of this trait. If there is a mismatch, the function calls\n/// fail with an arguments hash mismatch error message.\n///\n/// # Associated Constants\n/// * `N` - The length of the output Field array, known at compile time\n///\n/// # Example\n/// ```\n/// impl<let N: u32> Serialize for str<N> {\n/// let N: u32 = N;\n///\n/// fn serialize(self) -> [Field; Self::N] {\n/// let mut writer: Writer<Self::N> = Writer::new();\n/// self.stream_serialize(&mut writer);\n/// writer.finish()\n/// }\n///\n/// fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n/// let bytes = self.as_bytes();\n/// for i in 0..bytes.len() {\n/// writer.write(bytes[i] as Field);\n/// }\n/// }\n/// }\n/// ```\n#[derive_via(derive_serialize)]\npub trait Serialize {\n let N: u32;\n\n fn serialize(self) -> [Field; Self::N];\n\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>);\n}\n\n/// Generates a `Serialize` trait implementation for a struct type.\n///\n/// # Parameters\n/// - `s`: The struct type definition to generate the implementation for\n///\n/// # Returns\n/// A quoted code block containing the trait implementation\n///\n/// # Example\n/// For a struct defined as:\n/// ```\n/// struct Log<N> {\n/// fields: [Field; N],\n/// length: u32\n/// }\n/// ```\n///\n/// This function generates code equivalent to:\n/// ```\n/// impl<let N: u32> Serialize for Log<N> {\n/// let N: u32 = <[Field; N] as Serialize>::N + <u32 as Serialize>::N;\n///\n/// fn serialize(self) -> [Field; Self::N] {\n/// let mut writer: Writer<Self::N> = Writer::new();\n/// self.stream_serialize(&mut writer);\n/// writer.finish()\n/// }\n///\n/// #[inline_always]\n/// fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n/// Serialize::stream_serialize(self.fields, writer);\n/// Serialize::stream_serialize(self.length, writer);\n/// }\n/// }\n/// ```\npub comptime fn derive_serialize(s: TypeDefinition) -> Quoted {\n let typ = s.as_type();\n let nested_struct = typ.as_data_type().unwrap();\n\n // We care only about the name and type so we drop the last item of the tuple\n let params = nested_struct.0.fields(nested_struct.1).map(|(name, typ, _)| (name, typ));\n\n // Generates the generic parameter declarations (to be placed after the `impl` keyword) and the `where` clause\n // for the `Serialize` trait.\n let generics_declarations = get_generics_declarations(s);\n let where_serialize_clause = get_where_trait_clause(s, quote {Serialize});\n\n let params_len_quote = get_params_len_quote(params);\n\n let function_body = params\n .map(|(name, _typ): (Quoted, Type)| {\n quote {\n $crate::serialization::Serialize::stream_serialize(self.$name, writer);\n }\n })\n .join(quote {});\n\n quote {\n impl$generics_declarations $crate::serialization::Serialize for $typ\n $where_serialize_clause\n {\n let N: u32 = $params_len_quote;\n\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: $crate::writer::Writer<Self::N> = $crate::writer::Writer::new();\n $crate::serialization::Serialize::stream_serialize(self, &mut writer);\n writer.finish()\n }\n\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut $crate::writer::Writer<K>) {\n $function_body\n }\n }\n }\n}\n\n/// Trait for deserializing Noir types from arrays of Fields.\n///\n/// An implementation of the Deserialize trait has to follow Noir's intrinsic serialization (each member of a struct\n/// converted directly into one or more Fields without any packing or compression). This trait is typically used when\n/// deserializing return values from function calls in Noir. Since the same function could be called from TypeScript\n/// (TS), in which case the TS deserialization would get used, we need to have a match between the 2.\n///\n/// # Associated Constants\n/// * `N` - The length of the input Field array, known at compile time\n///\n/// # Example\n/// ```\n/// impl<let M: u32> Deserialize for str<M> {\n/// let N: u32 = M;\n///\n/// fn deserialize(fields: [Field; Self::N]) -> Self {\n/// let mut reader = Reader::new(fields);\n/// let result = Self::stream_deserialize(&mut reader);\n/// reader.finish();\n/// result\n/// }\n///\n/// fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n/// let mut bytes = [0 as u8; M];\n/// for i in 0..M {\n/// bytes[i] = reader.read() as u8;\n/// }\n/// str::<M>::from(bytes)\n/// }\n/// }\n/// ```\n#[derive_via(derive_deserialize)]\npub trait Deserialize {\n let N: u32;\n\n fn deserialize(fields: [Field; Self::N]) -> Self;\n\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self;\n}\n\n/// Generates a `Deserialize` trait implementation for a given struct `s`.\n///\n/// # Arguments\n/// * `s` - The struct type definition to generate the implementation for\n///\n/// # Returns\n/// A `Quoted` block containing the generated trait implementation\n///\n/// # Requirements\n/// Each struct member type must implement the `Deserialize` trait (it gets used in the generated code).\n///\n/// # Example\n/// For a struct like:\n/// ```\n/// struct MyStruct {\n/// x: AztecAddress,\n/// y: Field,\n/// }\n/// ```\n///\n/// This generates:\n/// ```\n/// impl Deserialize for MyStruct {\n/// let N: u32 = <AztecAddress as Deserialize>::N + <Field as Deserialize>::N;\n///\n/// fn deserialize(fields: [Field; Self::N]) -> Self {\n/// let mut reader = Reader::new(fields);\n/// let result = Self::stream_deserialize(&mut reader);\n/// reader.finish();\n/// result\n/// }\n///\n/// #[inline_always]\n/// fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n/// let x = <AztecAddress as Deserialize>::stream_deserialize(reader);\n/// let y = <Field as Deserialize>::stream_deserialize(reader);\n/// Self { x, y }\n/// }\n/// }\n/// ```\npub comptime fn derive_deserialize(s: TypeDefinition) -> Quoted {\n let typ = s.as_type();\n let nested_struct = typ.as_data_type().unwrap();\n let params = nested_struct.0.fields(nested_struct.1);\n\n // Generates the generic parameter declarations (to be placed after the `impl` keyword) and the `where` clause\n // for the `Deserialize` trait.\n let generics_declarations = get_generics_declarations(s);\n let where_deserialize_clause = get_where_trait_clause(s, quote {Deserialize});\n\n // The following will give us:\n // <type_of_struct_member_1 as Deserialize>::N + <type_of_struct_member_2 as Deserialize>::N + ...\n // (or 0 if the struct has no members)\n let right_hand_side_of_definition_of_n = if params.len() > 0 {\n params\n .map(|(_, param_type, _): (Quoted, Type, Quoted)| {\n quote {\n <$param_type as $crate::serialization::Deserialize>::N\n }\n })\n .join(quote {+})\n } else {\n quote {0}\n };\n\n // For structs containing a single member, we can enhance performance by directly deserializing the input array,\n // bypassing the need for loop-based array construction. While this optimization yields significant benefits in\n // Brillig where the loops are expected to not be optimized, it is not relevant in ACIR where the loops are\n // expected to be optimized away.\n let function_body = if params.len() > 1 {\n // This generates deserialization code for each struct member and concatenates them together.\n let deserialization_of_struct_members = params\n .map(|(param_name, param_type, _): (Quoted, Type, Quoted)| {\n quote {\n let $param_name = <$param_type as Deserialize>::stream_deserialize(reader);\n }\n })\n .join(quote {});\n\n // We join the struct member names with a comma to be used in the `Self { ... }` syntax\n // This will give us e.g. `a, b, c` for a struct with three fields named `a`, `b`, and `c`.\n let struct_members = params\n .map(|(param_name, _, _): (Quoted, Type, Quoted)| quote { $param_name })\n .join(quote {,});\n\n quote {\n $deserialization_of_struct_members\n\n Self { $struct_members }\n }\n } else if params.len() == 1 {\n let param_name = params[0].0;\n quote {\n Self { $param_name: $crate::serialization::Deserialize::stream_deserialize(reader) }\n }\n } else {\n quote {\n Self {}\n }\n };\n\n quote {\n impl$generics_declarations $crate::serialization::Deserialize for $typ\n $where_deserialize_clause\n {\n let N: u32 = $right_hand_side_of_definition_of_n;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = $crate::reader::Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut $crate::reader::Reader<K>) -> Self {\n $function_body\n }\n }\n }\n}\n\n/// Generates a quoted expression that computes the total serialized length of function parameters.\n///\n/// # Parameters\n/// * `params` - An array of tuples where each tuple contains a quoted parameter name and its Type. The type needs\n/// to implement the Serialize trait.\n///\n/// # Returns\n/// A quoted expression that evaluates to:\n/// * `0` if there are no parameters\n/// * `(<type1 as Serialize>::N + <type2 as Serialize>::N + ...)` for one or more parameters\ncomptime fn get_params_len_quote(params: [(Quoted, Type)]) -> Quoted {\n if params.len() == 0 {\n quote { 0 }\n } else {\n let params_quote_without_parentheses = params\n .map(|(_, param_type): (Quoted, Type)| {\n quote {\n <$param_type as $crate::serialization::Serialize>::N\n }\n })\n .join(quote {+});\n quote { ($params_quote_without_parentheses) }\n }\n}\n\ncomptime fn get_generics_declarations(s: TypeDefinition) -> Quoted {\n let generics = s.generics();\n\n if generics.len() > 0 {\n let generics_declarations_items = generics\n .map(|(name, maybe_integer_typ)| {\n // The second item in the generics tuple is an Option of an integer type that is Some only if\n // the generic is numeric.\n if maybe_integer_typ.is_some() {\n // The generic is numeric, so we return a quote defined as e.g. \"let N: u32\"\n let integer_type = maybe_integer_typ.unwrap();\n quote {let $name: $integer_type}\n } else {\n // The generic is not numeric, so we return a quote containing the name of the generic (e.g. \"T\")\n quote {$name}\n }\n })\n .join(quote {,});\n quote {<$generics_declarations_items>}\n } else {\n // The struct doesn't have any generics defined, so we just return an empty quote.\n quote {}\n }\n}\n\ncomptime fn get_where_trait_clause(s: TypeDefinition, trait_name: Quoted) -> Quoted {\n let generics = s.generics();\n\n // The second item in the generics tuple is an Option of an integer type that is Some only if the generic is\n // numeric.\n let non_numeric_generics =\n generics.filter(|(_, maybe_integer_typ)| maybe_integer_typ.is_none());\n\n if non_numeric_generics.len() > 0 {\n let non_numeric_generics_declarations =\n non_numeric_generics.map(|(name, _)| quote {$name: $trait_name}).join(quote {,});\n quote {where $non_numeric_generics_declarations}\n } else {\n // There are no non-numeric generics, so we return an empty quote.\n quote {}\n }\n}\n"
|
|
1007
|
+
"source": "use crate::{reader::Reader, writer::Writer};\n\n/// Trait for serializing Noir types into arrays of Fields.\n///\n/// An implementation of the Serialize trait has to follow Noir's intrinsic serialization (each member of a struct\n/// converted directly into one or more Fields without any packing or compression). This trait (and Deserialize) are\n/// typically used to communicate between Noir and TypeScript (via oracles and function arguments).\n///\n/// # On Following Noir's Intrinsic Serialization\n/// When calling a Noir function from TypeScript (TS), first the function arguments are serialized into an array\n/// of fields. This array is then included in the initial witness. Noir's intrinsic serialization is then used\n/// to deserialize the arguments from the witness. When the same Noir function is called from Noir this Serialize trait\n/// is used instead of the serialization in TS. For this reason we need to have a match between TS serialization,\n/// Noir's intrinsic serialization and the implementation of this trait. If there is a mismatch, the function calls\n/// fail with an arguments hash mismatch error message.\n///\n/// # Associated Constants\n/// * `N` - The length of the output Field array, known at compile time\n///\n/// # Example\n/// ```\n/// impl<let N: u32> Serialize for str<N> {\n/// let N: u32 = N;\n///\n/// fn serialize(self) -> [Field; Self::N] {\n/// let mut writer: Writer<Self::N> = Writer::new();\n/// self.stream_serialize(&mut writer);\n/// writer.finish()\n/// }\n///\n/// fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n/// let bytes = self.as_bytes();\n/// for i in 0..bytes.len() {\n/// writer.write(bytes[i] as Field);\n/// }\n/// }\n/// }\n/// ```\n#[derive_via(derive_serialize)]\npub trait Serialize {\n let N: u32;\n\n fn serialize(self) -> [Field; Self::N];\n\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>);\n}\n\n/// Generates a `Serialize` trait implementation for a struct type.\n///\n/// # Parameters\n/// - `s`: The struct type definition to generate the implementation for\n///\n/// # Returns\n/// A quoted code block containing the trait implementation\n///\n/// # Example\n/// For a struct defined as:\n/// ```\n/// struct Log<N> {\n/// fields: [Field; N],\n/// length: u32\n/// }\n/// ```\n///\n/// This function generates code equivalent to:\n/// ```\n/// impl<let N: u32> Serialize for Log<N> {\n/// let N: u32 = <[Field; N] as Serialize>::N + <u32 as Serialize>::N;\n///\n/// fn serialize(self) -> [Field; Self::N] {\n/// let mut writer: Writer<Self::N> = Writer::new();\n/// self.stream_serialize(&mut writer);\n/// writer.finish()\n/// }\n///\n/// #[inline_always]\n/// fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n/// Serialize::stream_serialize(self.fields, writer);\n/// Serialize::stream_serialize(self.length, writer);\n/// }\n/// }\n/// ```\npub comptime fn derive_serialize(s: TypeDefinition) -> Quoted {\n let typ = s.as_type();\n let nested_struct = typ.as_data_type().unwrap();\n\n // We care only about the name and type so we drop the last item of the tuple\n let params = nested_struct.0.fields(nested_struct.1).map(|(name, typ, _)| (name, typ));\n\n // Generates the generic parameter declarations (to be placed after the `impl` keyword) and the `where` clause\n // for the `Serialize` trait.\n let generics_declarations = get_generics_declarations(s);\n let where_serialize_clause = get_where_trait_clause(s, quote { Serialize });\n\n let params_len_quote = get_params_len_quote(params);\n\n let function_body = params\n .map(|(name, _typ): (Quoted, Type)| {\n quote {\n $crate::serialization::Serialize::stream_serialize(self.$name, writer);\n }\n })\n .join(quote {});\n\n quote {\n impl$generics_declarations $crate::serialization::Serialize for $typ\n $where_serialize_clause\n {\n let N: u32 = $params_len_quote;\n\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: $crate::writer::Writer<Self::N> = $crate::writer::Writer::new();\n $crate::serialization::Serialize::stream_serialize(self, &mut writer);\n writer.finish()\n }\n\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut $crate::writer::Writer<K>) {\n $function_body\n }\n }\n }\n}\n\n/// Trait for deserializing Noir types from arrays of Fields.\n///\n/// An implementation of the Deserialize trait has to follow Noir's intrinsic serialization (each member of a struct\n/// converted directly into one or more Fields without any packing or compression). This trait is typically used when\n/// deserializing return values from function calls in Noir. Since the same function could be called from TypeScript\n/// (TS), in which case the TS deserialization would get used, we need to have a match between the 2.\n///\n/// # Associated Constants\n/// * `N` - The length of the input Field array, known at compile time\n///\n/// # Example\n/// ```\n/// impl<let M: u32> Deserialize for str<M> {\n/// let N: u32 = M;\n///\n/// fn deserialize(fields: [Field; Self::N]) -> Self {\n/// let mut reader = Reader::new(fields);\n/// let result = Self::stream_deserialize(&mut reader);\n/// reader.finish();\n/// result\n/// }\n///\n/// fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n/// let mut bytes = [0 as u8; M];\n/// for i in 0..M {\n/// bytes[i] = reader.read() as u8;\n/// }\n/// str::<M>::from(bytes)\n/// }\n/// }\n/// ```\n#[derive_via(derive_deserialize)]\npub trait Deserialize {\n let N: u32;\n\n fn deserialize(fields: [Field; Self::N]) -> Self;\n\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self;\n}\n\n/// Generates a `Deserialize` trait implementation for a given struct `s`.\n///\n/// # Arguments\n/// * `s` - The struct type definition to generate the implementation for\n///\n/// # Returns\n/// A `Quoted` block containing the generated trait implementation\n///\n/// # Requirements\n/// Each struct member type must implement the `Deserialize` trait (it gets used in the generated code).\n///\n/// # Example\n/// For a struct like:\n/// ```\n/// struct MyStruct {\n/// x: AztecAddress,\n/// y: Field,\n/// }\n/// ```\n///\n/// This generates:\n/// ```\n/// impl Deserialize for MyStruct {\n/// let N: u32 = <AztecAddress as Deserialize>::N + <Field as Deserialize>::N;\n///\n/// fn deserialize(fields: [Field; Self::N]) -> Self {\n/// let mut reader = Reader::new(fields);\n/// let result = Self::stream_deserialize(&mut reader);\n/// reader.finish();\n/// result\n/// }\n///\n/// #[inline_always]\n/// fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n/// let x = <AztecAddress as Deserialize>::stream_deserialize(reader);\n/// let y = <Field as Deserialize>::stream_deserialize(reader);\n/// Self { x, y }\n/// }\n/// }\n/// ```\npub comptime fn derive_deserialize(s: TypeDefinition) -> Quoted {\n let typ = s.as_type();\n let nested_struct = typ.as_data_type().unwrap();\n let params = nested_struct.0.fields(nested_struct.1);\n\n // Generates the generic parameter declarations (to be placed after the `impl` keyword) and the `where` clause\n // for the `Deserialize` trait.\n let generics_declarations = get_generics_declarations(s);\n let where_deserialize_clause = get_where_trait_clause(s, quote { Deserialize });\n\n // The following will give us:\n // <type_of_struct_member_1 as Deserialize>::N + <type_of_struct_member_2 as Deserialize>::N + ...\n // (or 0 if the struct has no members)\n let right_hand_side_of_definition_of_n = if params.len() > 0 {\n params\n .map(|(_, param_type, _): (Quoted, Type, Quoted)| {\n quote {\n <$param_type as $crate::serialization::Deserialize>::N\n }\n })\n .join(quote {+})\n } else {\n quote { 0 }\n };\n\n // For structs containing a single member, we can enhance performance by directly deserializing the input array,\n // bypassing the need for loop-based array construction. While this optimization yields significant benefits in\n // Brillig where the loops are expected to not be optimized, it is not relevant in ACIR where the loops are\n // expected to be optimized away.\n let function_body = if params.len() > 1 {\n // This generates deserialization code for each struct member and concatenates them together.\n let deserialization_of_struct_members = params\n .map(|(param_name, param_type, _): (Quoted, Type, Quoted)| {\n quote {\n let $param_name = <$param_type as Deserialize>::stream_deserialize(reader);\n }\n })\n .join(quote {});\n\n // We join the struct member names with a comma to be used in the `Self { ... }` syntax\n // This will give us e.g. `a, b, c` for a struct with three fields named `a`, `b`, and `c`.\n let struct_members = params\n .map(|(param_name, _, _): (Quoted, Type, Quoted)| quote { $param_name })\n .join(quote {,});\n\n quote {\n $deserialization_of_struct_members\n\n Self { $struct_members }\n }\n } else if params.len() == 1 {\n let param_name = params[0].0;\n quote {\n Self { $param_name: $crate::serialization::Deserialize::stream_deserialize(reader) }\n }\n } else {\n quote {\n Self {}\n }\n };\n\n quote {\n impl$generics_declarations $crate::serialization::Deserialize for $typ\n $where_deserialize_clause\n {\n let N: u32 = $right_hand_side_of_definition_of_n;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = $crate::reader::Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut $crate::reader::Reader<K>) -> Self {\n $function_body\n }\n }\n }\n}\n\n/// Generates a quoted expression that computes the total serialized length of function parameters.\n///\n/// # Parameters\n/// * `params` - An array of tuples where each tuple contains a quoted parameter name and its Type. The type needs\n/// to implement the Serialize trait.\n///\n/// # Returns\n/// A quoted expression that evaluates to:\n/// * `0` if there are no parameters\n/// * `(<type1 as Serialize>::N + <type2 as Serialize>::N + ...)` for one or more parameters\ncomptime fn get_params_len_quote(params: [(Quoted, Type)]) -> Quoted {\n if params.len() == 0 {\n quote { 0 }\n } else {\n let params_quote_without_parentheses = params\n .map(|(_, param_type): (Quoted, Type)| {\n quote {\n <$param_type as $crate::serialization::Serialize>::N\n }\n })\n .join(quote {+});\n quote { ($params_quote_without_parentheses) }\n }\n}\n\ncomptime fn get_generics_declarations(s: TypeDefinition) -> Quoted {\n let generics = s.generics();\n\n if generics.len() > 0 {\n let generics_declarations_items = generics\n .map(|(name, maybe_integer_typ)| {\n // The second item in the generics tuple is an Option of an integer type that is Some only if\n // the generic is numeric.\n if maybe_integer_typ.is_some() {\n // The generic is numeric, so we return a quote defined as e.g. \"let N: u32\"\n let integer_type = maybe_integer_typ.unwrap();\n quote {let $name: $integer_type}\n } else {\n // The generic is not numeric, so we return a quote containing the name of the generic (e.g. \"T\")\n quote { $name }\n }\n })\n .join(quote {,});\n quote {<$generics_declarations_items>}\n } else {\n // The struct doesn't have any generics defined, so we just return an empty quote.\n quote {}\n }\n}\n\ncomptime fn get_where_trait_clause(s: TypeDefinition, trait_name: Quoted) -> Quoted {\n let generics = s.generics();\n\n // The second item in the generics tuple is an Option of an integer type that is Some only if the generic is\n // numeric.\n let non_numeric_generics =\n generics.filter(|(_, maybe_integer_typ)| maybe_integer_typ.is_none());\n\n if non_numeric_generics.len() > 0 {\n let non_numeric_generics_declarations =\n non_numeric_generics.map(|(name, _)| quote {$name: $trait_name}).join(quote {,});\n quote {where $non_numeric_generics_declarations}\n } else {\n // There are no non-numeric generics, so we return an empty quote.\n quote {}\n }\n}\n"
|
|
884
1008
|
},
|
|
885
1009
|
"246": {
|
|
886
1010
|
"function_locations": [
|
|
@@ -1174,27 +1298,27 @@
|
|
|
1174
1298
|
},
|
|
1175
1299
|
{
|
|
1176
1300
|
"name": "<impl Serialize for (T1,)>::serialize",
|
|
1177
|
-
"start":
|
|
1301
|
+
"start": 20178
|
|
1178
1302
|
},
|
|
1179
1303
|
{
|
|
1180
1304
|
"name": "<impl Serialize for (T1,)>::stream_serialize",
|
|
1181
|
-
"start":
|
|
1305
|
+
"start": 20429
|
|
1182
1306
|
},
|
|
1183
1307
|
{
|
|
1184
1308
|
"name": "<impl Deserialize for (T1,)>::deserialize",
|
|
1185
|
-
"start":
|
|
1309
|
+
"start": 20636
|
|
1186
1310
|
},
|
|
1187
1311
|
{
|
|
1188
1312
|
"name": "<impl Deserialize for (T1,)>::stream_deserialize",
|
|
1189
|
-
"start":
|
|
1313
|
+
"start": 20897
|
|
1190
1314
|
},
|
|
1191
1315
|
{
|
|
1192
1316
|
"name": "bounded_vec_serialization",
|
|
1193
|
-
"start":
|
|
1317
|
+
"start": 21246
|
|
1194
1318
|
}
|
|
1195
1319
|
],
|
|
1196
1320
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-protocol-circuits/crates/serde/src/type_impls.nr",
|
|
1197
|
-
"source": "use crate::{reader::Reader, serialization::{Deserialize, Serialize}, writer::Writer};\nuse std::embedded_curve_ops::EmbeddedCurvePoint;\nuse std::embedded_curve_ops::EmbeddedCurveScalar;\n\nglobal BOOL_SERIALIZED_LEN: u32 = 1;\nglobal U8_SERIALIZED_LEN: u32 = 1;\nglobal U16_SERIALIZED_LEN: u32 = 1;\nglobal U32_SERIALIZED_LEN: u32 = 1;\nglobal U64_SERIALIZED_LEN: u32 = 1;\nglobal U128_SERIALIZED_LEN: u32 = 1;\nglobal FIELD_SERIALIZED_LEN: u32 = 1;\nglobal I8_SERIALIZED_LEN: u32 = 1;\nglobal I16_SERIALIZED_LEN: u32 = 1;\nglobal I32_SERIALIZED_LEN: u32 = 1;\nglobal I64_SERIALIZED_LEN: u32 = 1;\n\nimpl Serialize for bool {\n let N: u32 = BOOL_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for bool {\n let N: u32 = BOOL_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> bool {\n reader.read() != 0\n }\n}\n\nimpl Serialize for u8 {\n let N: u32 = U8_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u8 {\n let N: u32 = U8_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u8\n }\n}\n\nimpl Serialize for u16 {\n let N: u32 = U16_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u16 {\n let N: u32 = U16_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u16\n }\n}\n\nimpl Serialize for u32 {\n let N: u32 = U32_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u32 {\n let N: u32 = U32_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u32\n }\n}\n\nimpl Serialize for u64 {\n let N: u32 = U64_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u64 {\n let N: u32 = U64_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u64\n }\n}\n\nimpl Serialize for u128 {\n let N: u32 = U128_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u128 {\n let N: u32 = U128_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u128\n }\n}\n\nimpl Serialize for Field {\n let N: u32 = FIELD_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self);\n }\n}\n\nimpl Deserialize for Field {\n let N: u32 = FIELD_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read()\n }\n}\n\nimpl Serialize for i8 {\n let N: u32 = I8_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as u8 as Field);\n }\n}\n\nimpl Deserialize for i8 {\n let N: u32 = I8_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u8 as i8\n }\n}\n\nimpl Serialize for i16 {\n let N: u32 = I16_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as u16 as Field);\n }\n}\n\nimpl Deserialize for i16 {\n let N: u32 = I16_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u16 as i16\n }\n}\n\nimpl Serialize for i32 {\n let N: u32 = I32_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as u32 as Field);\n }\n}\n\nimpl Deserialize for i32 {\n let N: u32 = I32_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u32 as i32\n }\n}\n\nimpl Serialize for i64 {\n let N: u32 = I64_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as u64 as Field);\n }\n}\n\nimpl Deserialize for i64 {\n let N: u32 = I64_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u64 as i64\n }\n}\n\nimpl<T, let M: u32> Serialize for [T; M]\nwhere\n T: Serialize,\n{\n let N: u32 = <T as Serialize>::N * M;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n for i in 0..M {\n self[i].stream_serialize(writer);\n }\n }\n}\n\nimpl<T, let M: u32> Deserialize for [T; M]\nwhere\n T: Deserialize,\n{\n let N: u32 = <T as Deserialize>::N * M;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n let mut result: [T; M] = std::mem::zeroed();\n for i in 0..M {\n result[i] = T::stream_deserialize(reader);\n }\n result\n }\n}\n\nimpl<T> Serialize for Option<T>\nwhere\n T: Serialize,\n{\n let N: u32 = <T as Serialize>::N + 1;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write_bool(self.is_some());\n if self.is_some() {\n self.unwrap_unchecked().stream_serialize(writer);\n } else {\n writer.advance_offset(<T as Serialize>::N);\n }\n }\n}\n\nimpl<T> Deserialize for Option<T>\nwhere\n T: Deserialize,\n{\n let N: u32 = <T as Deserialize>::N + 1;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n if reader.read_bool() {\n Option::some(<T as Deserialize>::stream_deserialize(reader))\n } else {\n reader.advance_offset(<T as Deserialize>::N);\n Option::none()\n }\n }\n}\n\nglobal SCALAR_SIZE: u32 = 2;\n\nimpl Serialize for EmbeddedCurveScalar {\n\n let N: u32 = SCALAR_SIZE;\n\n fn serialize(self) -> [Field; SCALAR_SIZE] {\n [self.lo, self.hi]\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self.lo);\n writer.write(self.hi);\n }\n}\n\nimpl Deserialize for EmbeddedCurveScalar {\n let N: u32 = SCALAR_SIZE;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n Self { lo: fields[0], hi: fields[1] }\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n Self { lo: reader.read(), hi: reader.read() }\n }\n}\n\nglobal POINT_SIZE: u32 = 2;\n\nimpl Serialize for EmbeddedCurvePoint {\n let N: u32 = POINT_SIZE;\n\n fn serialize(self) -> [Field; Self::N] {\n [self.x, self.y]\n }\n\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self.x);\n writer.write(self.y);\n }\n}\n\nimpl Deserialize for EmbeddedCurvePoint {\n let N: u32 = POINT_SIZE;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n Self { x: fields[0], y: fields[1] }\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n Self { x: reader.read(), y: reader.read() }\n }\n}\n\nimpl<let M: u32> Deserialize for str<M> {\n let N: u32 = M;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n let u8_arr = <[u8; Self::N] as Deserialize>::stream_deserialize(reader);\n str::<Self::N>::from(u8_arr)\n }\n}\n\nimpl<let M: u32> Serialize for str<M> {\n let N: u32 = M;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n self.as_bytes().stream_serialize(writer);\n }\n}\n\n// Note: Not deriving this because it's not supported to call derive_serialize on a \"remote\" struct (and it will never\n// be supported).\nimpl<T, let M: u32> Deserialize for BoundedVec<T, M>\nwhere\n T: Deserialize,\n{\n let N: u32 = <T as Deserialize>::N * M + 1;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n let mut new_bounded_vec: BoundedVec<T, M> = BoundedVec::new();\n let payload_len = Self::N - 1;\n\n // Length is stored in the last field as we need to match intrinsic Noir serialization and the `len` struct\n // field is after `storage` struct field (see `bounded_vec.nr` in noir-stdlib)\n let len = reader.peek_offset(payload_len) as u32;\n\n for i in 0..M {\n if i < len {\n new_bounded_vec.push(<T as Deserialize>::stream_deserialize(reader));\n }\n }\n\n // +1 for the length of the BoundedVec\n reader.advance_offset((M - len) * <T as Deserialize>::N + 1);\n\n new_bounded_vec\n }\n}\n\n// This may cause issues if used as program input, because noir disallows empty arrays for program input.\n// I think this is okay because I don't foresee a unit type being used as input. But leaving this comment as a hint\n// if someone does run into this in the future.\nimpl Deserialize for () {\n let N: u32 = 0;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(_reader: &mut Reader<K>) -> Self {\n ()\n }\n}\n\n// Note: Not deriving this because it's not supported to call derive_serialize on a \"remote\" struct (and it will never\n// be supported).\nimpl<T, let M: u32> Serialize for BoundedVec<T, M>\nwhere\n T: Serialize,\n{\n let N: u32 = <T as Serialize>::N * M + 1; // +1 for the length of the BoundedVec\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n self.storage().stream_serialize(writer);\n // Length is stored in the last field as we need to match intrinsic Noir serialization and the `len` struct\n // field is after `storage` struct field (see `bounded_vec.nr` in noir-stdlib)\n writer.write_u32(self.len() as u32);\n }\n}\n\n// Create a slice of the given length with each element made from `f(i)` where `i` is the current index\ncomptime fn make_slice<Env, T>(length: u32, f: fn[Env](u32) -> T) -> [T] {\n let mut slice = @[];\n for i in 0..length {\n slice = slice.push_back(f(i));\n }\n slice\n}\n\n// Implements Serialize and Deserialize for an arbitrary tuple type\ncomptime fn impl_serialize_for_tuple(_m: Module, length: u32) -> Quoted {\n // `T0`, `T1`, `T2`\n let type_names = make_slice(length, |i| f\"T{i}\".quoted_contents());\n\n // `result0`, `result1`, `result2`\n let result_names = make_slice(length, |i| f\"result{i}\".quoted_contents());\n\n // `T0, T1, T2`\n let field_generics = type_names.join(quote [,]);\n\n // `<T0 as Serialize>::N + <T1 as Serialize>::N + <T2 as Serialize>::N`\n let full_size_serialize = type_names\n .map(|type_name| quote {\n <$type_name as Serialize>::N\n })\n .join(quote [+]);\n\n // `<T0 as Deserialize>::N + <T1 as Deserialize>::N + <T2 as Deserialize>::N`\n let full_size_deserialize = type_names\n .map(|type_name| quote {\n <$type_name as Deserialize>::N\n })\n .join(quote [+]);\n\n // `T0: Serialize, T1: Serialize, T2: Serialize,`\n let serialize_constraints = type_names\n .map(|field_name| quote {\n $field_name: Serialize,\n })\n .join(quote []);\n\n // `T0: Deserialize, T1: Deserialize, T2: Deserialize,`\n let deserialize_constraints = type_names\n .map(|field_name| quote {\n $field_name: Deserialize,\n })\n .join(quote []);\n\n // Statements to serialize each field\n let serialized_fields = type_names\n .mapi(|i, _type_name| quote {\n $crate::serialization::Serialize::stream_serialize(self.$i, writer);\n })\n .join(quote []);\n\n // Statements to deserialize each field\n let deserialized_fields = type_names\n .mapi(|i, type_name| {\n let result_name = result_names[i];\n quote {\n let $result_name = <$type_name as $crate::serialization::Deserialize>::stream_deserialize(reader);\n }\n })\n .join(quote []);\n let deserialize_results = result_names.join(quote [,]);\n\n quote {\n impl<$field_generics> Serialize for ($field_generics) where $serialize_constraints {\n let N: u32 = $full_size_serialize;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: $crate::writer::Writer<Self::N> = $crate::writer::Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut $crate::writer::Writer<K>) {\n\n $serialized_fields\n }\n }\n\n impl<$field_generics> Deserialize for ($field_generics) where $deserialize_constraints {\n let N: u32 = $full_size_deserialize;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = $crate::reader::Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n \n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut $crate::reader::Reader<K>) -> Self {\n $deserialized_fields\n ($deserialize_results)\n }\n }\n }\n}\n\n// Keeping these manual impls. They are more efficient since they do not\n// require copying sub-arrays from any serialized arrays.\nimpl<T1> Serialize for (T1,)\nwhere\n T1: Serialize,\n{\n let N: u32 = <T1 as Serialize>::N;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: crate::writer::Writer<Self::N> = crate::writer::Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n self.0.stream_serialize(writer);\n }\n}\n\nimpl<T1> Deserialize for (T1,)\nwhere\n T1: Deserialize,\n{\n let N: u32 = <T1 as Deserialize>::N;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = crate::reader::Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n (<T1 as Deserialize>::stream_deserialize(reader),)\n }\n}\n\n#[impl_serialize_for_tuple(2)]\n#[impl_serialize_for_tuple(3)]\n#[impl_serialize_for_tuple(4)]\n#[impl_serialize_for_tuple(5)]\n#[impl_serialize_for_tuple(6)]\nmod impls {\n use crate::serialization::{Deserialize, Serialize};\n}\n\n#[test]\nunconstrained fn bounded_vec_serialization() {\n // Test empty BoundedVec\n let empty_vec: BoundedVec<Field, 3> = BoundedVec::from_array([]);\n let serialized = empty_vec.serialize();\n let deserialized = BoundedVec::<Field, 3>::deserialize(serialized);\n assert_eq(empty_vec, deserialized);\n assert_eq(deserialized.len(), 0);\n\n // Test partially filled BoundedVec\n let partial_vec: BoundedVec<[u32; 2], 3> = BoundedVec::from_array([[1, 2]]);\n let serialized = partial_vec.serialize();\n let deserialized = BoundedVec::<[u32; 2], 3>::deserialize(serialized);\n assert_eq(partial_vec, deserialized);\n assert_eq(deserialized.len(), 1);\n assert_eq(deserialized.get(0), [1, 2]);\n\n // Test full BoundedVec\n let full_vec: BoundedVec<[u32; 2], 3> = BoundedVec::from_array([[1, 2], [3, 4], [5, 6]]);\n let serialized = full_vec.serialize();\n let deserialized = BoundedVec::<[u32; 2], 3>::deserialize(serialized);\n assert_eq(full_vec, deserialized);\n assert_eq(deserialized.len(), 3);\n assert_eq(deserialized.get(0), [1, 2]);\n assert_eq(deserialized.get(1), [3, 4]);\n assert_eq(deserialized.get(2), [5, 6]);\n}\n"
|
|
1321
|
+
"source": "use crate::{reader::Reader, serialization::{Deserialize, Serialize}, writer::Writer};\nuse std::embedded_curve_ops::EmbeddedCurvePoint;\nuse std::embedded_curve_ops::EmbeddedCurveScalar;\n\nglobal BOOL_SERIALIZED_LEN: u32 = 1;\nglobal U8_SERIALIZED_LEN: u32 = 1;\nglobal U16_SERIALIZED_LEN: u32 = 1;\nglobal U32_SERIALIZED_LEN: u32 = 1;\nglobal U64_SERIALIZED_LEN: u32 = 1;\nglobal U128_SERIALIZED_LEN: u32 = 1;\nglobal FIELD_SERIALIZED_LEN: u32 = 1;\nglobal I8_SERIALIZED_LEN: u32 = 1;\nglobal I16_SERIALIZED_LEN: u32 = 1;\nglobal I32_SERIALIZED_LEN: u32 = 1;\nglobal I64_SERIALIZED_LEN: u32 = 1;\n\nimpl Serialize for bool {\n let N: u32 = BOOL_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for bool {\n let N: u32 = BOOL_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> bool {\n reader.read() != 0\n }\n}\n\nimpl Serialize for u8 {\n let N: u32 = U8_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u8 {\n let N: u32 = U8_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u8\n }\n}\n\nimpl Serialize for u16 {\n let N: u32 = U16_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u16 {\n let N: u32 = U16_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u16\n }\n}\n\nimpl Serialize for u32 {\n let N: u32 = U32_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u32 {\n let N: u32 = U32_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u32\n }\n}\n\nimpl Serialize for u64 {\n let N: u32 = U64_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u64 {\n let N: u32 = U64_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u64\n }\n}\n\nimpl Serialize for u128 {\n let N: u32 = U128_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u128 {\n let N: u32 = U128_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u128\n }\n}\n\nimpl Serialize for Field {\n let N: u32 = FIELD_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self);\n }\n}\n\nimpl Deserialize for Field {\n let N: u32 = FIELD_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read()\n }\n}\n\nimpl Serialize for i8 {\n let N: u32 = I8_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as u8 as Field);\n }\n}\n\nimpl Deserialize for i8 {\n let N: u32 = I8_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u8 as i8\n }\n}\n\nimpl Serialize for i16 {\n let N: u32 = I16_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as u16 as Field);\n }\n}\n\nimpl Deserialize for i16 {\n let N: u32 = I16_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u16 as i16\n }\n}\n\nimpl Serialize for i32 {\n let N: u32 = I32_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as u32 as Field);\n }\n}\n\nimpl Deserialize for i32 {\n let N: u32 = I32_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u32 as i32\n }\n}\n\nimpl Serialize for i64 {\n let N: u32 = I64_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as u64 as Field);\n }\n}\n\nimpl Deserialize for i64 {\n let N: u32 = I64_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u64 as i64\n }\n}\n\nimpl<T, let M: u32> Serialize for [T; M]\nwhere\n T: Serialize,\n{\n let N: u32 = <T as Serialize>::N * M;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n for i in 0..M {\n self[i].stream_serialize(writer);\n }\n }\n}\n\nimpl<T, let M: u32> Deserialize for [T; M]\nwhere\n T: Deserialize,\n{\n let N: u32 = <T as Deserialize>::N * M;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n let mut result: [T; M] = std::mem::zeroed();\n for i in 0..M {\n result[i] = T::stream_deserialize(reader);\n }\n result\n }\n}\n\nimpl<T> Serialize for Option<T>\nwhere\n T: Serialize,\n{\n let N: u32 = <T as Serialize>::N + 1;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write_bool(self.is_some());\n if self.is_some() {\n self.unwrap_unchecked().stream_serialize(writer);\n } else {\n writer.advance_offset(<T as Serialize>::N);\n }\n }\n}\n\nimpl<T> Deserialize for Option<T>\nwhere\n T: Deserialize,\n{\n let N: u32 = <T as Deserialize>::N + 1;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n if reader.read_bool() {\n Option::some(<T as Deserialize>::stream_deserialize(reader))\n } else {\n reader.advance_offset(<T as Deserialize>::N);\n Option::none()\n }\n }\n}\n\nglobal SCALAR_SIZE: u32 = 2;\n\nimpl Serialize for EmbeddedCurveScalar {\n\n let N: u32 = SCALAR_SIZE;\n\n fn serialize(self) -> [Field; SCALAR_SIZE] {\n [self.lo, self.hi]\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self.lo);\n writer.write(self.hi);\n }\n}\n\nimpl Deserialize for EmbeddedCurveScalar {\n let N: u32 = SCALAR_SIZE;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n Self { lo: fields[0], hi: fields[1] }\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n Self { lo: reader.read(), hi: reader.read() }\n }\n}\n\nglobal POINT_SIZE: u32 = 2;\n\nimpl Serialize for EmbeddedCurvePoint {\n let N: u32 = POINT_SIZE;\n\n fn serialize(self) -> [Field; Self::N] {\n [self.x, self.y]\n }\n\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self.x);\n writer.write(self.y);\n }\n}\n\nimpl Deserialize for EmbeddedCurvePoint {\n let N: u32 = POINT_SIZE;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n Self { x: fields[0], y: fields[1] }\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n Self { x: reader.read(), y: reader.read() }\n }\n}\n\nimpl<let M: u32> Deserialize for str<M> {\n let N: u32 = M;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n let u8_arr = <[u8; Self::N] as Deserialize>::stream_deserialize(reader);\n str::<Self::N>::from(u8_arr)\n }\n}\n\nimpl<let M: u32> Serialize for str<M> {\n let N: u32 = M;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n self.as_bytes().stream_serialize(writer);\n }\n}\n\n// Note: Not deriving this because it's not supported to call derive_serialize on a \"remote\" struct (and it will never\n// be supported).\nimpl<T, let M: u32> Deserialize for BoundedVec<T, M>\nwhere\n T: Deserialize,\n{\n let N: u32 = <T as Deserialize>::N * M + 1;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n let mut new_bounded_vec: BoundedVec<T, M> = BoundedVec::new();\n let payload_len = Self::N - 1;\n\n // Length is stored in the last field as we need to match intrinsic Noir serialization and the `len` struct\n // field is after `storage` struct field (see `bounded_vec.nr` in noir-stdlib)\n let len = reader.peek_offset(payload_len) as u32;\n\n for i in 0..M {\n if i < len {\n new_bounded_vec.push(<T as Deserialize>::stream_deserialize(reader));\n }\n }\n\n // +1 for the length of the BoundedVec\n reader.advance_offset((M - len) * <T as Deserialize>::N + 1);\n\n new_bounded_vec\n }\n}\n\n// This may cause issues if used as program input, because noir disallows empty arrays for program input.\n// I think this is okay because I don't foresee a unit type being used as input. But leaving this comment as a hint\n// if someone does run into this in the future.\nimpl Deserialize for () {\n let N: u32 = 0;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(_reader: &mut Reader<K>) -> Self {\n ()\n }\n}\n\n// Note: Not deriving this because it's not supported to call derive_serialize on a \"remote\" struct (and it will never\n// be supported).\nimpl<T, let M: u32> Serialize for BoundedVec<T, M>\nwhere\n T: Serialize,\n{\n let N: u32 = <T as Serialize>::N * M + 1; // +1 for the length of the BoundedVec\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n self.storage().stream_serialize(writer);\n // Length is stored in the last field as we need to match intrinsic Noir serialization and the `len` struct\n // field is after `storage` struct field (see `bounded_vec.nr` in noir-stdlib)\n writer.write_u32(self.len() as u32);\n }\n}\n\n// Create a slice of the given length with each element made from `f(i)` where `i` is the current index\ncomptime fn make_slice<Env, T>(length: u32, f: fn[Env](u32) -> T) -> [T] {\n let mut slice = @[];\n for i in 0..length {\n slice = slice.push_back(f(i));\n }\n slice\n}\n\n// Implements Serialize and Deserialize for an arbitrary tuple type\ncomptime fn impl_serialize_for_tuple(_m: Module, length: u32) -> Quoted {\n // `T0`, `T1`, `T2`\n let type_names = make_slice(length, |i| f\"T{i}\".quoted_contents());\n\n // `result0`, `result1`, `result2`\n let result_names = make_slice(length, |i| f\"result{i}\".quoted_contents());\n\n // `T0, T1, T2`\n let field_generics = type_names.join(quote [,]);\n\n // `<T0 as Serialize>::N + <T1 as Serialize>::N + <T2 as Serialize>::N`\n let full_size_serialize = type_names\n .map(|type_name| quote {\n <$type_name as Serialize>::N\n })\n .join(quote [+]);\n\n // `<T0 as Deserialize>::N + <T1 as Deserialize>::N + <T2 as Deserialize>::N`\n let full_size_deserialize = type_names\n .map(|type_name| quote {\n <$type_name as Deserialize>::N\n })\n .join(quote [+]);\n\n // `T0: Serialize, T1: Serialize, T2: Serialize,`\n let serialize_constraints = type_names\n .map(|field_name| quote {\n $field_name: Serialize,\n })\n .join(quote []);\n\n // `T0: Deserialize, T1: Deserialize, T2: Deserialize,`\n let deserialize_constraints = type_names\n .map(|field_name| quote {\n $field_name: Deserialize,\n })\n .join(quote []);\n\n // Statements to serialize each field\n let serialized_fields = type_names\n .mapi(|i, _type_name| quote {\n $crate::serialization::Serialize::stream_serialize(self.$i, writer);\n })\n .join(quote []);\n\n // Statements to deserialize each field\n let deserialized_fields = type_names\n .mapi(|i, type_name| {\n let result_name = result_names[i];\n quote {\n let $result_name = <$type_name as $crate::serialization::Deserialize>::stream_deserialize(reader);\n }\n })\n .join(quote []);\n let deserialize_results = result_names.join(quote [,]);\n\n quote {\n impl<$field_generics> Serialize for ($field_generics) where $serialize_constraints {\n let N: u32 = $full_size_serialize;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: $crate::writer::Writer<Self::N> = $crate::writer::Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut $crate::writer::Writer<K>) {\n\n $serialized_fields\n }\n }\n\n impl<$field_generics> Deserialize for ($field_generics) where $deserialize_constraints {\n let N: u32 = $full_size_deserialize;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = $crate::reader::Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n \n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut $crate::reader::Reader<K>) -> Self {\n $deserialized_fields\n ($deserialize_results)\n }\n }\n }\n}\n\n// Keeping these manual impls. They are more efficient since they do not\n// require copying sub-arrays from any serialized arrays.\nimpl<T1> Serialize for (T1,)\nwhere\n T1: Serialize,\n{\n let N: u32 = <T1 as Serialize>::N;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: crate::writer::Writer<Self::N> = crate::writer::Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n self.0.stream_serialize(writer);\n }\n}\n\nimpl<T1> Deserialize for (T1,)\nwhere\n T1: Deserialize,\n{\n let N: u32 = <T1 as Deserialize>::N;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = crate::reader::Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n (<T1 as Deserialize>::stream_deserialize(reader),)\n }\n}\n\n#[impl_serialize_for_tuple(2)]\n#[impl_serialize_for_tuple(3)]\n#[impl_serialize_for_tuple(4)]\n#[impl_serialize_for_tuple(5)]\n#[impl_serialize_for_tuple(6)]\nmod impls {\n use crate::serialization::{Deserialize, Serialize};\n}\n\n#[test]\nunconstrained fn bounded_vec_serialization() {\n // Test empty BoundedVec\n let empty_vec: BoundedVec<Field, 3> = BoundedVec::from_array([]);\n let serialized = empty_vec.serialize();\n let deserialized = BoundedVec::<Field, 3>::deserialize(serialized);\n assert_eq(empty_vec, deserialized);\n assert_eq(deserialized.len(), 0);\n\n // Test partially filled BoundedVec\n let partial_vec: BoundedVec<[u32; 2], 3> = BoundedVec::from_array([[1, 2]]);\n let serialized = partial_vec.serialize();\n let deserialized = BoundedVec::<[u32; 2], 3>::deserialize(serialized);\n assert_eq(partial_vec, deserialized);\n assert_eq(deserialized.len(), 1);\n assert_eq(deserialized.get(0), [1, 2]);\n\n // Test full BoundedVec\n let full_vec: BoundedVec<[u32; 2], 3> = BoundedVec::from_array([[1, 2], [3, 4], [5, 6]]);\n let serialized = full_vec.serialize();\n let deserialized = BoundedVec::<[u32; 2], 3>::deserialize(serialized);\n assert_eq(full_vec, deserialized);\n assert_eq(deserialized.len(), 3);\n assert_eq(deserialized.get(0), [1, 2]);\n assert_eq(deserialized.get(1), [3, 4]);\n assert_eq(deserialized.get(2), [5, 6]);\n}\n"
|
|
1198
1322
|
},
|
|
1199
1323
|
"256": {
|
|
1200
1324
|
"function_locations": [
|
|
@@ -1278,7 +1402,7 @@
|
|
|
1278
1402
|
"path": "/home/aztec-dev/nargo/github.com/noir-lang/sha256/v0.3.0/src/sha256.nr",
|
|
1279
1403
|
"source": "use std::hash::sha256_compression;\nuse std::runtime::is_unconstrained;\n\nuse constants::{\n BLOCK_BYTE_PTR, BLOCK_SIZE, HASH, INITIAL_STATE, INT_BLOCK_SIZE, INT_SIZE, INT_SIZE_PTR,\n MSG_BLOCK, MSG_SIZE_PTR, STATE, TWO_POW_16, TWO_POW_24, TWO_POW_32, TWO_POW_8,\n};\n\npub(crate) mod constants;\nmod tests;\nmod oracle_tests;\n\n// Implementation of SHA-256 mapping a byte array of variable length to\n// 32 bytes.\n\n// Deprecated in favour of `sha256_var`\n// docs:start:sha256\npub fn sha256<let N: u32>(input: [u8; N]) -> HASH\n// docs:end:sha256\n{\n digest(input)\n}\n\n// SHA-256 hash function\n#[no_predicates]\npub fn digest<let N: u32>(msg: [u8; N]) -> HASH {\n sha256_var(msg, N)\n}\n\n// Variable size SHA-256 hash\npub fn sha256_var<let N: u32>(msg: [u8; N], message_size: u32) -> HASH {\n assert(message_size <= N);\n\n let (h, msg_block) = process_full_blocks(msg, message_size, INITIAL_STATE);\n\n finalize_sha256_blocks(message_size, h, msg_block)\n}\n\n/// Returns the first partially filled message block along with the internal state prior to its compression.\npub(crate) fn process_full_blocks<let N: u32>(\n msg: [u8; N],\n message_size: u32,\n initial_state: STATE,\n) -> (STATE, MSG_BLOCK) {\n if std::runtime::is_unconstrained() {\n let num_full_blocks = message_size / BLOCK_SIZE;\n // Intermediate hash, starting with the canonical initial value\n let mut h: STATE = initial_state;\n // Pointer into msg_block on a 64 byte scale\n for i in 0..num_full_blocks {\n let msg_block = build_msg_block(msg, message_size, BLOCK_SIZE * i);\n h = sha256_compression(msg_block, h);\n }\n\n // We now build the final un-filled block.\n let msg_byte_ptr = message_size % BLOCK_SIZE;\n let msg_block: MSG_BLOCK = if msg_byte_ptr != 0 {\n let num_full_blocks = message_size / BLOCK_SIZE;\n let msg_start = BLOCK_SIZE * num_full_blocks;\n build_msg_block(msg, message_size, msg_start)\n } else {\n // If the message size is a multiple of the block size (i.e. `msg_byte_ptr == 0`) then this block will be empty,\n // so we short-circuit in this case.\n [0; 16]\n };\n\n (h, msg_block)\n } else {\n let num_blocks = N / BLOCK_SIZE;\n\n // We store the intermediate hash states and message blocks in these two arrays which allows us to select the correct state\n // for the given message size with a lookup.\n //\n // These can be reasoned about as followed:\n // Consider a message with an unknown number of bytes, `msg_size. It can be seen that this will have `msg_size / BLOCK_SIZE` full blocks.\n // - `states[i]` should then be the state after processing the first `i` blocks.\n // - `blocks[i]` should then be the next message block after processing the first `i` blocks.\n // blocks[first_partially_filled_block_index] is the last block that is partially filled or all 0 if the message is a multiple of the block size.\n //\n // In other words:\n //\n // blocks = [block 1, block 2, ..., block N / BLOCK_SIZE, block N / BLOCK_SIZE + 1]\n // states = [INITIAL_STATE, state after block 1, state after block 2, ..., state after block N / BLOCK_SIZE]\n //\n // We place the initial state in `states[0]` as in the case where the `message_size < BLOCK_SIZE` then there are no full blocks to process and no compressions should occur.\n let mut blocks: [MSG_BLOCK; N / BLOCK_SIZE + 1] = std::mem::zeroed();\n let mut states: [STATE; N / BLOCK_SIZE + 1] = [initial_state; N / BLOCK_SIZE + 1];\n\n // Optimization for small messages. If the largest possible message is smaller than a block then we know that the first block is partially filled\n // no matter the value of `message_size`.\n //\n // Note that the condition `N >= BLOCK_SIZE` is known during monomorphization so this has no runtime cost.\n let first_partially_filled_block_index = if N >= BLOCK_SIZE {\n message_size / BLOCK_SIZE\n } else {\n 0\n };\n\n for i in 0..num_blocks {\n let msg_start = BLOCK_SIZE * i;\n let new_msg_block = build_msg_block(msg, message_size, msg_start);\n\n blocks[i] = new_msg_block;\n states[i + 1] = sha256_compression(new_msg_block, states[i]);\n }\n // If message_size/BLOCK_SIZE == N/BLOCK_SIZE, and there is a remainder, we need to process the last block.\n if N % BLOCK_SIZE != 0 {\n let new_msg_block = build_msg_block(msg, message_size, BLOCK_SIZE * num_blocks);\n\n blocks[num_blocks] = new_msg_block;\n }\n\n (states[first_partially_filled_block_index], blocks[first_partially_filled_block_index])\n }\n}\n\n// Take `BLOCK_SIZE` number of bytes from `msg` starting at `msg_start` and pack them into a `MSG_BLOCK`.\npub(crate) unconstrained fn build_msg_block_helper<let N: u32>(\n msg: [u8; N],\n message_size: u32,\n msg_start: u32,\n) -> MSG_BLOCK {\n let mut msg_block: MSG_BLOCK = [0; INT_BLOCK_SIZE];\n\n // We insert `BLOCK_SIZE` bytes (or up to the end of the message)\n let block_input = if message_size < msg_start {\n // This function is sometimes called with `msg_start` past the end of the message.\n // In this case we return an empty block and zero pointer to signal that the result should be ignored.\n 0\n } else if message_size < msg_start + BLOCK_SIZE {\n message_size - msg_start\n } else {\n BLOCK_SIZE\n };\n\n // Figure out the number of items in the int array that we have to pack.\n // e.g. if the input is [0,1,2,3,4,5] then we need to pack it as 2 items: [0123, 4500]\n let int_input = (block_input + INT_SIZE - 1) / INT_SIZE;\n\n for i in 0..int_input {\n let mut msg_item: u32 = 0;\n // Always construct the integer as 4 bytes, even if it means going beyond the input.\n for j in 0..INT_SIZE {\n let k = i * INT_SIZE + j;\n let msg_byte = if k < block_input {\n msg[msg_start + k]\n } else {\n 0\n };\n msg_item = (msg_item << 8) + msg_byte as u32;\n }\n msg_block[i] = msg_item;\n }\n\n // Returning the index as if it was a 64 byte array.\n // We have to project it down to 16 items and bit shifting to get a byte back if we need it.\n msg_block\n}\n\n// Build a message block from the input message starting at `msg_start`.\n//\n// If `message_size` is less than `msg_start` then this is called with the old non-empty block;\n// in that case we can skip verification, ie. no need to check that everything is zero.\nfn build_msg_block<let N: u32>(msg: [u8; N], message_size: u32, msg_start: u32) -> MSG_BLOCK {\n let msg_block =\n // Safety: We constrain the block below by reconstructing each `u32` word from the input bytes.\n unsafe { build_msg_block_helper(msg, message_size, msg_start) };\n\n if !is_unconstrained() {\n let mut msg_end = msg_start + BLOCK_SIZE;\n\n let max_read_index = std::cmp::min(message_size, msg_end);\n\n // Reconstructed packed item\n let mut msg_item: Field = 0;\n\n // Inclusive at the end so that we can compare the last item.\n for k in msg_start..=msg_end {\n if (k != msg_start) & (k % INT_SIZE == 0) {\n // If we consumed some input we can compare against the block.\n let msg_block_index = (k - msg_start) / INT_SIZE - 1;\n assert_eq(msg_block[msg_block_index] as Field, msg_item);\n\n msg_item = 0;\n }\n\n // If we have input to consume, add it at the rightmost position.\n let msg_byte = if k < max_read_index { msg[k] } else { 0 };\n msg_item = msg_item * (TWO_POW_8 as Field) + msg_byte as Field;\n }\n }\n msg_block\n}\n\n// Encode `8 * message_size` into two `u32` limbs.\nunconstrained fn encode_len(message_size: u32) -> (u32, u32) {\n let len = 8 * message_size as u64;\n let lo = len & 0xFFFFFFFF;\n let hi = (len >> 32) & 0xFFFFFFFF;\n (lo as u32, hi as u32)\n}\n\n// Write the length into the last 8 bytes of the block.\nfn attach_len_to_msg_block(mut msg_block: MSG_BLOCK, message_size: u32) -> MSG_BLOCK {\n // Safety: We assert the correctness of the decomposition below.\n // 2 `u32` limbs cannot overflow the field modulus so performing the check as `Field`s is safe.\n let (lo, hi) = unsafe { encode_len(message_size) };\n assert_eq(8 * (message_size as Field), lo as Field + hi as Field * TWO_POW_32);\n\n msg_block[INT_SIZE_PTR] = hi;\n msg_block[INT_SIZE_PTR + 1] = lo;\n msg_block\n}\n\n// Perform the final compression, then transform the `STATE` into `HASH`.\nfn hash_final_block(msg_block: MSG_BLOCK, mut state: STATE) -> HASH {\n // Hash final padded block\n state = sha256_compression(msg_block, state);\n\n // Return final hash as byte array\n let mut out_h: HASH = [0; 32]; // Digest as sequence of bytes\n for j in 0..8 {\n let h_bytes: [u8; 4] = (state[j] as Field).to_be_bytes();\n for k in 0..4 {\n out_h[4 * j + k] = h_bytes[k];\n }\n }\n\n out_h\n}\n\n/// Lookup table for the position of the padding bit within one of the `u32` words in the final message block.\nglobal PADDING_BIT_TABLE: [u32; 4] =\n [(1 << 7) * TWO_POW_24, (1 << 7) * TWO_POW_16, (1 << 7) * TWO_POW_8, (1 << 7)];\n\n/// Add 1 bit padding to end of message and compress the block if there's not enough room for the 8-byte length.\n/// Returns the updated hash state and message block that will be used to write the message size.\n///\n/// # Assumptions:\n///\n/// - `msg_block[i] == 0` for all `i > msg_byte_ptr / INT_SIZE`\n/// - `msg_block[msg_byte_ptr / INT_SIZE] & ((1 << 7) * (msg_byte_ptr % INT_SIZE)) == 0`\nfn add_padding_byte_and_compress_if_needed(\n mut msg_block: MSG_BLOCK,\n msg_byte_ptr: BLOCK_BYTE_PTR,\n h: STATE,\n) -> (STATE, MSG_BLOCK) {\n // Pad the rest such that we have a [u32; 2] block at the end representing the length\n // of the message, and a block of 1 0 ... 0 following the message (i.e. [1 << 7, 0, ..., 0]).\n // Here we rely on the fact that everything beyond the available input is set to 0.\n let index = msg_byte_ptr / INT_SIZE;\n\n // Lookup the position of the padding bit and insert it into the message block.\n msg_block[index] += PADDING_BIT_TABLE[msg_byte_ptr % INT_SIZE];\n\n // If we don't have room to write the size, compress the block and reset it.\n if msg_byte_ptr >= MSG_SIZE_PTR {\n let h = sha256_compression(msg_block, h);\n\n // In this case, the final block consists of all zeros with the last 8 bytes containing the length.\n // We set msg_block to all zeros and attach_len_to_msg_block will add the length to the last 8 bytes.\n let msg_block = [0; INT_BLOCK_SIZE];\n (h, msg_block)\n } else {\n (h, msg_block)\n }\n}\n\npub(crate) fn finalize_sha256_blocks(\n message_size: u32,\n mut h: STATE,\n mut msg_block: MSG_BLOCK,\n) -> HASH {\n let msg_byte_ptr = message_size % BLOCK_SIZE;\n\n let (h, mut msg_block) = add_padding_byte_and_compress_if_needed(msg_block, msg_byte_ptr, h);\n\n msg_block = attach_len_to_msg_block(msg_block, message_size);\n\n hash_final_block(msg_block, h)\n}\n\n/**\n * Given some state of a partially computed sha256 hash and part of the preimage, continue hashing\n * @notice used for complex/ recursive offloading of post-partial hashing\n *\n * @param N - the maximum length of the message to hash\n * @param h - the intermediate hash state\n * @param msg - the preimage to hash\n * @param message_size - the actual length of the preimage to hash\n * @return the intermediate hash state after compressing in msg to h\n */\npub fn partial_sha256_var_interstitial<let N: u32>(\n mut h: [u32; 8],\n msg: [u8; N],\n message_size: u32,\n) -> [u32; 8] {\n assert(message_size % BLOCK_SIZE == 0, \"Message size must be a multiple of the block size\");\n if std::runtime::is_unconstrained() {\n // Safety: running as an unconstrained function\n unsafe {\n __sha_partial_var_interstitial(h, msg, message_size)\n }\n } else {\n let (h, _) = process_full_blocks(msg, message_size, h);\n\n h\n }\n}\n\n/**\n * Given some state of a partially computed sha256 hash and remaining preimage, complete the hash\n * @notice used for traditional partial hashing\n *\n * @param N - the maximum length of the message to hash\n * @param h - the intermediate hash state\n * @param msg - the remaining preimage to hash\n * @param message_size - the size of the current chunk\n * @param real_message_size - the total size of the original preimage\n * @return finalized sha256 hash\n */\npub fn partial_sha256_var_end<let N: u32>(\n mut h: [u32; 8],\n msg: [u8; N],\n message_size: u32,\n real_message_size: u32,\n) -> [u8; 32] {\n assert(message_size % BLOCK_SIZE == 0, \"Message size must be a multiple of the block size\");\n if std::runtime::is_unconstrained() {\n // Safety: running as an unconstrained function\n unsafe {\n h = __sha_partial_var_interstitial(h, msg, message_size);\n\n // Handle setup of the final msg block.\n // This case is only hit if the msg is less than the block size,\n // or our message cannot be evenly split into blocks.\n\n finalize_last_sha256_block(h, real_message_size, msg)\n }\n } else {\n let (h, msg_block) = process_full_blocks(msg, message_size, h);\n finalize_sha256_blocks(real_message_size, h, msg_block)\n }\n}\n\nunconstrained fn __sha_partial_var_interstitial<let N: u32>(\n mut h: [u32; 8],\n msg: [u8; N],\n message_size: u32,\n) -> [u32; 8] {\n let num_full_blocks = message_size / BLOCK_SIZE;\n // Intermediate hash, starting with the canonical initial value\n // Pointer into msg_block on a 64 byte scale\n for i in 0..num_full_blocks {\n let msg_block = build_msg_block(msg, message_size, BLOCK_SIZE * i);\n h = sha256_compression(msg_block, h);\n }\n h\n}\n\n// Helper function to finalize the message block with padding and length\nunconstrained fn finalize_last_sha256_block<let N: u32>(\n mut h: STATE,\n message_size: u32,\n msg: [u8; N],\n) -> HASH {\n let msg_byte_ptr = message_size % BLOCK_SIZE;\n\n // We now build the final un-filled block.\n let msg_block: MSG_BLOCK = if msg_byte_ptr != 0 {\n let num_full_blocks = message_size / BLOCK_SIZE;\n let msg_start = BLOCK_SIZE * num_full_blocks;\n build_msg_block(msg, message_size, msg_start)\n } else {\n // If the message size is a multiple of the block size (i.e. `msg_byte_ptr == 0`) then this block will be empty,\n // so we short-circuit in this case.\n [0; 16]\n };\n\n // Once built, we need to add the necessary padding bytes and encoded length\n let (h, mut msg_block) = add_padding_byte_and_compress_if_needed(msg_block, msg_byte_ptr, h);\n msg_block = attach_len_to_msg_block(msg_block, message_size);\n\n hash_final_block(msg_block, h)\n}\n\nmod test_process_full_blocks {\n\n /// Wrapper to force an unconstrained runtime on process_full_blocks.\n unconstrained fn unconstrained_process_full_blocks<let N: u32>(\n msg: [u8; N],\n message_size: u32,\n h: super::STATE,\n ) -> (super::STATE, super::MSG_BLOCK) {\n super::process_full_blocks(msg, message_size, h)\n }\n\n #[test]\n fn test_implementations_agree(msg: [u8; 100], message_size: u32) {\n let message_size = message_size % 100;\n // Safety: test function\n let unconstrained_state =\n unsafe { unconstrained_process_full_blocks(msg, message_size, super::INITIAL_STATE) };\n let state = super::process_full_blocks(msg, message_size, super::INITIAL_STATE);\n assert_eq(state, unconstrained_state);\n }\n}\n\nmod test_sha256_var {\n\n /// Wrapper to force an unconstrained runtime on sha256.\n unconstrained fn unconstrained_sha256<let N: u32>(\n msg: [u8; N],\n message_size: u32,\n ) -> super::HASH {\n super::sha256_var(msg, message_size)\n }\n\n #[test]\n fn test_implementations_agree(msg: [u8; 100], message_size: u32) {\n let message_size = message_size % 100;\n // Safety: test function\n let unconstrained_sha = unsafe { unconstrained_sha256(msg, message_size) };\n let sha = super::sha256_var(msg, message_size);\n assert_eq(sha, unconstrained_sha);\n }\n\n}\n"
|
|
1280
1404
|
},
|
|
1281
|
-
"
|
|
1405
|
+
"40": {
|
|
1282
1406
|
"function_locations": [
|
|
1283
1407
|
{
|
|
1284
1408
|
"name": "<impl Add for Field>::add",
|
|
@@ -1653,70 +1777,194 @@
|
|
|
1653
1777
|
"start": 12477
|
|
1654
1778
|
},
|
|
1655
1779
|
{
|
|
1656
|
-
"name": "tests::arithmetic::
|
|
1657
|
-
"start":
|
|
1780
|
+
"name": "tests::arithmetic::add::u8_overflow",
|
|
1781
|
+
"start": 14265
|
|
1782
|
+
},
|
|
1783
|
+
{
|
|
1784
|
+
"name": "tests::arithmetic::add::u16_overflow",
|
|
1785
|
+
"start": 14423
|
|
1786
|
+
},
|
|
1787
|
+
{
|
|
1788
|
+
"name": "tests::arithmetic::add::i8_overflow",
|
|
1789
|
+
"start": 14584
|
|
1790
|
+
},
|
|
1791
|
+
{
|
|
1792
|
+
"name": "tests::arithmetic::add::i16_overflow",
|
|
1793
|
+
"start": 14742
|
|
1794
|
+
},
|
|
1795
|
+
{
|
|
1796
|
+
"name": "tests::arithmetic::add::i32_overflow",
|
|
1797
|
+
"start": 14904
|
|
1798
|
+
},
|
|
1799
|
+
{
|
|
1800
|
+
"name": "tests::arithmetic::add::i64_overflow",
|
|
1801
|
+
"start": 15071
|
|
1802
|
+
},
|
|
1803
|
+
{
|
|
1804
|
+
"name": "tests::arithmetic::sub::u8_overflow",
|
|
1805
|
+
"start": 15525
|
|
1806
|
+
},
|
|
1807
|
+
{
|
|
1808
|
+
"name": "tests::arithmetic::sub::u16_overflow",
|
|
1809
|
+
"start": 15686
|
|
1658
1810
|
},
|
|
1659
1811
|
{
|
|
1660
|
-
"name": "tests::arithmetic::
|
|
1661
|
-
"start":
|
|
1812
|
+
"name": "tests::arithmetic::sub::i8_overflow",
|
|
1813
|
+
"start": 15848
|
|
1662
1814
|
},
|
|
1663
1815
|
{
|
|
1664
|
-
"name": "tests::arithmetic::
|
|
1665
|
-
"start":
|
|
1816
|
+
"name": "tests::arithmetic::sub::i16_overflow",
|
|
1817
|
+
"start": 16045
|
|
1666
1818
|
},
|
|
1667
1819
|
{
|
|
1668
|
-
"name": "tests::arithmetic::
|
|
1669
|
-
"start":
|
|
1820
|
+
"name": "tests::arithmetic::sub::i32_overflow",
|
|
1821
|
+
"start": 16246
|
|
1670
1822
|
},
|
|
1671
1823
|
{
|
|
1672
|
-
"name": "tests::arithmetic::
|
|
1673
|
-
"start":
|
|
1824
|
+
"name": "tests::arithmetic::sub::i64_overflow",
|
|
1825
|
+
"start": 16452
|
|
1674
1826
|
},
|
|
1675
1827
|
{
|
|
1676
|
-
"name": "tests::arithmetic::
|
|
1677
|
-
"start":
|
|
1828
|
+
"name": "tests::arithmetic::mul::u8_overflow",
|
|
1829
|
+
"start": 17058
|
|
1678
1830
|
},
|
|
1679
1831
|
{
|
|
1680
|
-
"name": "tests::arithmetic::
|
|
1681
|
-
"start":
|
|
1832
|
+
"name": "tests::arithmetic::mul::u16_overflow",
|
|
1833
|
+
"start": 17221
|
|
1682
1834
|
},
|
|
1683
1835
|
{
|
|
1684
|
-
"name": "tests::arithmetic::
|
|
1685
|
-
"start":
|
|
1836
|
+
"name": "tests::arithmetic::mul::i8_min_times_neg_one_overflow",
|
|
1837
|
+
"start": 17405
|
|
1838
|
+
},
|
|
1839
|
+
{
|
|
1840
|
+
"name": "tests::arithmetic::mul::i16_min_times_neg_one_overflow",
|
|
1841
|
+
"start": 17621
|
|
1842
|
+
},
|
|
1843
|
+
{
|
|
1844
|
+
"name": "tests::arithmetic::mul::i32_min_times_neg_one_overflow",
|
|
1845
|
+
"start": 17841
|
|
1846
|
+
},
|
|
1847
|
+
{
|
|
1848
|
+
"name": "tests::arithmetic::mul::i64_min_times_neg_one_overflow",
|
|
1849
|
+
"start": 18066
|
|
1850
|
+
},
|
|
1851
|
+
{
|
|
1852
|
+
"name": "tests::arithmetic::div::i8_min_by_neg_one_overflow",
|
|
1853
|
+
"start": 18601
|
|
1854
|
+
},
|
|
1855
|
+
{
|
|
1856
|
+
"name": "tests::arithmetic::div::i16_min_by_neg_one_overflow",
|
|
1857
|
+
"start": 18812
|
|
1858
|
+
},
|
|
1859
|
+
{
|
|
1860
|
+
"name": "tests::arithmetic::div::i32_min_by_neg_one_overflow",
|
|
1861
|
+
"start": 19027
|
|
1862
|
+
},
|
|
1863
|
+
{
|
|
1864
|
+
"name": "tests::arithmetic::div::i64_min_by_neg_one_overflow",
|
|
1865
|
+
"start": 19247
|
|
1866
|
+
},
|
|
1867
|
+
{
|
|
1868
|
+
"name": "tests::arithmetic::rem::i8_min_by_neg_one_overflow",
|
|
1869
|
+
"start": 19840
|
|
1870
|
+
},
|
|
1871
|
+
{
|
|
1872
|
+
"name": "tests::arithmetic::rem::i16_min_by_neg_one_overflow",
|
|
1873
|
+
"start": 20068
|
|
1874
|
+
},
|
|
1875
|
+
{
|
|
1876
|
+
"name": "tests::arithmetic::rem::i32_min_by_neg_one_overflow",
|
|
1877
|
+
"start": 20300
|
|
1878
|
+
},
|
|
1879
|
+
{
|
|
1880
|
+
"name": "tests::arithmetic::rem::i64_min_by_neg_one_overflow",
|
|
1881
|
+
"start": 20537
|
|
1882
|
+
},
|
|
1883
|
+
{
|
|
1884
|
+
"name": "tests::arithmetic::neg::i8_min_overflow",
|
|
1885
|
+
"start": 21490
|
|
1886
|
+
},
|
|
1887
|
+
{
|
|
1888
|
+
"name": "tests::arithmetic::neg::i16_min_overflow",
|
|
1889
|
+
"start": 21668
|
|
1890
|
+
},
|
|
1891
|
+
{
|
|
1892
|
+
"name": "tests::arithmetic::neg::i32_min_overflow",
|
|
1893
|
+
"start": 21849
|
|
1894
|
+
},
|
|
1895
|
+
{
|
|
1896
|
+
"name": "tests::arithmetic::neg::i64_min_overflow",
|
|
1897
|
+
"start": 22035
|
|
1686
1898
|
},
|
|
1687
1899
|
{
|
|
1688
1900
|
"name": "tests::arithmetic::test_field",
|
|
1689
|
-
"start":
|
|
1901
|
+
"start": 22190
|
|
1690
1902
|
},
|
|
1691
1903
|
{
|
|
1692
1904
|
"name": "tests::wrapping_arithmetic::test_wrapping_add",
|
|
1693
|
-
"start":
|
|
1905
|
+
"start": 22787
|
|
1694
1906
|
},
|
|
1695
1907
|
{
|
|
1696
1908
|
"name": "tests::wrapping_arithmetic::test_wrapping_sub",
|
|
1697
|
-
"start":
|
|
1909
|
+
"start": 24537
|
|
1698
1910
|
},
|
|
1699
1911
|
{
|
|
1700
1912
|
"name": "tests::wrapping_arithmetic::test_wrapping_mul",
|
|
1701
|
-
"start":
|
|
1913
|
+
"start": 25877
|
|
1702
1914
|
},
|
|
1703
1915
|
{
|
|
1704
1916
|
"name": "tests::wrapping_arithmetic::test_wrapping_vs_regular",
|
|
1705
|
-
"start":
|
|
1917
|
+
"start": 28094
|
|
1706
1918
|
},
|
|
1707
1919
|
{
|
|
1708
1920
|
"name": "tests::wrapping_arithmetic::test_field_wrapping_operations",
|
|
1709
|
-
"start":
|
|
1921
|
+
"start": 28727
|
|
1710
1922
|
},
|
|
1711
1923
|
{
|
|
1712
1924
|
"name": "tests::split_functions::test_split_functions",
|
|
1713
|
-
"start":
|
|
1925
|
+
"start": 29811
|
|
1926
|
+
},
|
|
1927
|
+
{
|
|
1928
|
+
"name": "tests::traits::add",
|
|
1929
|
+
"start": 31149
|
|
1930
|
+
},
|
|
1931
|
+
{
|
|
1932
|
+
"name": "tests::traits::sub",
|
|
1933
|
+
"start": 31596
|
|
1934
|
+
},
|
|
1935
|
+
{
|
|
1936
|
+
"name": "tests::traits::mul",
|
|
1937
|
+
"start": 32043
|
|
1938
|
+
},
|
|
1939
|
+
{
|
|
1940
|
+
"name": "tests::traits::div",
|
|
1941
|
+
"start": 32490
|
|
1942
|
+
},
|
|
1943
|
+
{
|
|
1944
|
+
"name": "tests::traits::rem",
|
|
1945
|
+
"start": 32937
|
|
1946
|
+
},
|
|
1947
|
+
{
|
|
1948
|
+
"name": "tests::traits::neg",
|
|
1949
|
+
"start": 33342
|
|
1950
|
+
},
|
|
1951
|
+
{
|
|
1952
|
+
"name": "tests::traits::wrapping_add",
|
|
1953
|
+
"start": 33556
|
|
1954
|
+
},
|
|
1955
|
+
{
|
|
1956
|
+
"name": "tests::traits::wrapping_sub",
|
|
1957
|
+
"start": 34244
|
|
1958
|
+
},
|
|
1959
|
+
{
|
|
1960
|
+
"name": "tests::traits::wrapping_mul",
|
|
1961
|
+
"start": 34940
|
|
1714
1962
|
}
|
|
1715
1963
|
],
|
|
1716
1964
|
"path": "std/ops/arith.nr",
|
|
1717
|
-
"source": "use crate::convert::AsPrimitive;\n\n// docs:start:add-trait\npub trait Add {\n fn add(self, other: Self) -> Self;\n}\n// docs:end:add-trait\n\nimpl Add for Field {\n fn add(self, other: Field) -> Field {\n self + other\n }\n}\n\nimpl Add for u128 {\n fn add(self, other: u128) -> u128 {\n self + other\n }\n}\nimpl Add for u64 {\n fn add(self, other: u64) -> u64 {\n self + other\n }\n}\nimpl Add for u32 {\n fn add(self, other: u32) -> u32 {\n self + other\n }\n}\nimpl Add for u16 {\n fn add(self, other: u16) -> u16 {\n self + other\n }\n}\nimpl Add for u8 {\n fn add(self, other: u8) -> u8 {\n self + other\n }\n}\nimpl Add for i8 {\n fn add(self, other: i8) -> i8 {\n self + other\n }\n}\nimpl Add for i16 {\n fn add(self, other: i16) -> i16 {\n self + other\n }\n}\nimpl Add for i32 {\n fn add(self, other: i32) -> i32 {\n self + other\n }\n}\nimpl Add for i64 {\n fn add(self, other: i64) -> i64 {\n self + other\n }\n}\n\n// docs:start:sub-trait\npub trait Sub {\n fn sub(self, other: Self) -> Self;\n}\n// docs:end:sub-trait\n\nimpl Sub for Field {\n fn sub(self, other: Field) -> Field {\n self - other\n }\n}\n\nimpl Sub for u128 {\n fn sub(self, other: u128) -> u128 {\n self - other\n }\n}\nimpl Sub for u64 {\n fn sub(self, other: u64) -> u64 {\n self - other\n }\n}\nimpl Sub for u32 {\n fn sub(self, other: u32) -> u32 {\n self - other\n }\n}\nimpl Sub for u16 {\n fn sub(self, other: u16) -> u16 {\n self - other\n }\n}\nimpl Sub for u8 {\n fn sub(self, other: u8) -> u8 {\n self - other\n }\n}\nimpl Sub for i8 {\n fn sub(self, other: i8) -> i8 {\n self - other\n }\n}\nimpl Sub for i16 {\n fn sub(self, other: i16) -> i16 {\n self - other\n }\n}\nimpl Sub for i32 {\n fn sub(self, other: i32) -> i32 {\n self - other\n }\n}\nimpl Sub for i64 {\n fn sub(self, other: i64) -> i64 {\n self - other\n }\n}\n\n// docs:start:mul-trait\npub trait Mul {\n fn mul(self, other: Self) -> Self;\n}\n// docs:end:mul-trait\n\nimpl Mul for Field {\n fn mul(self, other: Field) -> Field {\n self * other\n }\n}\n\nimpl Mul for u128 {\n fn mul(self, other: u128) -> u128 {\n self * other\n }\n}\nimpl Mul for u64 {\n fn mul(self, other: u64) -> u64 {\n self * other\n }\n}\nimpl Mul for u32 {\n fn mul(self, other: u32) -> u32 {\n self * other\n }\n}\nimpl Mul for u16 {\n fn mul(self, other: u16) -> u16 {\n self * other\n }\n}\nimpl Mul for u8 {\n fn mul(self, other: u8) -> u8 {\n self * other\n }\n}\nimpl Mul for i8 {\n fn mul(self, other: i8) -> i8 {\n self * other\n }\n}\nimpl Mul for i16 {\n fn mul(self, other: i16) -> i16 {\n self * other\n }\n}\nimpl Mul for i32 {\n fn mul(self, other: i32) -> i32 {\n self * other\n }\n}\nimpl Mul for i64 {\n fn mul(self, other: i64) -> i64 {\n self * other\n }\n}\n\n// docs:start:div-trait\npub trait Div {\n fn div(self, other: Self) -> Self;\n}\n// docs:end:div-trait\n\nimpl Div for Field {\n fn div(self, other: Field) -> Field {\n self / other\n }\n}\n\nimpl Div for u128 {\n fn div(self, other: u128) -> u128 {\n self / other\n }\n}\nimpl Div for u64 {\n fn div(self, other: u64) -> u64 {\n self / other\n }\n}\nimpl Div for u32 {\n fn div(self, other: u32) -> u32 {\n self / other\n }\n}\nimpl Div for u16 {\n fn div(self, other: u16) -> u16 {\n self / other\n }\n}\nimpl Div for u8 {\n fn div(self, other: u8) -> u8 {\n self / other\n }\n}\nimpl Div for i8 {\n fn div(self, other: i8) -> i8 {\n self / other\n }\n}\nimpl Div for i16 {\n fn div(self, other: i16) -> i16 {\n self / other\n }\n}\nimpl Div for i32 {\n fn div(self, other: i32) -> i32 {\n self / other\n }\n}\nimpl Div for i64 {\n fn div(self, other: i64) -> i64 {\n self / other\n }\n}\n\n// docs:start:rem-trait\npub trait Rem {\n fn rem(self, other: Self) -> Self;\n}\n// docs:end:rem-trait\n\nimpl Rem for u128 {\n fn rem(self, other: u128) -> u128 {\n self % other\n }\n}\nimpl Rem for u64 {\n fn rem(self, other: u64) -> u64 {\n self % other\n }\n}\nimpl Rem for u32 {\n fn rem(self, other: u32) -> u32 {\n self % other\n }\n}\nimpl Rem for u16 {\n fn rem(self, other: u16) -> u16 {\n self % other\n }\n}\nimpl Rem for u8 {\n fn rem(self, other: u8) -> u8 {\n self % other\n }\n}\nimpl Rem for i8 {\n fn rem(self, other: i8) -> i8 {\n self % other\n }\n}\nimpl Rem for i16 {\n fn rem(self, other: i16) -> i16 {\n self % other\n }\n}\nimpl Rem for i32 {\n fn rem(self, other: i32) -> i32 {\n self % other\n }\n}\nimpl Rem for i64 {\n fn rem(self, other: i64) -> i64 {\n self % other\n }\n}\n\n// docs:start:neg-trait\npub trait Neg {\n fn neg(self) -> Self;\n}\n// docs:end:neg-trait\n\n// docs:start:neg-trait-impls\nimpl Neg for Field {\n fn neg(self) -> Field {\n -self\n }\n}\n\nimpl Neg for i8 {\n fn neg(self) -> i8 {\n -self\n }\n}\nimpl Neg for i16 {\n fn neg(self) -> i16 {\n -self\n }\n}\nimpl Neg for i32 {\n fn neg(self) -> i32 {\n -self\n }\n}\nimpl Neg for i64 {\n fn neg(self) -> i64 {\n -self\n }\n}\n// docs:end:neg-trait-impls\n\n// docs:start:wrapping-add-trait\npub trait WrappingAdd {\n fn wrapping_add(self, y: Self) -> Self;\n}\n// docs:end:wrapping-add-trait\n\nimpl WrappingAdd for u8 {\n fn wrapping_add(self: u8, y: u8) -> u8 {\n wrapping_add_hlp(self, y)\n }\n}\n\nimpl WrappingAdd for u16 {\n fn wrapping_add(self: u16, y: u16) -> u16 {\n wrapping_add_hlp(self, y)\n }\n}\n\nimpl WrappingAdd for u32 {\n fn wrapping_add(self: u32, y: u32) -> u32 {\n wrapping_add_hlp(self, y)\n }\n}\n\nimpl WrappingAdd for u64 {\n fn wrapping_add(self: u64, y: u64) -> u64 {\n wrapping_add_hlp(self, y)\n }\n}\n\nimpl WrappingAdd for u128 {\n fn wrapping_add(self: u128, y: u128) -> u128 {\n wrapping_add_hlp(self, y)\n }\n}\n\nimpl WrappingAdd for i8 {\n fn wrapping_add(self: i8, y: i8) -> i8 {\n let x = self as u8;\n x.wrapping_add(y as u8) as i8\n }\n}\n\nimpl WrappingAdd for i16 {\n fn wrapping_add(self: i16, y: i16) -> i16 {\n let x = self as u16;\n x.wrapping_add(y as u16) as i16\n }\n}\n\nimpl WrappingAdd for i32 {\n fn wrapping_add(self: i32, y: i32) -> i32 {\n let x = self as u32;\n x.wrapping_add(y as u32) as i32\n }\n}\n\nimpl WrappingAdd for i64 {\n fn wrapping_add(self: i64, y: i64) -> i64 {\n let x = self as u64;\n x.wrapping_add(y as u64) as i64\n }\n}\nimpl WrappingAdd for Field {\n fn wrapping_add(self: Field, y: Field) -> Field {\n self + y\n }\n}\n\n// docs:start:wrapping-sub-trait\npub trait WrappingSub {\n fn wrapping_sub(self, y: Self) -> Self;\n}\n// docs:start:wrapping-sub-trait\n\nimpl WrappingSub for u8 {\n fn wrapping_sub(self: u8, y: u8) -> u8 {\n wrapping_sub_hlp(self, y) as u8\n }\n}\n\nimpl WrappingSub for u16 {\n fn wrapping_sub(self: u16, y: u16) -> u16 {\n wrapping_sub_hlp(self, y) as u16\n }\n}\n\nimpl WrappingSub for u32 {\n fn wrapping_sub(self: u32, y: u32) -> u32 {\n wrapping_sub_hlp(self, y) as u32\n }\n}\nimpl WrappingSub for u64 {\n fn wrapping_sub(self: u64, y: u64) -> u64 {\n wrapping_sub_hlp(self, y) as u64\n }\n}\nimpl WrappingSub for u128 {\n fn wrapping_sub(self: u128, y: u128) -> u128 {\n wrapping_sub_hlp(self, y) as u128\n }\n}\n\nimpl WrappingSub for i8 {\n fn wrapping_sub(self: i8, y: i8) -> i8 {\n let x = self as u8;\n x.wrapping_sub(y as u8) as i8\n }\n}\n\nimpl WrappingSub for i16 {\n fn wrapping_sub(self: i16, y: i16) -> i16 {\n let x = self as u16;\n x.wrapping_sub(y as u16) as i16\n }\n}\n\nimpl WrappingSub for i32 {\n fn wrapping_sub(self: i32, y: i32) -> i32 {\n let x = self as u32;\n x.wrapping_sub(y as u32) as i32\n }\n}\nimpl WrappingSub for i64 {\n fn wrapping_sub(self: i64, y: i64) -> i64 {\n let x = self as u64;\n x.wrapping_sub(y as u64) as i64\n }\n}\nimpl WrappingSub for Field {\n fn wrapping_sub(self: Field, y: Field) -> Field {\n self - y\n }\n}\n\n// docs:start:wrapping-mul-trait\npub trait WrappingMul {\n fn wrapping_mul(self, y: Self) -> Self;\n}\n// docs:start:wrapping-mul-trait\n\nimpl WrappingMul for u8 {\n fn wrapping_mul(self: u8, y: u8) -> u8 {\n wrapping_mul_hlp(self, y)\n }\n}\n\nimpl WrappingMul for u16 {\n fn wrapping_mul(self: u16, y: u16) -> u16 {\n wrapping_mul_hlp(self, y)\n }\n}\n\nimpl WrappingMul for u32 {\n fn wrapping_mul(self: u32, y: u32) -> u32 {\n wrapping_mul_hlp(self, y)\n }\n}\nimpl WrappingMul for u64 {\n fn wrapping_mul(self: u64, y: u64) -> u64 {\n wrapping_mul_hlp(self, y)\n }\n}\n\nimpl WrappingMul for i8 {\n fn wrapping_mul(self: i8, y: i8) -> i8 {\n let x = self as u8;\n x.wrapping_mul(y as u8) as i8\n }\n}\n\nimpl WrappingMul for i16 {\n fn wrapping_mul(self: i16, y: i16) -> i16 {\n let x = self as u16;\n x.wrapping_mul(y as u16) as i16\n }\n}\n\nimpl WrappingMul for i32 {\n fn wrapping_mul(self: i32, y: i32) -> i32 {\n let x = self as u32;\n x.wrapping_mul(y as u32) as i32\n }\n}\n\nimpl WrappingMul for i64 {\n fn wrapping_mul(self: i64, y: i64) -> i64 {\n let x = self as u64;\n x.wrapping_mul(y as u64) as i64\n }\n}\n\nimpl WrappingMul for u128 {\n fn wrapping_mul(self: u128, y: u128) -> u128 {\n wrapping_mul128_hlp(self, y)\n }\n}\nimpl WrappingMul for Field {\n fn wrapping_mul(self: Field, y: Field) -> Field {\n self * y\n }\n}\n\nfn wrapping_add_hlp<T>(x: T, y: T) -> T\nwhere\n T: AsPrimitive<Field>,\n Field: AsPrimitive<T>,\n{\n AsPrimitive::as_(x.as_() + y.as_())\n}\n\nfn wrapping_sub_hlp<T>(x: T, y: T) -> Field\nwhere\n T: AsPrimitive<Field>,\n{\n //340282366920938463463374607431768211456 is 2^128, it is used to avoid underflow\n x.as_() + 340282366920938463463374607431768211456 - y.as_()\n}\n\nfn wrapping_mul_hlp<T>(x: T, y: T) -> T\nwhere\n T: AsPrimitive<Field>,\n Field: AsPrimitive<T>,\n{\n AsPrimitive::as_(x.as_() * y.as_())\n}\n\nglobal two_pow_64: u128 = 0x10000000000000000;\n/// Splits a 128 bits number into two 64 bits limbs\nunconstrained fn split64(x: u128) -> (u64, u64) {\n let lo = x as u64;\n let hi = (x / two_pow_64) as u64;\n (lo, hi)\n}\n\n/// Split a 128 bits number into two 64 bits limbs\n/// It will fail if the number is more than 128 bits\nfn split_into_64_bit_limbs(x: u128) -> (u64, u64) {\n // Safety: the limbs are constrained below\n let (x_lo, x_hi) = unsafe { split64(x) };\n assert(x as Field == x_lo as Field + x_hi as Field * two_pow_64 as Field);\n (x_lo, x_hi)\n}\n\n#[field(bn254)]\nfn wrapping_mul128_hlp(x: u128, y: u128) -> u128 {\n let (x_lo, x_hi) = split_into_64_bit_limbs(x);\n let (y_lo, y_hi) = split_into_64_bit_limbs(y);\n // Multiplication using the limbs:(x_lo + 2**64*x_hi)*(y_lo + 2**64*y_hi)=x_lo*y_lo+...\n // and skipping the terms over 2**128\n // Working with u64 limbs ensures that we cannot overflow the field modulus.\n let low = x_lo as Field * y_lo as Field;\n let lo = low as u64 as Field;\n let carry = (low - lo) / two_pow_64 as Field;\n let high = x_lo as Field * y_hi as Field + x_hi as Field * y_lo as Field + carry;\n let hi = high as u64 as Field;\n (lo + two_pow_64 as Field * hi) as u128\n}\n\nmod tests {\n #[test(should_fail_with = \"custom message\")]\n fn test_static_assert_custom_message() {\n crate::static_assert(1 == 2, \"custom message\");\n }\n\n mod arithmetic {\n use crate::ops::arith::{Add, Div, Mul, Neg, Rem, Sub};\n #[test]\n fn test_basic_arithmetic_traits() {\n // add\n assert_eq(5.add(3), 8);\n assert_eq(0u8.add(255u8), 255u8);\n assert_eq(42.add(58), 100);\n\n // sub\n assert_eq(10.sub(3), 7);\n assert_eq(100.sub(42), 58);\n\n // mul\n assert_eq(6.mul(7), 42);\n\n // div\n assert_eq(15.div(3), 5);\n assert_eq(10u8.div(3u8), 3u8);\n assert_eq(15.div(3), 5);\n\n // rem (Field doesn't implement Rem)\n assert_eq(17u64.rem(5u64), 2u64);\n assert_eq(10u8.rem(3u8), 1u8);\n\n // neg\n assert_eq(42.neg(), -42);\n assert_eq((-10).neg(), 10);\n assert_eq(42.neg(), -42);\n }\n\n #[test]\n fn test_division() {\n // test division by one\n assert_eq(42.div(1), 42);\n assert_eq(0.div(1), 0);\n assert_eq(255u8.div(1u8), 255u8);\n\n // test division by self\n assert_eq(42.div(42), 1);\n assert_eq(1.div(1), 1);\n\n // test remainder (Field doesn't implement Rem)\n assert_eq(42u32.rem(42u32), 0u32);\n assert_eq(0u16.rem(42u16), 0u16);\n assert_eq(1u64.rem(42u64), 1u64);\n }\n\n #[test(should_fail)]\n fn test_u8_sub_overflow_failure() {\n let _ = 0u8.sub(1u8);\n }\n\n #[test(should_fail)]\n fn test_u8_add_overflow_failure() {\n let _ = 255u8.add(1u8);\n }\n\n #[test(should_fail)]\n fn test_u8_mul_overflow_failure() {\n let _ = 255u8.mul(2u8);\n }\n\n #[test(should_fail)]\n fn test_u16_sub_overflow_failure() {\n let _ = 0u16.sub(1u16);\n }\n\n #[test(should_fail)]\n fn test_u16_add_overflow_failure() {\n let _ = 65535u16.add(1u16);\n }\n\n #[test(should_fail)]\n fn test_u16_mul_overflow_failure() {\n let _ = 65535u16.mul(2u16);\n }\n\n #[test(should_fail)]\n fn test_signed_sub_overflow_failure() {\n let val: i8 = -128;\n let _ = val.sub(1i8);\n }\n\n #[test(should_fail)]\n fn test_signed_overflow_failure() {\n let _ = 127i8.add(1i8);\n }\n\n #[test]\n fn test_field() {\n let zero: Field = 0;\n let one: Field = 1;\n\n // test Field basic operations\n assert_eq(zero.add(one), one);\n assert_eq(one.add(zero), one);\n assert_eq(one.sub(one), zero);\n assert_eq(one.mul(one), one);\n assert_eq(one.div(one), one);\n assert_eq(zero.neg(), zero);\n assert_eq(one.neg(), -one);\n }\n\n }\n\n mod wrapping_arithmetic {\n use crate::ops::arith::{Add, Div, Mul, Neg, Sub, WrappingAdd, WrappingMul, WrappingSub};\n #[test]\n fn test_wrapping_add() {\n assert_eq(255u8.wrapping_add(1u8), 0u8);\n assert_eq(255u8.wrapping_add(255u8), 254u8);\n assert_eq(0u8.wrapping_add(0u8), 0u8);\n assert_eq(128u8.wrapping_add(128u8), 0u8);\n\n // test u16 wrapping add\n assert_eq(65535u16.wrapping_add(1u16), 0u16);\n assert_eq(65535u16.wrapping_add(65535u16), 65534u16);\n\n // test u32 wrapping add\n assert_eq(0xffffffffu32.wrapping_add(1u32), 0u32);\n assert_eq(0xffffffffu32.wrapping_add(0xffffffffu32), 0xfffffffeu32);\n\n // test u64 wrapping add\n assert_eq(0xffffffffffffffffu64.wrapping_add(1u64), 0u64);\n assert_eq(\n 0xffffffffffffffffu64.wrapping_add(0xffffffffffffffffu64),\n 0xfffffffffffffffeu64,\n );\n\n // test u128 wrapping add\n assert_eq(0xffffffffffffffffffffffffffffffffu128.wrapping_add(1u128), 0u128);\n\n // test signed types\n assert_eq(127i8.wrapping_add(1i8), -128i8);\n let val: i8 = -128;\n assert_eq(val.wrapping_add(-1i8), 127i8);\n\n // test Field wrapping add\n let forty_two: Field = 42;\n let fifty_eight: Field = 58;\n let hundred: Field = 100;\n let neg_two: Field = -2;\n let two: Field = 2;\n let zero: Field = 0;\n let neg_two_hundred: Field = -200;\n let neg_one_ninety_eight: Field = -198;\n assert_eq(forty_two.wrapping_add(fifty_eight), hundred);\n assert_eq(neg_two.wrapping_add(two), zero);\n assert_eq(neg_two_hundred.wrapping_add(two), neg_one_ninety_eight);\n }\n\n #[test]\n fn test_wrapping_sub() {\n assert_eq(0u8.wrapping_sub(1u8), 255u8);\n assert_eq(255u8.wrapping_sub(255u8), 0u8);\n assert_eq(0u8.wrapping_sub(0u8), 0u8);\n assert_eq(1u8.wrapping_sub(2u8), 255u8);\n\n // test u16 wrapping sub\n assert_eq(0u16.wrapping_sub(1u16), 65535u16);\n assert_eq(65535u16.wrapping_sub(65535u16), 0u16);\n\n // test u32 wrapping sub\n assert_eq(0u32.wrapping_sub(1u32), 0xffffffffu32);\n assert_eq(0xffffffffu32.wrapping_sub(0xffffffffu32), 0u32);\n\n // test u64 wrapping sub\n assert_eq(0u64.wrapping_sub(1u64), 0xffffffffffffffffu64);\n assert_eq(0xffffffffffffffffu64.wrapping_sub(0xffffffffffffffffu64), 0u64);\n\n // test u128 wrapping sub\n assert_eq(0u128.wrapping_sub(1u128), 0xffffffffffffffffffffffffffffffffu128);\n\n // test signed types\n let val: i8 = -128;\n assert_eq(val.wrapping_sub(1i8), 127i8);\n assert_eq(127i8.wrapping_sub(-1i8), -128i8);\n\n // test Field wrapping sub\n let forty_two: Field = 42;\n let fifty_eight: Field = 58;\n let neg_sixteen: Field = -16;\n assert_eq(forty_two.wrapping_sub(fifty_eight), neg_sixteen);\n }\n\n #[test]\n fn test_wrapping_mul() {\n let zero: u128 = 0;\n let one: u128 = 1;\n let two_pow_64: u128 = 0x10000000000000000;\n let u128_max: u128 = 0xffffffffffffffffffffffffffffffff;\n\n assert_eq(zero, zero.wrapping_mul(one));\n assert_eq(zero, one.wrapping_mul(zero));\n assert_eq(one, one.wrapping_mul(one));\n assert_eq(zero, zero.wrapping_mul(two_pow_64));\n assert_eq(zero, two_pow_64.wrapping_mul(zero));\n assert_eq(two_pow_64, two_pow_64.wrapping_mul(one));\n assert_eq(two_pow_64, one.wrapping_mul(two_pow_64));\n assert_eq(zero, two_pow_64.wrapping_mul(two_pow_64));\n assert_eq(one, u128_max.wrapping_mul(u128_max));\n\n // test u8 wrapping mul\n assert_eq(255u8.wrapping_mul(2u8), 254u8);\n assert_eq(255u8.wrapping_mul(255u8), 1u8);\n assert_eq(128u8.wrapping_mul(2u8), 0u8);\n\n // test u16 wrapping mul\n assert_eq(65535u16.wrapping_mul(2u16), 65534u16);\n assert_eq(65535u16.wrapping_mul(65535u16), 1u16);\n\n // test u32 wrapping mul\n assert_eq(0xffffffffu32.wrapping_mul(2u32), 0xfffffffeu32);\n assert_eq(0xffffffffu32.wrapping_mul(0xffffffffu32), 1u32);\n\n // test u64 wrapping mul\n // 0xffffffffffffffffu64 is 2^64 - 1\n assert_eq(0xffffffffffffffffu64.wrapping_mul(2u64), 0xfffffffffffffffeu64);\n assert_eq(0xffffffffffffffffu64.wrapping_mul(0xffffffffffffffffu64), 1u64);\n\n // test signed types\n assert_eq(127i8.wrapping_mul(2i8), -2i8);\n let val: i8 = -128;\n assert_eq(val.wrapping_mul(-1i8), -128i8);\n\n // test Field wrapping mul\n let six: Field = 6;\n let seven: Field = 7;\n let forty_two: Field = 42;\n let neg_two: Field = -2;\n let two: Field = 2;\n let neg_four: Field = -4;\n assert_eq(six.wrapping_mul(seven), forty_two);\n assert_eq(neg_two.wrapping_mul(two), neg_four);\n }\n\n // test wrapping operations is the same as the regular operations\n #[test]\n fn test_wrapping_vs_regular() {\n let u64_large = 0x123456789abcdef0u64;\n let u128_large = 0x123456789abcdef0123456789abcdef0u128;\n\n assert_eq(u64_large.wrapping_add(1u64), u64_large + 1u64);\n assert_eq(u64_large.wrapping_sub(1u64), u64_large - 1u64);\n assert_eq(u64_large.wrapping_mul(2u64), u64_large * 2u64);\n\n assert_eq(u128_large.wrapping_add(1u128), u128_large + 1u128);\n assert_eq(u128_large.wrapping_sub(1u128), u128_large - 1u128);\n assert_eq(u128_large.wrapping_mul(2u128), u128_large * 2u128);\n }\n\n #[test]\n fn test_field_wrapping_operations() {\n let zero: Field = 0;\n let one: Field = 1;\n let large_val = 0xffffffffffffffff;\n\n // test Field wrapping operations\n assert_eq(zero.wrapping_add(one), one);\n assert_eq(one.wrapping_add(large_val), one + large_val);\n assert_eq(zero.wrapping_sub(one), -one);\n assert_eq(one.wrapping_sub(large_val), one - large_val);\n assert_eq(zero.wrapping_mul(one), zero);\n assert_eq(one.wrapping_mul(large_val), large_val);\n\n // test Field basic operations\n assert_eq(zero.add(one), one);\n assert_eq(one.add(zero), one);\n assert_eq(one.sub(one), zero);\n assert_eq(one.mul(one), one);\n assert_eq(one.div(one), one);\n assert_eq(zero.neg(), zero);\n assert_eq(one.neg(), -one);\n }\n\n }\n\n mod split_functions {\n\n use crate::ops::arith::{split64, split_into_64_bit_limbs};\n\n // test split64 and split_into_64_bit_limbs functions\n #[test]\n fn test_split_functions() {\n let small_val = 0x123456789abcdefu128;\n let large_val = 0x123456789abcdef0123456789abcdef0u128;\n let max_val = 0xffffffffffffffffffffffffffffffffu128;\n\n // test split64 (unconstrained)\n // Safety: testing\n unsafe {\n let (lo, hi) = split64(small_val);\n assert_eq(lo, 0x123456789abcdefu64);\n assert_eq(hi, 0u64);\n\n let (lo2, hi2) = split64(large_val);\n assert_eq(lo2, 0x123456789abcdef0u64);\n assert_eq(hi2, 0x123456789abcdef0u64);\n }\n\n // test split_into_64_bit_limbs (constrained)\n let (lo3, hi3) = split_into_64_bit_limbs(small_val);\n assert_eq(lo3, 0x123456789abcdefu64);\n assert_eq(hi3, 0u64);\n\n let (lo4, hi4) = split_into_64_bit_limbs(large_val);\n assert_eq(lo4, 0x123456789abcdef0u64);\n assert_eq(hi4, 0x123456789abcdef0u64);\n\n let (lo5, hi5) = split_into_64_bit_limbs(max_val);\n assert_eq(lo5, 0xffffffffffffffffu64);\n assert_eq(hi5, 0xffffffffffffffffu64);\n }\n }\n}\n"
|
|
1965
|
+
"source": "use crate::convert::AsPrimitive;\n\n// docs:start:add-trait\npub trait Add {\n fn add(self, other: Self) -> Self;\n}\n// docs:end:add-trait\n\nimpl Add for Field {\n fn add(self, other: Field) -> Field {\n self + other\n }\n}\n\nimpl Add for u128 {\n fn add(self, other: u128) -> u128 {\n self + other\n }\n}\nimpl Add for u64 {\n fn add(self, other: u64) -> u64 {\n self + other\n }\n}\nimpl Add for u32 {\n fn add(self, other: u32) -> u32 {\n self + other\n }\n}\nimpl Add for u16 {\n fn add(self, other: u16) -> u16 {\n self + other\n }\n}\nimpl Add for u8 {\n fn add(self, other: u8) -> u8 {\n self + other\n }\n}\nimpl Add for i8 {\n fn add(self, other: i8) -> i8 {\n self + other\n }\n}\nimpl Add for i16 {\n fn add(self, other: i16) -> i16 {\n self + other\n }\n}\nimpl Add for i32 {\n fn add(self, other: i32) -> i32 {\n self + other\n }\n}\nimpl Add for i64 {\n fn add(self, other: i64) -> i64 {\n self + other\n }\n}\n\n// docs:start:sub-trait\npub trait Sub {\n fn sub(self, other: Self) -> Self;\n}\n// docs:end:sub-trait\n\nimpl Sub for Field {\n fn sub(self, other: Field) -> Field {\n self - other\n }\n}\n\nimpl Sub for u128 {\n fn sub(self, other: u128) -> u128 {\n self - other\n }\n}\nimpl Sub for u64 {\n fn sub(self, other: u64) -> u64 {\n self - other\n }\n}\nimpl Sub for u32 {\n fn sub(self, other: u32) -> u32 {\n self - other\n }\n}\nimpl Sub for u16 {\n fn sub(self, other: u16) -> u16 {\n self - other\n }\n}\nimpl Sub for u8 {\n fn sub(self, other: u8) -> u8 {\n self - other\n }\n}\nimpl Sub for i8 {\n fn sub(self, other: i8) -> i8 {\n self - other\n }\n}\nimpl Sub for i16 {\n fn sub(self, other: i16) -> i16 {\n self - other\n }\n}\nimpl Sub for i32 {\n fn sub(self, other: i32) -> i32 {\n self - other\n }\n}\nimpl Sub for i64 {\n fn sub(self, other: i64) -> i64 {\n self - other\n }\n}\n\n// docs:start:mul-trait\npub trait Mul {\n fn mul(self, other: Self) -> Self;\n}\n// docs:end:mul-trait\n\nimpl Mul for Field {\n fn mul(self, other: Field) -> Field {\n self * other\n }\n}\n\nimpl Mul for u128 {\n fn mul(self, other: u128) -> u128 {\n self * other\n }\n}\nimpl Mul for u64 {\n fn mul(self, other: u64) -> u64 {\n self * other\n }\n}\nimpl Mul for u32 {\n fn mul(self, other: u32) -> u32 {\n self * other\n }\n}\nimpl Mul for u16 {\n fn mul(self, other: u16) -> u16 {\n self * other\n }\n}\nimpl Mul for u8 {\n fn mul(self, other: u8) -> u8 {\n self * other\n }\n}\nimpl Mul for i8 {\n fn mul(self, other: i8) -> i8 {\n self * other\n }\n}\nimpl Mul for i16 {\n fn mul(self, other: i16) -> i16 {\n self * other\n }\n}\nimpl Mul for i32 {\n fn mul(self, other: i32) -> i32 {\n self * other\n }\n}\nimpl Mul for i64 {\n fn mul(self, other: i64) -> i64 {\n self * other\n }\n}\n\n// docs:start:div-trait\npub trait Div {\n fn div(self, other: Self) -> Self;\n}\n// docs:end:div-trait\n\nimpl Div for Field {\n fn div(self, other: Field) -> Field {\n self / other\n }\n}\n\nimpl Div for u128 {\n fn div(self, other: u128) -> u128 {\n self / other\n }\n}\nimpl Div for u64 {\n fn div(self, other: u64) -> u64 {\n self / other\n }\n}\nimpl Div for u32 {\n fn div(self, other: u32) -> u32 {\n self / other\n }\n}\nimpl Div for u16 {\n fn div(self, other: u16) -> u16 {\n self / other\n }\n}\nimpl Div for u8 {\n fn div(self, other: u8) -> u8 {\n self / other\n }\n}\nimpl Div for i8 {\n fn div(self, other: i8) -> i8 {\n self / other\n }\n}\nimpl Div for i16 {\n fn div(self, other: i16) -> i16 {\n self / other\n }\n}\nimpl Div for i32 {\n fn div(self, other: i32) -> i32 {\n self / other\n }\n}\nimpl Div for i64 {\n fn div(self, other: i64) -> i64 {\n self / other\n }\n}\n\n// docs:start:rem-trait\npub trait Rem {\n fn rem(self, other: Self) -> Self;\n}\n// docs:end:rem-trait\n\nimpl Rem for u128 {\n fn rem(self, other: u128) -> u128 {\n self % other\n }\n}\nimpl Rem for u64 {\n fn rem(self, other: u64) -> u64 {\n self % other\n }\n}\nimpl Rem for u32 {\n fn rem(self, other: u32) -> u32 {\n self % other\n }\n}\nimpl Rem for u16 {\n fn rem(self, other: u16) -> u16 {\n self % other\n }\n}\nimpl Rem for u8 {\n fn rem(self, other: u8) -> u8 {\n self % other\n }\n}\nimpl Rem for i8 {\n fn rem(self, other: i8) -> i8 {\n self % other\n }\n}\nimpl Rem for i16 {\n fn rem(self, other: i16) -> i16 {\n self % other\n }\n}\nimpl Rem for i32 {\n fn rem(self, other: i32) -> i32 {\n self % other\n }\n}\nimpl Rem for i64 {\n fn rem(self, other: i64) -> i64 {\n self % other\n }\n}\n\n// docs:start:neg-trait\npub trait Neg {\n fn neg(self) -> Self;\n}\n// docs:end:neg-trait\n\n// docs:start:neg-trait-impls\nimpl Neg for Field {\n fn neg(self) -> Field {\n -self\n }\n}\n\nimpl Neg for i8 {\n fn neg(self) -> i8 {\n -self\n }\n}\nimpl Neg for i16 {\n fn neg(self) -> i16 {\n -self\n }\n}\nimpl Neg for i32 {\n fn neg(self) -> i32 {\n -self\n }\n}\nimpl Neg for i64 {\n fn neg(self) -> i64 {\n -self\n }\n}\n// docs:end:neg-trait-impls\n\n// docs:start:wrapping-add-trait\npub trait WrappingAdd {\n fn wrapping_add(self, y: Self) -> Self;\n}\n// docs:end:wrapping-add-trait\n\nimpl WrappingAdd for u8 {\n fn wrapping_add(self: u8, y: u8) -> u8 {\n wrapping_add_hlp(self, y)\n }\n}\n\nimpl WrappingAdd for u16 {\n fn wrapping_add(self: u16, y: u16) -> u16 {\n wrapping_add_hlp(self, y)\n }\n}\n\nimpl WrappingAdd for u32 {\n fn wrapping_add(self: u32, y: u32) -> u32 {\n wrapping_add_hlp(self, y)\n }\n}\n\nimpl WrappingAdd for u64 {\n fn wrapping_add(self: u64, y: u64) -> u64 {\n wrapping_add_hlp(self, y)\n }\n}\n\nimpl WrappingAdd for u128 {\n fn wrapping_add(self: u128, y: u128) -> u128 {\n wrapping_add_hlp(self, y)\n }\n}\n\nimpl WrappingAdd for i8 {\n fn wrapping_add(self: i8, y: i8) -> i8 {\n let x = self as u8;\n x.wrapping_add(y as u8) as i8\n }\n}\n\nimpl WrappingAdd for i16 {\n fn wrapping_add(self: i16, y: i16) -> i16 {\n let x = self as u16;\n x.wrapping_add(y as u16) as i16\n }\n}\n\nimpl WrappingAdd for i32 {\n fn wrapping_add(self: i32, y: i32) -> i32 {\n let x = self as u32;\n x.wrapping_add(y as u32) as i32\n }\n}\n\nimpl WrappingAdd for i64 {\n fn wrapping_add(self: i64, y: i64) -> i64 {\n let x = self as u64;\n x.wrapping_add(y as u64) as i64\n }\n}\nimpl WrappingAdd for Field {\n fn wrapping_add(self: Field, y: Field) -> Field {\n self + y\n }\n}\n\n// docs:start:wrapping-sub-trait\npub trait WrappingSub {\n fn wrapping_sub(self, y: Self) -> Self;\n}\n// docs:start:wrapping-sub-trait\n\nimpl WrappingSub for u8 {\n fn wrapping_sub(self: u8, y: u8) -> u8 {\n wrapping_sub_hlp(self, y) as u8\n }\n}\n\nimpl WrappingSub for u16 {\n fn wrapping_sub(self: u16, y: u16) -> u16 {\n wrapping_sub_hlp(self, y) as u16\n }\n}\n\nimpl WrappingSub for u32 {\n fn wrapping_sub(self: u32, y: u32) -> u32 {\n wrapping_sub_hlp(self, y) as u32\n }\n}\nimpl WrappingSub for u64 {\n fn wrapping_sub(self: u64, y: u64) -> u64 {\n wrapping_sub_hlp(self, y) as u64\n }\n}\nimpl WrappingSub for u128 {\n fn wrapping_sub(self: u128, y: u128) -> u128 {\n wrapping_sub_hlp(self, y) as u128\n }\n}\n\nimpl WrappingSub for i8 {\n fn wrapping_sub(self: i8, y: i8) -> i8 {\n let x = self as u8;\n x.wrapping_sub(y as u8) as i8\n }\n}\n\nimpl WrappingSub for i16 {\n fn wrapping_sub(self: i16, y: i16) -> i16 {\n let x = self as u16;\n x.wrapping_sub(y as u16) as i16\n }\n}\n\nimpl WrappingSub for i32 {\n fn wrapping_sub(self: i32, y: i32) -> i32 {\n let x = self as u32;\n x.wrapping_sub(y as u32) as i32\n }\n}\nimpl WrappingSub for i64 {\n fn wrapping_sub(self: i64, y: i64) -> i64 {\n let x = self as u64;\n x.wrapping_sub(y as u64) as i64\n }\n}\nimpl WrappingSub for Field {\n fn wrapping_sub(self: Field, y: Field) -> Field {\n self - y\n }\n}\n\n// docs:start:wrapping-mul-trait\npub trait WrappingMul {\n fn wrapping_mul(self, y: Self) -> Self;\n}\n// docs:start:wrapping-mul-trait\n\nimpl WrappingMul for u8 {\n fn wrapping_mul(self: u8, y: u8) -> u8 {\n wrapping_mul_hlp(self, y)\n }\n}\n\nimpl WrappingMul for u16 {\n fn wrapping_mul(self: u16, y: u16) -> u16 {\n wrapping_mul_hlp(self, y)\n }\n}\n\nimpl WrappingMul for u32 {\n fn wrapping_mul(self: u32, y: u32) -> u32 {\n wrapping_mul_hlp(self, y)\n }\n}\nimpl WrappingMul for u64 {\n fn wrapping_mul(self: u64, y: u64) -> u64 {\n wrapping_mul_hlp(self, y)\n }\n}\n\nimpl WrappingMul for i8 {\n fn wrapping_mul(self: i8, y: i8) -> i8 {\n let x = self as u8;\n x.wrapping_mul(y as u8) as i8\n }\n}\n\nimpl WrappingMul for i16 {\n fn wrapping_mul(self: i16, y: i16) -> i16 {\n let x = self as u16;\n x.wrapping_mul(y as u16) as i16\n }\n}\n\nimpl WrappingMul for i32 {\n fn wrapping_mul(self: i32, y: i32) -> i32 {\n let x = self as u32;\n x.wrapping_mul(y as u32) as i32\n }\n}\n\nimpl WrappingMul for i64 {\n fn wrapping_mul(self: i64, y: i64) -> i64 {\n let x = self as u64;\n x.wrapping_mul(y as u64) as i64\n }\n}\n\nimpl WrappingMul for u128 {\n fn wrapping_mul(self: u128, y: u128) -> u128 {\n wrapping_mul128_hlp(self, y)\n }\n}\nimpl WrappingMul for Field {\n fn wrapping_mul(self: Field, y: Field) -> Field {\n self * y\n }\n}\n\nfn wrapping_add_hlp<T>(x: T, y: T) -> T\nwhere\n T: AsPrimitive<Field>,\n Field: AsPrimitive<T>,\n{\n AsPrimitive::as_(x.as_() + y.as_())\n}\n\nfn wrapping_sub_hlp<T>(x: T, y: T) -> Field\nwhere\n T: AsPrimitive<Field>,\n{\n //340282366920938463463374607431768211456 is 2^128, it is used to avoid underflow\n x.as_() + 340282366920938463463374607431768211456 - y.as_()\n}\n\nfn wrapping_mul_hlp<T>(x: T, y: T) -> T\nwhere\n T: AsPrimitive<Field>,\n Field: AsPrimitive<T>,\n{\n AsPrimitive::as_(x.as_() * y.as_())\n}\n\nglobal two_pow_64: u128 = 0x10000000000000000;\n/// Splits a 128 bits number into two 64 bits limbs\nunconstrained fn split64(x: u128) -> (u64, u64) {\n let lo = x as u64;\n let hi = (x / two_pow_64) as u64;\n (lo, hi)\n}\n\n/// Split a 128 bits number into two 64 bits limbs\n/// It will fail if the number is more than 128 bits\nfn split_into_64_bit_limbs(x: u128) -> (u64, u64) {\n // Safety: the limbs are constrained below\n let (x_lo, x_hi) = unsafe { split64(x) };\n assert(x as Field == x_lo as Field + x_hi as Field * two_pow_64 as Field);\n (x_lo, x_hi)\n}\n\n#[field(bn254)]\nfn wrapping_mul128_hlp(x: u128, y: u128) -> u128 {\n let (x_lo, x_hi) = split_into_64_bit_limbs(x);\n let (y_lo, y_hi) = split_into_64_bit_limbs(y);\n // Multiplication using the limbs:(x_lo + 2**64*x_hi)*(y_lo + 2**64*y_hi)=x_lo*y_lo+...\n // and skipping the terms over 2**128\n // Working with u64 limbs ensures that we cannot overflow the field modulus.\n let low = x_lo as Field * y_lo as Field;\n let lo = low as u64 as Field;\n let carry = (low - lo) / two_pow_64 as Field;\n let high = x_lo as Field * y_hi as Field + x_hi as Field * y_lo as Field + carry;\n let hi = high as u64 as Field;\n (lo + two_pow_64 as Field * hi) as u128\n}\n\nmod tests {\n #[test(should_fail_with = \"custom message\")]\n fn test_static_assert_custom_message() {\n crate::static_assert(1 == 2, \"custom message\");\n }\n\n mod arithmetic {\n use crate::ops::arith::{Add, Div, Mul, Neg, Rem, Sub};\n #[test]\n fn test_basic_arithmetic_traits() {\n // add\n assert_eq(5.add(3), 8);\n assert_eq(0u8.add(255u8), 255u8);\n assert_eq(42.add(58), 100);\n\n // sub\n assert_eq(10.sub(3), 7);\n assert_eq(100.sub(42), 58);\n\n // mul\n assert_eq(6.mul(7), 42);\n\n // div\n assert_eq(15.div(3), 5);\n assert_eq(10u8.div(3u8), 3u8);\n assert_eq(15.div(3), 5);\n\n // rem (Field doesn't implement Rem)\n assert_eq(17u64.rem(5u64), 2u64);\n assert_eq(10u8.rem(3u8), 1u8);\n\n // neg\n assert_eq(42.neg(), -42);\n assert_eq((-10).neg(), 10);\n assert_eq(42.neg(), -42);\n }\n\n #[test]\n fn test_division() {\n // test division by one\n assert_eq(42.div(1), 42);\n assert_eq(0.div(1), 0);\n assert_eq(255u8.div(1u8), 255u8);\n\n // test division by self\n assert_eq(42.div(42), 1);\n assert_eq(1.div(1), 1);\n\n // test remainder (Field doesn't implement Rem)\n assert_eq(42u32.rem(42u32), 0u32);\n assert_eq(0u16.rem(42u16), 0u16);\n assert_eq(1u64.rem(42u64), 1u64);\n }\n\n // Per-operator overflow corners. The signed `iN::MIN` corners pin down\n // compiler-side overflow detection on the trait dispatch path: the\n // trait impls are one-line delegations to the built-in operators and\n // rely entirely on the compiler's lowering to emit the two's-complement\n // overflow constraints. These tests trip CI on any future SSA pass\n // that drops one of those constraints.\n //\n // Each case pins the exact runtime message via `should_fail_with`, so a\n // regression that starts failing for the *wrong* reason (a divide by\n // zero, or a panic in unrelated code) is caught too, rather than being\n // accepted as \"it failed somehow\". The matcher is a case-insensitive\n // substring, so the same string works under both ACIR and Brillig even\n // though Brillig capitalizes the divide/remainder messages.\n\n mod add {\n use crate::ops::arith::Add;\n\n // `MAX + 1` is one past the largest representable value, so the\n // range check on the sum rejects it. For unsigned this is a wrap\n // past `2^bits - 1`; for signed it steps out of `[MIN, MAX]`.\n\n #[test(should_fail_with = \"attempt to add with overflow\")]\n fn u8_overflow() {\n let _ = 255u8.add(1u8);\n }\n\n #[test(should_fail_with = \"attempt to add with overflow\")]\n fn u16_overflow() {\n let _ = 65535u16.add(1u16);\n }\n\n #[test(should_fail_with = \"attempt to add with overflow\")]\n fn i8_overflow() {\n let _ = 127i8.add(1i8);\n }\n\n #[test(should_fail_with = \"attempt to add with overflow\")]\n fn i16_overflow() {\n let _ = 32767i16.add(1i16);\n }\n\n #[test(should_fail_with = \"attempt to add with overflow\")]\n fn i32_overflow() {\n let _ = 2147483647i32.add(1i32);\n }\n\n #[test(should_fail_with = \"attempt to add with overflow\")]\n fn i64_overflow() {\n let _ = 9223372036854775807i64.add(1i64);\n }\n }\n\n mod sub {\n use crate::ops::arith::Sub;\n\n // Subtraction underflows past the type's minimum: `0 - 1` for\n // unsigned (a borrow below zero), and `MIN - 1` for signed (one step\n // below the most-negative value).\n\n #[test(should_fail_with = \"attempt to subtract with overflow\")]\n fn u8_overflow() {\n let _ = 0u8.sub(1u8);\n }\n\n #[test(should_fail_with = \"attempt to subtract with overflow\")]\n fn u16_overflow() {\n let _ = 0u16.sub(1u16);\n }\n\n #[test(should_fail_with = \"attempt to subtract with overflow\")]\n fn i8_overflow() {\n let val: i8 = -128;\n let _ = val.sub(1i8);\n }\n\n #[test(should_fail_with = \"attempt to subtract with overflow\")]\n fn i16_overflow() {\n let val: i16 = -32768;\n let _ = val.sub(1i16);\n }\n\n #[test(should_fail_with = \"attempt to subtract with overflow\")]\n fn i32_overflow() {\n let val: i32 = -2147483648;\n let _ = val.sub(1i32);\n }\n\n #[test(should_fail_with = \"attempt to subtract with overflow\")]\n fn i64_overflow() {\n let val: i64 = -9223372036854775808;\n let _ = val.sub(1i64);\n }\n }\n\n mod mul {\n use crate::ops::arith::Mul;\n\n // Unsigned `MAX * 2` exceeds the maximum. The signed corner is\n // `MIN * -1`: the true product is `-MIN == 2^(bits-1)`, exactly one\n // past the signed maximum `2^(bits-1) - 1`, so it is unrepresentable.\n // This is the same range asymmetry that makes negating MIN overflow.\n\n #[test(should_fail_with = \"attempt to multiply with overflow\")]\n fn u8_overflow() {\n let _ = 255u8.mul(2u8);\n }\n\n #[test(should_fail_with = \"attempt to multiply with overflow\")]\n fn u16_overflow() {\n let _ = 65535u16.mul(2u16);\n }\n\n #[test(should_fail_with = \"attempt to multiply with overflow\")]\n fn i8_min_times_neg_one_overflow() {\n let val: i8 = -128;\n let _ = val.mul(-1i8);\n }\n\n #[test(should_fail_with = \"attempt to multiply with overflow\")]\n fn i16_min_times_neg_one_overflow() {\n let val: i16 = -32768;\n let _ = val.mul(-1i16);\n }\n\n #[test(should_fail_with = \"attempt to multiply with overflow\")]\n fn i32_min_times_neg_one_overflow() {\n let val: i32 = -2147483648;\n let _ = val.mul(-1i32);\n }\n\n #[test(should_fail_with = \"attempt to multiply with overflow\")]\n fn i64_min_times_neg_one_overflow() {\n let val: i64 = -9223372036854775808;\n let _ = val.mul(-1i64);\n }\n }\n\n mod div {\n use crate::ops::arith::Div;\n\n // `MIN / -1` is the only division that overflows: the quotient is\n // `-MIN == 2^(bits-1)`, one past the signed maximum. (Division by\n // zero is a distinct error and is not what these cases exercise.)\n\n #[test(should_fail_with = \"attempt to divide with overflow\")]\n fn i8_min_by_neg_one_overflow() {\n let val: i8 = -128;\n let _ = val.div(-1i8);\n }\n\n #[test(should_fail_with = \"attempt to divide with overflow\")]\n fn i16_min_by_neg_one_overflow() {\n let val: i16 = -32768;\n let _ = val.div(-1i16);\n }\n\n #[test(should_fail_with = \"attempt to divide with overflow\")]\n fn i32_min_by_neg_one_overflow() {\n let val: i32 = -2147483648;\n let _ = val.div(-1i32);\n }\n\n #[test(should_fail_with = \"attempt to divide with overflow\")]\n fn i64_min_by_neg_one_overflow() {\n let val: i64 = -9223372036854775808;\n let _ = val.div(-1i64);\n }\n }\n\n mod rem {\n use crate::ops::arith::Rem;\n\n // `MIN % -1` is mathematically 0, but it is computed via the same\n // `MIN / -1` division that overflows, so the operation is rejected\n // rather than silently yielding 0. This matches Rust, where\n // `iN::MIN % -1` also overflows.\n\n #[test(should_fail_with = \"attempt to calculate the remainder with overflow\")]\n fn i8_min_by_neg_one_overflow() {\n let val: i8 = -128;\n let _ = val.rem(-1i8);\n }\n\n #[test(should_fail_with = \"attempt to calculate the remainder with overflow\")]\n fn i16_min_by_neg_one_overflow() {\n let val: i16 = -32768;\n let _ = val.rem(-1i16);\n }\n\n #[test(should_fail_with = \"attempt to calculate the remainder with overflow\")]\n fn i32_min_by_neg_one_overflow() {\n let val: i32 = -2147483648;\n let _ = val.rem(-1i32);\n }\n\n #[test(should_fail_with = \"attempt to calculate the remainder with overflow\")]\n fn i64_min_by_neg_one_overflow() {\n let val: i64 = -9223372036854775808;\n let _ = val.rem(-1i64);\n }\n }\n\n mod neg {\n use crate::ops::arith::Neg;\n\n // Negating `MIN` overflows because the two's-complement range is\n // asymmetric: `-MIN == 2^(bits-1)` has no representable positive\n // counterpart (the maximum is only `2^(bits-1) - 1`). MIN is the\n // unique value with this property, so it is the only negation that\n // fails. The wording of the failure depends on the execution path:\n // the comptime interpreter reports \"attempt to negate with\n // overflow\", while ACIR/Brillig lower unary `-` to `0 - x` and so\n // report \"attempt to subtract with overflow\". Both share\n // \"with overflow\", which is what these cases assert on.\n\n #[test(should_fail_with = \"with overflow\")]\n fn i8_min_overflow() {\n let val: i8 = -128;\n let _ = val.neg();\n }\n\n #[test(should_fail_with = \"with overflow\")]\n fn i16_min_overflow() {\n let val: i16 = -32768;\n let _ = val.neg();\n }\n\n #[test(should_fail_with = \"with overflow\")]\n fn i32_min_overflow() {\n let val: i32 = -2147483648;\n let _ = val.neg();\n }\n\n #[test(should_fail_with = \"with overflow\")]\n fn i64_min_overflow() {\n let val: i64 = -9223372036854775808;\n let _ = val.neg();\n }\n }\n\n #[test]\n fn test_field() {\n let zero: Field = 0;\n let one: Field = 1;\n\n // test Field basic operations\n assert_eq(zero.add(one), one);\n assert_eq(one.add(zero), one);\n assert_eq(one.sub(one), zero);\n assert_eq(one.mul(one), one);\n assert_eq(one.div(one), one);\n assert_eq(zero.neg(), zero);\n assert_eq(one.neg(), -one);\n }\n\n }\n\n mod wrapping_arithmetic {\n use crate::ops::arith::{Add, Div, Mul, Neg, Sub, WrappingAdd, WrappingMul, WrappingSub};\n #[test]\n fn test_wrapping_add() {\n assert_eq(255u8.wrapping_add(1u8), 0u8);\n assert_eq(255u8.wrapping_add(255u8), 254u8);\n assert_eq(0u8.wrapping_add(0u8), 0u8);\n assert_eq(128u8.wrapping_add(128u8), 0u8);\n\n // test u16 wrapping add\n assert_eq(65535u16.wrapping_add(1u16), 0u16);\n assert_eq(65535u16.wrapping_add(65535u16), 65534u16);\n\n // test u32 wrapping add\n assert_eq(0xffffffffu32.wrapping_add(1u32), 0u32);\n assert_eq(0xffffffffu32.wrapping_add(0xffffffffu32), 0xfffffffeu32);\n\n // test u64 wrapping add\n assert_eq(0xffffffffffffffffu64.wrapping_add(1u64), 0u64);\n assert_eq(\n 0xffffffffffffffffu64.wrapping_add(0xffffffffffffffffu64),\n 0xfffffffffffffffeu64,\n );\n\n // test u128 wrapping add\n assert_eq(0xffffffffffffffffffffffffffffffffu128.wrapping_add(1u128), 0u128);\n\n // test signed types\n assert_eq(127i8.wrapping_add(1i8), -128i8);\n let val: i8 = -128;\n assert_eq(val.wrapping_add(-1i8), 127i8);\n\n // test Field wrapping add\n let forty_two: Field = 42;\n let fifty_eight: Field = 58;\n let hundred: Field = 100;\n let neg_two: Field = -2;\n let two: Field = 2;\n let zero: Field = 0;\n let neg_two_hundred: Field = -200;\n let neg_one_ninety_eight: Field = -198;\n assert_eq(forty_two.wrapping_add(fifty_eight), hundred);\n assert_eq(neg_two.wrapping_add(two), zero);\n assert_eq(neg_two_hundred.wrapping_add(two), neg_one_ninety_eight);\n }\n\n #[test]\n fn test_wrapping_sub() {\n assert_eq(0u8.wrapping_sub(1u8), 255u8);\n assert_eq(255u8.wrapping_sub(255u8), 0u8);\n assert_eq(0u8.wrapping_sub(0u8), 0u8);\n assert_eq(1u8.wrapping_sub(2u8), 255u8);\n\n // test u16 wrapping sub\n assert_eq(0u16.wrapping_sub(1u16), 65535u16);\n assert_eq(65535u16.wrapping_sub(65535u16), 0u16);\n\n // test u32 wrapping sub\n assert_eq(0u32.wrapping_sub(1u32), 0xffffffffu32);\n assert_eq(0xffffffffu32.wrapping_sub(0xffffffffu32), 0u32);\n\n // test u64 wrapping sub\n assert_eq(0u64.wrapping_sub(1u64), 0xffffffffffffffffu64);\n assert_eq(0xffffffffffffffffu64.wrapping_sub(0xffffffffffffffffu64), 0u64);\n\n // test u128 wrapping sub\n assert_eq(0u128.wrapping_sub(1u128), 0xffffffffffffffffffffffffffffffffu128);\n\n // test signed types\n let val: i8 = -128;\n assert_eq(val.wrapping_sub(1i8), 127i8);\n assert_eq(127i8.wrapping_sub(-1i8), -128i8);\n\n // test Field wrapping sub\n let forty_two: Field = 42;\n let fifty_eight: Field = 58;\n let neg_sixteen: Field = -16;\n assert_eq(forty_two.wrapping_sub(fifty_eight), neg_sixteen);\n }\n\n #[test]\n fn test_wrapping_mul() {\n let zero: u128 = 0;\n let one: u128 = 1;\n let two_pow_64: u128 = 0x10000000000000000;\n let u128_max: u128 = 0xffffffffffffffffffffffffffffffff;\n\n assert_eq(zero, zero.wrapping_mul(one));\n assert_eq(zero, one.wrapping_mul(zero));\n assert_eq(one, one.wrapping_mul(one));\n assert_eq(zero, zero.wrapping_mul(two_pow_64));\n assert_eq(zero, two_pow_64.wrapping_mul(zero));\n assert_eq(two_pow_64, two_pow_64.wrapping_mul(one));\n assert_eq(two_pow_64, one.wrapping_mul(two_pow_64));\n assert_eq(zero, two_pow_64.wrapping_mul(two_pow_64));\n assert_eq(one, u128_max.wrapping_mul(u128_max));\n\n // test u8 wrapping mul\n assert_eq(255u8.wrapping_mul(2u8), 254u8);\n assert_eq(255u8.wrapping_mul(255u8), 1u8);\n assert_eq(128u8.wrapping_mul(2u8), 0u8);\n\n // test u16 wrapping mul\n assert_eq(65535u16.wrapping_mul(2u16), 65534u16);\n assert_eq(65535u16.wrapping_mul(65535u16), 1u16);\n\n // test u32 wrapping mul\n assert_eq(0xffffffffu32.wrapping_mul(2u32), 0xfffffffeu32);\n assert_eq(0xffffffffu32.wrapping_mul(0xffffffffu32), 1u32);\n\n // test u64 wrapping mul\n // 0xffffffffffffffffu64 is 2^64 - 1\n assert_eq(0xffffffffffffffffu64.wrapping_mul(2u64), 0xfffffffffffffffeu64);\n assert_eq(0xffffffffffffffffu64.wrapping_mul(0xffffffffffffffffu64), 1u64);\n\n // test signed types\n assert_eq(127i8.wrapping_mul(2i8), -2i8);\n let val: i8 = -128;\n assert_eq(val.wrapping_mul(-1i8), -128i8);\n\n // test Field wrapping mul\n let six: Field = 6;\n let seven: Field = 7;\n let forty_two: Field = 42;\n let neg_two: Field = -2;\n let two: Field = 2;\n let neg_four: Field = -4;\n assert_eq(six.wrapping_mul(seven), forty_two);\n assert_eq(neg_two.wrapping_mul(two), neg_four);\n }\n\n // test wrapping operations is the same as the regular operations\n #[test]\n fn test_wrapping_vs_regular() {\n let u64_large = 0x123456789abcdef0u64;\n let u128_large = 0x123456789abcdef0123456789abcdef0u128;\n\n assert_eq(u64_large.wrapping_add(1u64), u64_large + 1u64);\n assert_eq(u64_large.wrapping_sub(1u64), u64_large - 1u64);\n assert_eq(u64_large.wrapping_mul(2u64), u64_large * 2u64);\n\n assert_eq(u128_large.wrapping_add(1u128), u128_large + 1u128);\n assert_eq(u128_large.wrapping_sub(1u128), u128_large - 1u128);\n assert_eq(u128_large.wrapping_mul(2u128), u128_large * 2u128);\n }\n\n #[test]\n fn test_field_wrapping_operations() {\n let zero: Field = 0;\n let one: Field = 1;\n let large_val = 0xffffffffffffffff;\n\n // test Field wrapping operations\n assert_eq(zero.wrapping_add(one), one);\n assert_eq(one.wrapping_add(large_val), one + large_val);\n assert_eq(zero.wrapping_sub(one), -one);\n assert_eq(one.wrapping_sub(large_val), one - large_val);\n assert_eq(zero.wrapping_mul(one), zero);\n assert_eq(one.wrapping_mul(large_val), large_val);\n\n // test Field basic operations\n assert_eq(zero.add(one), one);\n assert_eq(one.add(zero), one);\n assert_eq(one.sub(one), zero);\n assert_eq(one.mul(one), one);\n assert_eq(one.div(one), one);\n assert_eq(zero.neg(), zero);\n assert_eq(one.neg(), -one);\n }\n\n }\n\n mod split_functions {\n\n use crate::ops::arith::{split64, split_into_64_bit_limbs};\n\n // test split64 and split_into_64_bit_limbs functions\n #[test]\n fn test_split_functions() {\n let small_val = 0x123456789abcdefu128;\n let large_val = 0x123456789abcdef0123456789abcdef0u128;\n let max_val = 0xffffffffffffffffffffffffffffffffu128;\n\n // test split64 (unconstrained)\n // Safety: testing\n unsafe {\n let (lo, hi) = split64(small_val);\n assert_eq(lo, 0x123456789abcdefu64);\n assert_eq(hi, 0u64);\n\n let (lo2, hi2) = split64(large_val);\n assert_eq(lo2, 0x123456789abcdef0u64);\n assert_eq(hi2, 0x123456789abcdef0u64);\n }\n\n // test split_into_64_bit_limbs (constrained)\n let (lo3, hi3) = split_into_64_bit_limbs(small_val);\n assert_eq(lo3, 0x123456789abcdefu64);\n assert_eq(hi3, 0u64);\n\n let (lo4, hi4) = split_into_64_bit_limbs(large_val);\n assert_eq(lo4, 0x123456789abcdef0u64);\n assert_eq(hi4, 0x123456789abcdef0u64);\n\n let (lo5, hi5) = split_into_64_bit_limbs(max_val);\n assert_eq(lo5, 0xffffffffffffffffu64);\n assert_eq(hi5, 0xffffffffffffffffu64);\n }\n }\n\n mod traits {\n use crate::ops::arith::{\n Add, Div, Mul, Neg, Rem, Sub, WrappingAdd, WrappingMul, WrappingSub,\n };\n\n #[test]\n fn add() {\n assert_eq(1_u8.add(2), 3);\n assert_eq(1_u16.add(2), 3);\n assert_eq(1_u32.add(2), 3);\n assert_eq(1_u64.add(2), 3);\n assert_eq(1_u128.add(2), 3);\n assert_eq(1_i8.add(2), 3);\n assert_eq(1_i16.add(2), 3);\n assert_eq(1_i32.add(2), 3);\n assert_eq(1_i64.add(2), 3);\n assert_eq(1_Field.add(2), 3);\n }\n\n #[test]\n fn sub() {\n assert_eq(3_u8.sub(2), 1);\n assert_eq(3_u16.sub(2), 1);\n assert_eq(3_u32.sub(2), 1);\n assert_eq(3_u64.sub(2), 1);\n assert_eq(3_u128.sub(2), 1);\n assert_eq(3_i8.sub(2), 1);\n assert_eq(3_i16.sub(2), 1);\n assert_eq(3_i32.sub(2), 1);\n assert_eq(3_i64.sub(2), 1);\n assert_eq(3_Field.sub(2), 1);\n }\n\n #[test]\n fn mul() {\n assert_eq(3_u8.mul(2), 6);\n assert_eq(3_u16.mul(2), 6);\n assert_eq(3_u32.mul(2), 6);\n assert_eq(3_u64.mul(2), 6);\n assert_eq(3_u128.mul(2), 6);\n assert_eq(3_i8.mul(2), 6);\n assert_eq(3_i16.mul(2), 6);\n assert_eq(3_i32.mul(2), 6);\n assert_eq(3_i64.mul(2), 6);\n assert_eq(3_Field.mul(2), 6);\n }\n\n #[test]\n fn div() {\n assert_eq(6_u8.div(2), 3);\n assert_eq(6_u16.div(2), 3);\n assert_eq(6_u32.div(2), 3);\n assert_eq(6_u64.div(2), 3);\n assert_eq(6_u128.div(2), 3);\n assert_eq(6_i8.div(2), 3);\n assert_eq(6_i16.div(2), 3);\n assert_eq(6_i32.div(2), 3);\n assert_eq(6_i64.div(2), 3);\n assert_eq(6_Field.div(2), 3);\n }\n\n #[test]\n fn rem() {\n assert_eq(3_u8.rem(2), 1);\n assert_eq(3_u16.rem(2), 1);\n assert_eq(3_u32.rem(2), 1);\n assert_eq(3_u64.rem(2), 1);\n assert_eq(3_u128.rem(2), 1);\n assert_eq(3_i8.rem(2), 1);\n assert_eq(3_i16.rem(2), 1);\n assert_eq(3_i32.rem(2), 1);\n assert_eq(3_i64.rem(2), 1);\n }\n\n #[test]\n fn neg() {\n assert_eq(3_i8.neg(), -3);\n assert_eq(3_i16.neg(), -3);\n assert_eq(3_i32.neg(), -3);\n assert_eq(3_i64.neg(), -3);\n }\n\n #[test]\n fn wrapping_add() {\n assert_eq(255_u8.wrapping_add(2), 1);\n assert_eq(65535_u16.wrapping_add(2), 1);\n assert_eq(4294967295_u32.wrapping_add(2), 1);\n assert_eq(18446744073709551615_u64.wrapping_add(2), 1);\n assert_eq(340282366920938463463374607431768211455_u128.wrapping_add(2), 1);\n assert_eq(127_i8.wrapping_add(2), -127);\n assert_eq(32767_i16.wrapping_add(2), -32767);\n assert_eq(2147483647_i32.wrapping_add(2), -2147483647);\n assert_eq(9223372036854775807_i64.wrapping_add(2), -9223372036854775807);\n assert_eq(1_Field.wrapping_add(2), 3);\n }\n\n #[test]\n fn wrapping_sub() {\n assert_eq(0_u8.wrapping_sub(1), 255);\n assert_eq(0_u16.wrapping_sub(1), 65535);\n assert_eq(0_u32.wrapping_sub(1), 4294967295);\n assert_eq(0_u64.wrapping_sub(1), 18446744073709551615);\n assert_eq(0_u128.wrapping_sub(1), 340282366920938463463374607431768211455);\n assert_eq((-128_i8).wrapping_sub(1), 127);\n assert_eq((-32768_i16).wrapping_sub(1), 32767);\n assert_eq((-2147483648_i32).wrapping_sub(1), 2147483647);\n assert_eq((-9223372036854775808_i64).wrapping_sub(1), 9223372036854775807);\n assert_eq(3_Field.wrapping_sub(1), 2);\n }\n\n #[test]\n fn wrapping_mul() {\n assert_eq(255_u8.wrapping_mul(2), 254);\n assert_eq(65535_u16.wrapping_mul(2), 65534);\n assert_eq(4294967295_u32.wrapping_mul(2), 4294967294);\n assert_eq(18446744073709551615_u64.wrapping_mul(2), 18446744073709551614);\n assert_eq(\n 340282366920938463463374607431768211455_u128.wrapping_mul(2),\n 340282366920938463463374607431768211454,\n );\n assert_eq(127_i8.wrapping_mul(2), -2);\n assert_eq(32767_i16.wrapping_mul(2), -2);\n assert_eq(2147483647_i32.wrapping_mul(2), -2);\n assert_eq(9223372036854775807_i64.wrapping_mul(2), -2);\n assert_eq(2_Field.wrapping_mul(3), 6);\n }\n }\n}\n"
|
|
1718
1966
|
},
|
|
1719
|
-
"
|
|
1967
|
+
"43": {
|
|
1720
1968
|
"function_locations": [
|
|
1721
1969
|
{
|
|
1722
1970
|
"name": "Option<T>::none",
|
|
@@ -1809,34 +2057,104 @@
|
|
|
1809
2057
|
{
|
|
1810
2058
|
"name": "<impl Ord for Option<T>>::cmp",
|
|
1811
2059
|
"start": 5975
|
|
2060
|
+
},
|
|
2061
|
+
{
|
|
2062
|
+
"name": "tests::some_and_none",
|
|
2063
|
+
"start": 6447
|
|
2064
|
+
},
|
|
2065
|
+
{
|
|
2066
|
+
"name": "tests::unwrap_succeeds",
|
|
2067
|
+
"start": 6677
|
|
2068
|
+
},
|
|
2069
|
+
{
|
|
2070
|
+
"name": "tests::unwrap_fails",
|
|
2071
|
+
"start": 6781
|
|
2072
|
+
},
|
|
2073
|
+
{
|
|
2074
|
+
"name": "tests::unwrap_or",
|
|
2075
|
+
"start": 6868
|
|
2076
|
+
},
|
|
2077
|
+
{
|
|
2078
|
+
"name": "tests::unwrap_or_else",
|
|
2079
|
+
"start": 7016
|
|
2080
|
+
},
|
|
2081
|
+
{
|
|
2082
|
+
"name": "tests::expect_succeeds",
|
|
2083
|
+
"start": 7181
|
|
2084
|
+
},
|
|
2085
|
+
{
|
|
2086
|
+
"name": "tests::expect_fails",
|
|
2087
|
+
"start": 7328
|
|
2088
|
+
},
|
|
2089
|
+
{
|
|
2090
|
+
"name": "tests::map",
|
|
2091
|
+
"start": 7427
|
|
2092
|
+
},
|
|
2093
|
+
{
|
|
2094
|
+
"name": "tests::map_or",
|
|
2095
|
+
"start": 7595
|
|
2096
|
+
},
|
|
2097
|
+
{
|
|
2098
|
+
"name": "tests::map_or_else",
|
|
2099
|
+
"start": 7762
|
|
2100
|
+
},
|
|
2101
|
+
{
|
|
2102
|
+
"name": "tests::and",
|
|
2103
|
+
"start": 7937
|
|
2104
|
+
},
|
|
2105
|
+
{
|
|
2106
|
+
"name": "tests::and_then",
|
|
2107
|
+
"start": 8277
|
|
2108
|
+
},
|
|
2109
|
+
{
|
|
2110
|
+
"name": "tests::or",
|
|
2111
|
+
"start": 8663
|
|
2112
|
+
},
|
|
2113
|
+
{
|
|
2114
|
+
"name": "tests::or_else",
|
|
2115
|
+
"start": 9000
|
|
2116
|
+
},
|
|
2117
|
+
{
|
|
2118
|
+
"name": "tests::xor",
|
|
2119
|
+
"start": 9365
|
|
2120
|
+
},
|
|
2121
|
+
{
|
|
2122
|
+
"name": "tests::filter",
|
|
2123
|
+
"start": 9704
|
|
2124
|
+
},
|
|
2125
|
+
{
|
|
2126
|
+
"name": "tests::flatten",
|
|
2127
|
+
"start": 10030
|
|
2128
|
+
},
|
|
2129
|
+
{
|
|
2130
|
+
"name": "tests::default",
|
|
2131
|
+
"start": 10301
|
|
2132
|
+
},
|
|
2133
|
+
{
|
|
2134
|
+
"name": "tests::eq",
|
|
2135
|
+
"start": 10394
|
|
2136
|
+
},
|
|
2137
|
+
{
|
|
2138
|
+
"name": "tests::cmp",
|
|
2139
|
+
"start": 10714
|
|
1812
2140
|
}
|
|
1813
2141
|
],
|
|
1814
2142
|
"path": "std/option.nr",
|
|
1815
|
-
"source": "use crate::cmp::{Eq, Ord, Ordering};\nuse crate::default::Default;\nuse crate::hash::{Hash, Hasher};\n\n/// Represents a value of type T or its absence.\n/// Use `Option::some(value)` to construct a value or `Option::none()` to record the absence of one.\npub struct Option<T> {\n _is_some: bool,\n _value: T,\n}\n\nimpl<T> Option<T> {\n /// Constructs a None value\n pub fn none() -> Self {\n Self { _is_some: false, _value: crate::mem::zeroed() }\n }\n\n /// Constructs a Some wrapper around the given value\n pub fn some(_value: T) -> Self {\n Self { _is_some: true, _value }\n }\n\n /// True if this Option is None\n pub fn is_none(&self) -> bool {\n !self._is_some\n }\n\n /// True if this Option is Some\n pub fn is_some(&self) -> bool {\n self._is_some\n }\n\n /// Asserts `self.is_some()` and returns the wrapped value.\n pub fn unwrap(self) -> T {\n assert(self._is_some);\n self._value\n }\n\n /// Returns the inner value without asserting `self.is_some()`\n /// Note that if `self` is `None`, there is no guarantee what value will be returned,\n /// only that it will be of type `T`.\n pub fn unwrap_unchecked(self) -> T {\n self._value\n }\n\n /// Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value.\n pub fn unwrap_or(self, default: T) -> T {\n if self._is_some {\n self._value\n } else {\n default\n }\n }\n\n /// Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return\n /// a default value.\n pub fn unwrap_or_else<Env>(self, default: fn[Env]() -> T) -> T {\n if self._is_some {\n self._value\n } else {\n default()\n }\n }\n\n /// Asserts `self.is_some()` with a provided custom message and returns the contained `Some` value\n pub fn expect<let N: u32, MessageTypes>(self, message: fmtstr<N, MessageTypes>) -> T {\n assert(self.is_some(), message);\n self._value\n }\n\n /// If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`.\n pub fn map<U, Env>(self, f: fn[Env](T) -> U) -> Option<U> {\n if self._is_some {\n Option::some(f(self._value))\n } else {\n Option::none()\n }\n }\n\n /// If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value.\n pub fn map_or<U, Env>(self, default: U, f: fn[Env](T) -> U) -> U {\n if self._is_some {\n f(self._value)\n } else {\n default\n }\n }\n\n /// If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`.\n pub fn map_or_else<U, Env1, Env2>(self, default: fn[Env1]() -> U, f: fn[Env2](T) -> U) -> U {\n if self._is_some {\n f(self._value)\n } else {\n default()\n }\n }\n\n /// Returns None if self is None. Otherwise, this returns `other`.\n pub fn and(self, other: Self) -> Self {\n if self.is_none() {\n Option::none()\n } else {\n other\n }\n }\n\n /// If self is None, this returns None. Otherwise, this calls the given function\n /// with the Some value contained within self, and returns the result of that call.\n ///\n /// In some languages this function is called `flat_map` or `bind`.\n pub fn and_then<U, Env>(self, f: fn[Env](T) -> Option<U>) -> Option<U> {\n if self._is_some {\n f(self._value)\n } else {\n Option::none()\n }\n }\n\n /// If self is Some, return self. Otherwise, return `other`.\n pub fn or(self, other: Self) -> Self {\n if self._is_some {\n self\n } else {\n other\n }\n }\n\n /// If self is Some, return self. Otherwise, return `default()`.\n pub fn or_else<Env>(self, default: fn[Env]() -> Self) -> Self {\n if self._is_some {\n self\n } else {\n default()\n }\n }\n\n // If only one of the two Options is Some, return that option.\n // Otherwise, if both options are Some or both are None, None is returned.\n pub fn xor(self, other: Self) -> Self {\n if self._is_some {\n if other._is_some {\n Option::none()\n } else {\n self\n }\n } else if other._is_some {\n other\n } else {\n Option::none()\n }\n }\n\n /// Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true.\n /// Otherwise, this returns `None`\n pub fn filter<Env>(self, predicate: fn[Env](T) -> bool) -> Self {\n if self._is_some {\n if predicate(self._value) {\n self\n } else {\n Option::none()\n }\n } else {\n Option::none()\n }\n }\n\n /// Flattens an Option<Option<T>> into a Option<T>.\n /// This returns None if the outer Option is None. Otherwise, this returns the inner Option.\n pub fn flatten(option: Option<Option<T>>) -> Option<T> {\n if option._is_some {\n option._value\n } else {\n Option::none()\n }\n }\n}\n\nimpl<T> Default for Option<T> {\n fn default() -> Self {\n Option::none()\n }\n}\n\nimpl<T> Eq for Option<T>\nwhere\n T: Eq,\n{\n fn eq(self, other: Self) -> bool {\n if self._is_some == other._is_some {\n if self._is_some {\n self._value == other._value\n } else {\n true\n }\n } else {\n false\n }\n }\n}\n\nimpl<T> Hash for Option<T>\nwhere\n T: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self._is_some.hash(state);\n if self._is_some {\n self._value.hash(state);\n }\n }\n}\n\n// For this impl we're declaring Option::none < Option::some\nimpl<T> Ord for Option<T>\nwhere\n T: Ord,\n{\n fn cmp(self, other: Self) -> Ordering {\n if self._is_some {\n if other._is_some {\n self._value.cmp(other._value)\n } else {\n Ordering::greater()\n }\n } else if other._is_some {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n}\n"
|
|
2143
|
+
"source": "use crate::cmp::{Eq, Ord, Ordering};\nuse crate::default::Default;\nuse crate::hash::{Hash, Hasher};\n\n/// Represents a value of type T or its absence.\n/// Use `Option::some(value)` to construct a value or `Option::none()` to record the absence of one.\npub struct Option<T> {\n _is_some: bool,\n _value: T,\n}\n\nimpl<T> Option<T> {\n /// Constructs a None value\n pub fn none() -> Self {\n Self { _is_some: false, _value: crate::mem::zeroed() }\n }\n\n /// Constructs a Some wrapper around the given value\n pub fn some(_value: T) -> Self {\n Self { _is_some: true, _value }\n }\n\n /// True if this Option is None\n pub fn is_none(&self) -> bool {\n !self._is_some\n }\n\n /// True if this Option is Some\n pub fn is_some(&self) -> bool {\n self._is_some\n }\n\n /// Asserts `self.is_some()` and returns the wrapped value.\n pub fn unwrap(self) -> T {\n assert(self._is_some);\n self._value\n }\n\n /// Returns the inner value without asserting `self.is_some()`\n /// Note that if `self` is `None`, there is no guarantee what value will be returned,\n /// only that it will be of type `T`.\n pub fn unwrap_unchecked(self) -> T {\n self._value\n }\n\n /// Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value.\n pub fn unwrap_or(self, default: T) -> T {\n if self._is_some {\n self._value\n } else {\n default\n }\n }\n\n /// Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return\n /// a default value.\n pub fn unwrap_or_else<Env>(self, default: fn[Env]() -> T) -> T {\n if self._is_some {\n self._value\n } else {\n default()\n }\n }\n\n /// Asserts `self.is_some()` with a provided custom message and returns the contained `Some` value\n pub fn expect<let N: u32, MessageTypes>(self, message: fmtstr<N, MessageTypes>) -> T {\n assert(self.is_some(), message);\n self._value\n }\n\n /// If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`.\n pub fn map<U, Env>(self, f: fn[Env](T) -> U) -> Option<U> {\n if self._is_some {\n Option::some(f(self._value))\n } else {\n Option::none()\n }\n }\n\n /// If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value.\n pub fn map_or<U, Env>(self, default: U, f: fn[Env](T) -> U) -> U {\n if self._is_some {\n f(self._value)\n } else {\n default\n }\n }\n\n /// If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`.\n pub fn map_or_else<U, Env1, Env2>(self, default: fn[Env1]() -> U, f: fn[Env2](T) -> U) -> U {\n if self._is_some {\n f(self._value)\n } else {\n default()\n }\n }\n\n /// Returns None if self is None. Otherwise, this returns `other`.\n pub fn and(self, other: Self) -> Self {\n if self.is_none() {\n Option::none()\n } else {\n other\n }\n }\n\n /// If self is None, this returns None. Otherwise, this calls the given function\n /// with the Some value contained within self, and returns the result of that call.\n ///\n /// In some languages this function is called `flat_map` or `bind`.\n pub fn and_then<U, Env>(self, f: fn[Env](T) -> Option<U>) -> Option<U> {\n if self._is_some {\n f(self._value)\n } else {\n Option::none()\n }\n }\n\n /// If self is Some, return self. Otherwise, return `other`.\n pub fn or(self, other: Self) -> Self {\n if self._is_some {\n self\n } else {\n other\n }\n }\n\n /// If self is Some, return self. Otherwise, return `default()`.\n pub fn or_else<Env>(self, default: fn[Env]() -> Self) -> Self {\n if self._is_some {\n self\n } else {\n default()\n }\n }\n\n // If only one of the two Options is Some, return that option.\n // Otherwise, if both options are Some or both are None, None is returned.\n pub fn xor(self, other: Self) -> Self {\n if self._is_some {\n if other._is_some {\n Option::none()\n } else {\n self\n }\n } else if other._is_some {\n other\n } else {\n Option::none()\n }\n }\n\n /// Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true.\n /// Otherwise, this returns `None`\n pub fn filter<Env>(self, predicate: fn[Env](T) -> bool) -> Self {\n if self._is_some {\n if predicate(self._value) {\n self\n } else {\n Option::none()\n }\n } else {\n Option::none()\n }\n }\n\n /// Flattens an Option<Option<T>> into a Option<T>.\n /// This returns None if the outer Option is None. Otherwise, this returns the inner Option.\n pub fn flatten(option: Option<Option<T>>) -> Option<T> {\n if option._is_some {\n option._value\n } else {\n Option::none()\n }\n }\n}\n\nimpl<T> Default for Option<T> {\n fn default() -> Self {\n Option::none()\n }\n}\n\nimpl<T> Eq for Option<T>\nwhere\n T: Eq,\n{\n fn eq(self, other: Self) -> bool {\n if self._is_some == other._is_some {\n if self._is_some {\n self._value == other._value\n } else {\n true\n }\n } else {\n false\n }\n }\n}\n\nimpl<T> Hash for Option<T>\nwhere\n T: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self._is_some.hash(state);\n if self._is_some {\n self._value.hash(state);\n }\n }\n}\n\n// For this impl we're declaring Option::none < Option::some\nimpl<T> Ord for Option<T>\nwhere\n T: Ord,\n{\n fn cmp(self, other: Self) -> Ordering {\n if self._is_some {\n if other._is_some {\n self._value.cmp(other._value)\n } else {\n Ordering::greater()\n }\n } else if other._is_some {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n}\n\nmod tests {\n use crate::cmp::Ord;\n use crate::cmp::Ordering;\n use crate::default::Default as _;\n use super::Option;\n\n #[test]\n fn some_and_none() {\n assert(Option::<u8>::none().is_none());\n assert(!Option::<u8>::none().is_some());\n assert(Option::some(1).is_some());\n assert(!Option::some(1).is_none());\n }\n\n #[test]\n fn unwrap_succeeds() {\n assert_eq(Option::some(1).unwrap(), 1);\n }\n\n #[test(should_fail)]\n fn unwrap_fails() {\n let _ = Option::<u8>::none().unwrap();\n }\n\n #[test]\n fn unwrap_or() {\n assert_eq(Option::some(1).unwrap_or(2), 1);\n assert_eq(Option::none().unwrap_or(2), 2);\n }\n\n #[test]\n fn unwrap_or_else() {\n assert_eq(Option::some(1).unwrap_or_else(|| 2), 1);\n assert_eq(Option::none().unwrap_or_else(|| 2), 2);\n }\n\n #[test]\n fn expect_succeeds() {\n assert_eq(Option::some(1).expect(f\"Should be there\"), 1);\n }\n\n #[test(should_fail_with = \"Should be there\")]\n fn expect_fails() {\n let _ = Option::<u8>::none().expect(f\"Should be there\");\n }\n\n #[test]\n fn map() {\n assert(Option::<u8>::none().map(|x| x + 1).is_none());\n assert_eq(Option::some(1).map(|x| x + 1), Option::some(2));\n }\n\n #[test]\n fn map_or() {\n assert_eq(Option::<u8>::none().map_or(0, |x| x + 1), 0);\n assert_eq(Option::some(1).map_or(0, |x| x + 1), 2);\n }\n\n #[test]\n fn map_or_else() {\n assert_eq(Option::<u8>::none().map_or_else(|| 0, |x| x + 1), 0);\n assert_eq(Option::some(1).map_or_else(|| 0, |x| x + 1), 2);\n }\n\n #[test]\n fn and() {\n assert_eq(Option::<u8>::none().and(Option::none()), Option::none());\n assert_eq(Option::<u8>::none().and(Option::some(1)), Option::none());\n assert_eq(Option::some(1).and(Option::some(2)), Option::some(2));\n assert_eq(Option::some(1).and(Option::none()), Option::none());\n }\n\n #[test]\n fn and_then() {\n assert_eq(Option::<u8>::none().and_then(|_| Option::<u8>::none()), Option::none());\n assert_eq(Option::<u8>::none().and_then(|_| Option::some(1)), Option::none());\n assert_eq(Option::some(1).and_then(|x| Option::some(x + 1)), Option::some(2));\n assert_eq(Option::some(1).and_then(|_| Option::<u8>::none()), Option::none());\n }\n\n #[test]\n fn or() {\n assert_eq(Option::<u8>::none().or(Option::none()), Option::none());\n assert_eq(Option::<u8>::none().or(Option::some(1)), Option::some(1));\n assert_eq(Option::some(1).or(Option::some(2)), Option::some(1));\n assert_eq(Option::some(1).or(Option::none()), Option::some(1));\n }\n\n #[test]\n fn or_else() {\n assert_eq(Option::<u8>::none().or_else(|| Option::none()), Option::none());\n assert_eq(Option::<u8>::none().or_else(|| Option::some(1)), Option::some(1));\n assert_eq(Option::some(1).or_else(|| Option::some(2)), Option::some(1));\n assert_eq(Option::some(1).or_else(|| Option::none()), Option::some(1));\n }\n\n #[test]\n fn xor() {\n assert_eq(Option::<u8>::none().xor(Option::none()), Option::none());\n assert_eq(Option::<u8>::none().xor(Option::some(1)), Option::some(1));\n assert_eq(Option::some(1).xor(Option::some(2)), Option::none());\n assert_eq(Option::some(1).xor(Option::none()), Option::some(1));\n }\n\n #[test]\n fn filter() {\n assert_eq(Option::<u8>::none().filter(|_| true), Option::none());\n assert_eq(Option::some(1).filter(|x| x == 1), Option::some(1));\n assert_eq(Option::some(1).filter(|x| x == 2), Option::none());\n assert_eq(Option::some(1).filter(|x| x == 2), Option::none());\n }\n\n #[test]\n fn flatten() {\n assert_eq(Option::<Option<u8>>::none().flatten(), Option::none());\n assert_eq(Option::some(Option::<u8>::none()).flatten(), Option::none());\n assert_eq(Option::some(Option::some(1)).flatten(), Option::some(1));\n }\n\n #[test]\n fn default() {\n assert_eq(Option::<u8>::default(), Option::none());\n }\n\n #[test]\n fn eq() {\n assert(Option::<u8>::none() == Option::none());\n assert(Option::<u8>::some(1) != Option::none());\n assert(Option::<u8>::none() != Option::some(1));\n assert(Option::<u8>::some(1) == Option::some(1));\n assert(Option::<u8>::some(1) != Option::some(2));\n }\n\n #[test]\n fn cmp() {\n let none = Option::<u8>::none();\n let one = Option::<u8>::some(1);\n let two = Option::<u8>::some(2);\n assert_eq(none.cmp(none), Ordering::equal());\n assert_eq(none.cmp(one), Ordering::less());\n assert_eq(one.cmp(none), Ordering::greater());\n assert_eq(one.cmp(one), Ordering::equal());\n assert_eq(one.cmp(two), Ordering::less());\n assert_eq(two.cmp(one), Ordering::greater());\n }\n}\n"
|
|
1816
2144
|
},
|
|
1817
|
-
"
|
|
2145
|
+
"44": {
|
|
1818
2146
|
"function_locations": [
|
|
1819
2147
|
{
|
|
1820
2148
|
"name": "panic",
|
|
1821
2149
|
"start": 196
|
|
1822
|
-
}
|
|
1823
|
-
],
|
|
1824
|
-
"path": "std/panic.nr",
|
|
1825
|
-
"source": "/// Halt the program at runtime with the given error message.\n///\n/// The provided error message must be either a `str` or a `fmtstr`.\npub fn panic<T, U>(message: T) -> U\nwhere\n T: StringLike,\n{\n assert(false, message);\n crate::mem::zeroed()\n}\n\ntrait StringLike {}\n\nimpl<let N: u32> StringLike for str<N> {}\nimpl<let N: u32, T> StringLike for fmtstr<N, T> {}\n"
|
|
1826
|
-
},
|
|
1827
|
-
"49": {
|
|
1828
|
-
"function_locations": [
|
|
1829
|
-
{
|
|
1830
|
-
"name": "calculate_fee",
|
|
1831
|
-
"start": 232
|
|
1832
2150
|
},
|
|
1833
2151
|
{
|
|
1834
|
-
"name": "
|
|
1835
|
-
"start":
|
|
2152
|
+
"name": "tests::panics",
|
|
2153
|
+
"start": 469
|
|
1836
2154
|
}
|
|
1837
2155
|
],
|
|
1838
|
-
"path": "/
|
|
1839
|
-
"source": "
|
|
2156
|
+
"path": "std/panic.nr",
|
|
2157
|
+
"source": "/// Halt the program at runtime with the given error message.\n///\n/// The provided error message must be either a `str` or a `fmtstr`.\npub fn panic<T, U>(message: T) -> U\nwhere\n T: StringLike,\n{\n assert(false, message);\n crate::mem::zeroed()\n}\n\ntrait StringLike {}\n\nimpl<let N: u32> StringLike for str<N> {}\nimpl<let N: u32, T> StringLike for fmtstr<N, T> {}\n\nmod tests {\n use crate::prelude::panic;\n\n #[test(should_fail_with = \"OH NO\")]\n fn panics() {\n panic(\"OH NO\");\n }\n}\n"
|
|
1840
2158
|
},
|
|
1841
2159
|
"5": {
|
|
1842
2160
|
"function_locations": [
|
|
@@ -1908,199 +2226,261 @@
|
|
|
1908
2226
|
"name": "make_tuple_eq_body",
|
|
1909
2227
|
"start": 2598
|
|
1910
2228
|
},
|
|
2229
|
+
{
|
|
2230
|
+
"name": "<impl Eq for (A,)>::eq",
|
|
2231
|
+
"start": 2848
|
|
2232
|
+
},
|
|
1911
2233
|
{
|
|
1912
2234
|
"name": "<impl Eq for (A, B)>::eq",
|
|
1913
|
-
"start":
|
|
2235
|
+
"start": 2959
|
|
1914
2236
|
},
|
|
1915
2237
|
{
|
|
1916
2238
|
"name": "<impl Eq for (A, B, C)>::eq",
|
|
1917
|
-
"start":
|
|
2239
|
+
"start": 3091
|
|
1918
2240
|
},
|
|
1919
2241
|
{
|
|
1920
2242
|
"name": "<impl Eq for (A, B, C, D)>::eq",
|
|
1921
|
-
"start":
|
|
2243
|
+
"start": 3236
|
|
1922
2244
|
},
|
|
1923
2245
|
{
|
|
1924
2246
|
"name": "<impl Eq for (A, B, C, D, E)>::eq",
|
|
1925
|
-
"start":
|
|
2247
|
+
"start": 3394
|
|
1926
2248
|
},
|
|
1927
2249
|
{
|
|
1928
2250
|
"name": "<impl Eq for (A, B, C, D, E, F)>::eq",
|
|
1929
|
-
"start":
|
|
2251
|
+
"start": 3565
|
|
1930
2252
|
},
|
|
1931
2253
|
{
|
|
1932
2254
|
"name": "<impl Eq for (A, B, C, D, E, F, G)>::eq",
|
|
1933
|
-
"start":
|
|
2255
|
+
"start": 3749
|
|
1934
2256
|
},
|
|
1935
2257
|
{
|
|
1936
2258
|
"name": "<impl Eq for (A, B, C, D, E, F, G, H)>::eq",
|
|
1937
|
-
"start":
|
|
2259
|
+
"start": 3946
|
|
1938
2260
|
},
|
|
1939
2261
|
{
|
|
1940
2262
|
"name": "<impl Eq for (A, B, C, D, E, F, G, H, I)>::eq",
|
|
1941
|
-
"start":
|
|
2263
|
+
"start": 4156
|
|
1942
2264
|
},
|
|
1943
2265
|
{
|
|
1944
2266
|
"name": "<impl Eq for (A, B, C, D, E, F, G, H, I, J)>::eq",
|
|
1945
|
-
"start":
|
|
2267
|
+
"start": 4379
|
|
1946
2268
|
},
|
|
1947
2269
|
{
|
|
1948
2270
|
"name": "<impl Eq for (A, B, C, D, E, F, G, H, I, J, K)>::eq",
|
|
1949
|
-
"start":
|
|
2271
|
+
"start": 4616
|
|
1950
2272
|
},
|
|
1951
2273
|
{
|
|
1952
2274
|
"name": "<impl Eq for (A, B, C, D, E, F, G, H, I, J, K, L)>::eq",
|
|
1953
|
-
"start":
|
|
2275
|
+
"start": 4866
|
|
1954
2276
|
},
|
|
1955
2277
|
{
|
|
1956
2278
|
"name": "<impl Eq for Ordering>::eq",
|
|
1957
|
-
"start":
|
|
2279
|
+
"start": 4976
|
|
1958
2280
|
},
|
|
1959
2281
|
{
|
|
1960
2282
|
"name": "Ordering::less",
|
|
1961
|
-
"start":
|
|
2283
|
+
"start": 5577
|
|
1962
2284
|
},
|
|
1963
2285
|
{
|
|
1964
2286
|
"name": "Ordering::equal",
|
|
1965
|
-
"start":
|
|
2287
|
+
"start": 5648
|
|
1966
2288
|
},
|
|
1967
2289
|
{
|
|
1968
2290
|
"name": "Ordering::greater",
|
|
1969
|
-
"start":
|
|
2291
|
+
"start": 5721
|
|
1970
2292
|
},
|
|
1971
2293
|
{
|
|
1972
2294
|
"name": "derive_ord",
|
|
1973
|
-
"start":
|
|
2295
|
+
"start": 6092
|
|
1974
2296
|
},
|
|
1975
2297
|
{
|
|
1976
2298
|
"name": "<impl Ord for u128>::cmp",
|
|
1977
|
-
"start":
|
|
2299
|
+
"start": 6742
|
|
1978
2300
|
},
|
|
1979
2301
|
{
|
|
1980
2302
|
"name": "<impl Ord for u64>::cmp",
|
|
1981
|
-
"start":
|
|
2303
|
+
"start": 6989
|
|
1982
2304
|
},
|
|
1983
2305
|
{
|
|
1984
2306
|
"name": "<impl Ord for u32>::cmp",
|
|
1985
|
-
"start":
|
|
2307
|
+
"start": 7237
|
|
1986
2308
|
},
|
|
1987
2309
|
{
|
|
1988
2310
|
"name": "<impl Ord for u16>::cmp",
|
|
1989
|
-
"start":
|
|
2311
|
+
"start": 7485
|
|
1990
2312
|
},
|
|
1991
2313
|
{
|
|
1992
2314
|
"name": "<impl Ord for u8>::cmp",
|
|
1993
|
-
"start":
|
|
2315
|
+
"start": 7731
|
|
1994
2316
|
},
|
|
1995
2317
|
{
|
|
1996
2318
|
"name": "<impl Ord for i8>::cmp",
|
|
1997
|
-
"start":
|
|
2319
|
+
"start": 7977
|
|
1998
2320
|
},
|
|
1999
2321
|
{
|
|
2000
2322
|
"name": "<impl Ord for i16>::cmp",
|
|
2001
|
-
"start":
|
|
2323
|
+
"start": 8225
|
|
2002
2324
|
},
|
|
2003
2325
|
{
|
|
2004
2326
|
"name": "<impl Ord for i32>::cmp",
|
|
2005
|
-
"start":
|
|
2327
|
+
"start": 8473
|
|
2006
2328
|
},
|
|
2007
2329
|
{
|
|
2008
2330
|
"name": "<impl Ord for i64>::cmp",
|
|
2009
|
-
"start":
|
|
2331
|
+
"start": 8721
|
|
2010
2332
|
},
|
|
2011
2333
|
{
|
|
2012
2334
|
"name": "<impl Ord for ()>::cmp",
|
|
2013
|
-
"start":
|
|
2335
|
+
"start": 8975
|
|
2014
2336
|
},
|
|
2015
2337
|
{
|
|
2016
2338
|
"name": "<impl Ord for bool>::cmp",
|
|
2017
|
-
"start":
|
|
2339
|
+
"start": 9074
|
|
2018
2340
|
},
|
|
2019
2341
|
{
|
|
2020
2342
|
"name": "<impl Ord for [T; N]>::cmp",
|
|
2021
|
-
"start":
|
|
2343
|
+
"start": 9544
|
|
2022
2344
|
},
|
|
2023
2345
|
{
|
|
2024
2346
|
"name": "<impl Ord for [T]>::cmp",
|
|
2025
|
-
"start":
|
|
2347
|
+
"start": 9947
|
|
2026
2348
|
},
|
|
2027
2349
|
{
|
|
2028
2350
|
"name": "make_tuple_ord_body",
|
|
2029
|
-
"start":
|
|
2351
|
+
"start": 10515
|
|
2352
|
+
},
|
|
2353
|
+
{
|
|
2354
|
+
"name": "<impl Ord for (A,)>::cmp",
|
|
2355
|
+
"start": 11125
|
|
2030
2356
|
},
|
|
2031
2357
|
{
|
|
2032
2358
|
"name": "<impl Ord for (A, B)>::cmp",
|
|
2033
|
-
"start":
|
|
2359
|
+
"start": 11246
|
|
2034
2360
|
},
|
|
2035
2361
|
{
|
|
2036
2362
|
"name": "<impl Ord for (A, B, C)>::cmp",
|
|
2037
|
-
"start":
|
|
2363
|
+
"start": 11388
|
|
2038
2364
|
},
|
|
2039
2365
|
{
|
|
2040
2366
|
"name": "<impl Ord for (A, B, C, D)>::cmp",
|
|
2041
|
-
"start":
|
|
2367
|
+
"start": 11544
|
|
2042
2368
|
},
|
|
2043
2369
|
{
|
|
2044
2370
|
"name": "<impl Ord for (A, B, C, D, E)>::cmp",
|
|
2045
|
-
"start":
|
|
2371
|
+
"start": 11714
|
|
2046
2372
|
},
|
|
2047
2373
|
{
|
|
2048
2374
|
"name": "<impl Ord for (A, B, C, D, E, F)>::cmp",
|
|
2049
|
-
"start":
|
|
2375
|
+
"start": 11898
|
|
2050
2376
|
},
|
|
2051
2377
|
{
|
|
2052
2378
|
"name": "<impl Ord for (A, B, C, D, E, F, G)>::cmp",
|
|
2053
|
-
"start":
|
|
2379
|
+
"start": 12096
|
|
2054
2380
|
},
|
|
2055
2381
|
{
|
|
2056
2382
|
"name": "<impl Ord for (A, B, C, D, E, F, G, H)>::cmp",
|
|
2057
|
-
"start":
|
|
2383
|
+
"start": 12308
|
|
2058
2384
|
},
|
|
2059
2385
|
{
|
|
2060
2386
|
"name": "<impl Ord for (A, B, C, D, E, F, G, H, I)>::cmp",
|
|
2061
|
-
"start":
|
|
2387
|
+
"start": 12534
|
|
2062
2388
|
},
|
|
2063
2389
|
{
|
|
2064
2390
|
"name": "<impl Ord for (A, B, C, D, E, F, G, H, I, J)>::cmp",
|
|
2065
|
-
"start":
|
|
2391
|
+
"start": 12774
|
|
2066
2392
|
},
|
|
2067
2393
|
{
|
|
2068
2394
|
"name": "<impl Ord for (A, B, C, D, E, F, G, H, I, J, K)>::cmp",
|
|
2069
|
-
"start":
|
|
2395
|
+
"start": 13029
|
|
2070
2396
|
},
|
|
2071
2397
|
{
|
|
2072
2398
|
"name": "<impl Ord for (A, B, C, D, E, F, G, H, I, J, K, L)>::cmp",
|
|
2073
|
-
"start":
|
|
2399
|
+
"start": 13298
|
|
2074
2400
|
},
|
|
2075
2401
|
{
|
|
2076
2402
|
"name": "max",
|
|
2077
|
-
"start":
|
|
2403
|
+
"start": 13660
|
|
2078
2404
|
},
|
|
2079
2405
|
{
|
|
2080
2406
|
"name": "min",
|
|
2081
|
-
"start":
|
|
2407
|
+
"start": 14037
|
|
2082
2408
|
},
|
|
2083
2409
|
{
|
|
2084
2410
|
"name": "cmp_tests::sanity_check_min",
|
|
2085
|
-
"start":
|
|
2411
|
+
"start": 14231
|
|
2086
2412
|
},
|
|
2087
2413
|
{
|
|
2088
2414
|
"name": "cmp_tests::sanity_check_max",
|
|
2089
|
-
"start":
|
|
2415
|
+
"start": 14427
|
|
2090
2416
|
},
|
|
2091
2417
|
{
|
|
2092
2418
|
"name": "cmp_tests::correctly_handles_unequal_length_vectors",
|
|
2093
|
-
"start":
|
|
2419
|
+
"start": 14649
|
|
2094
2420
|
},
|
|
2095
2421
|
{
|
|
2096
2422
|
"name": "cmp_tests::lexicographic_ordering_for_vectors",
|
|
2097
|
-
"start":
|
|
2423
|
+
"start": 14849
|
|
2424
|
+
},
|
|
2425
|
+
{
|
|
2426
|
+
"name": "cmp_tests::eq_unit",
|
|
2427
|
+
"start": 15181
|
|
2428
|
+
},
|
|
2429
|
+
{
|
|
2430
|
+
"name": "cmp_tests::eq_bool",
|
|
2431
|
+
"start": 15246
|
|
2432
|
+
},
|
|
2433
|
+
{
|
|
2434
|
+
"name": "cmp_tests::eq_integers",
|
|
2435
|
+
"start": 15422
|
|
2436
|
+
},
|
|
2437
|
+
{
|
|
2438
|
+
"name": "cmp_tests::eq_tuples",
|
|
2439
|
+
"start": 16163
|
|
2440
|
+
},
|
|
2441
|
+
{
|
|
2442
|
+
"name": "cmp_tests::cmp_unit",
|
|
2443
|
+
"start": 17041
|
|
2444
|
+
},
|
|
2445
|
+
{
|
|
2446
|
+
"name": "cmp_tests::cmp_bool",
|
|
2447
|
+
"start": 17130
|
|
2448
|
+
},
|
|
2449
|
+
{
|
|
2450
|
+
"name": "cmp_tests::cmp_integers",
|
|
2451
|
+
"start": 17394
|
|
2452
|
+
},
|
|
2453
|
+
{
|
|
2454
|
+
"name": "cmp_tests::cmp_tuples",
|
|
2455
|
+
"start": 18217
|
|
2456
|
+
},
|
|
2457
|
+
{
|
|
2458
|
+
"name": "cmp_tests::cmp_array",
|
|
2459
|
+
"start": 19224
|
|
2460
|
+
},
|
|
2461
|
+
{
|
|
2462
|
+
"name": "cmp_tests::cmp_vectors",
|
|
2463
|
+
"start": 19468
|
|
2098
2464
|
}
|
|
2099
2465
|
],
|
|
2100
2466
|
"path": "std/cmp.nr",
|
|
2101
|
-
"source": "use crate::meta::ctstring::AsCtString;\nuse crate::meta::derive_via;\n\n/// Compare two values for equality\n#[derive_via(derive_eq)]\n// docs:start:eq-trait\npub trait Eq {\n fn eq(self, other: Self) -> bool;\n}\n// docs:end:eq-trait\n\n// docs:start:derive_eq\ncomptime fn derive_eq(s: TypeDefinition) -> Quoted {\n let signature = quote { fn eq(_self: Self, _other: Self) -> bool };\n let for_each_field = |name| quote { (_self.$name == _other.$name) };\n let body = |fields| {\n if s.fields_as_written().len() == 0 {\n quote { true }\n } else {\n fields\n }\n };\n crate::meta::make_trait_impl(\n s,\n quote { $crate::cmp::Eq },\n signature,\n for_each_field,\n quote { & },\n body,\n )\n}\n// docs:end:derive_eq\n\nimpl Eq for Field {\n fn eq(self, other: Field) -> bool {\n self == other\n }\n}\n\nimpl Eq for u128 {\n fn eq(self, other: u128) -> bool {\n self == other\n }\n}\nimpl Eq for u64 {\n fn eq(self, other: u64) -> bool {\n self == other\n }\n}\nimpl Eq for u32 {\n fn eq(self, other: u32) -> bool {\n self == other\n }\n}\nimpl Eq for u16 {\n fn eq(self, other: u16) -> bool {\n self == other\n }\n}\nimpl Eq for u8 {\n fn eq(self, other: u8) -> bool {\n self == other\n }\n}\nimpl Eq for i8 {\n fn eq(self, other: i8) -> bool {\n self == other\n }\n}\nimpl Eq for i16 {\n fn eq(self, other: i16) -> bool {\n self == other\n }\n}\nimpl Eq for i32 {\n fn eq(self, other: i32) -> bool {\n self == other\n }\n}\nimpl Eq for i64 {\n fn eq(self, other: i64) -> bool {\n self == other\n }\n}\n\nimpl Eq for () {\n fn eq(_self: Self, _other: ()) -> bool {\n true\n }\n}\nimpl Eq for bool {\n fn eq(self, other: bool) -> bool {\n self == other\n }\n}\n\nimpl<T, let N: u32> Eq for [T; N]\nwhere\n T: Eq,\n{\n fn eq(self, other: [T; N]) -> bool {\n let mut result = true;\n for i in 0..self.len() {\n result &= self[i].eq(other[i]);\n }\n result\n }\n}\n\nimpl<T> Eq for [T]\nwhere\n T: Eq,\n{\n fn eq(self, other: [T]) -> bool {\n let mut result = self.len() == other.len();\n if result {\n for i in 0..self.len() {\n result &= self[i].eq(other[i]);\n }\n }\n result\n }\n}\n\nimpl<let N: u32> Eq for str<N> {\n fn eq(self, other: str<N>) -> bool {\n let self_bytes = self.as_bytes();\n let other_bytes = other.as_bytes();\n self_bytes == other_bytes\n }\n}\n\ncomptime fn make_tuple_eq_body(n: u32) -> Quoted {\n let mut body = f\"self.0.eq(other.0)\".as_ctstring();\n for i in 1u32..n {\n body = body.append_fmtstr(f\" & self.{i}.eq(other.{i})\");\n }\n f\"{body}\".quoted_contents()\n}\n\nimpl<A: Eq, B: Eq> Eq for (A, B) {\n fn eq(self, other: (A, B)) -> bool {\n make_tuple_eq_body!(2u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq> Eq for (A, B, C) {\n fn eq(self, other: (A, B, C)) -> bool {\n make_tuple_eq_body!(3u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq> Eq for (A, B, C, D) {\n fn eq(self, other: (A, B, C, D)) -> bool {\n make_tuple_eq_body!(4u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq, E: Eq> Eq for (A, B, C, D, E) {\n fn eq(self, other: (A, B, C, D, E)) -> bool {\n make_tuple_eq_body!(5u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq> Eq for (A, B, C, D, E, F) {\n fn eq(self, other: (A, B, C, D, E, F)) -> bool {\n make_tuple_eq_body!(6u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq, G: Eq> Eq for (A, B, C, D, E, F, G) {\n fn eq(self, other: (A, B, C, D, E, F, G)) -> bool {\n make_tuple_eq_body!(7u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq, G: Eq, H: Eq> Eq for (A, B, C, D, E, F, G, H) {\n fn eq(self, other: (A, B, C, D, E, F, G, H)) -> bool {\n make_tuple_eq_body!(8u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq, G: Eq, H: Eq, I: Eq> Eq for (A, B, C, D, E, F, G, H, I) {\n fn eq(self, other: (A, B, C, D, E, F, G, H, I)) -> bool {\n make_tuple_eq_body!(9u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq, G: Eq, H: Eq, I: Eq, J: Eq> Eq for (A, B, C, D, E, F, G, H, I, J) {\n fn eq(self, other: (A, B, C, D, E, F, G, H, I, J)) -> bool {\n make_tuple_eq_body!(10u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq, G: Eq, H: Eq, I: Eq, J: Eq, K: Eq> Eq for (A, B, C, D, E, F, G, H, I, J, K) {\n fn eq(self, other: (A, B, C, D, E, F, G, H, I, J, K)) -> bool {\n make_tuple_eq_body!(11u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq, G: Eq, H: Eq, I: Eq, J: Eq, K: Eq, L: Eq> Eq for (A, B, C, D, E, F, G, H, I, J, K, L) {\n fn eq(self, other: (A, B, C, D, E, F, G, H, I, J, K, L)) -> bool {\n make_tuple_eq_body!(12u32)\n }\n}\n\nimpl Eq for Ordering {\n fn eq(self, other: Ordering) -> bool {\n self.result == other.result\n }\n}\n\n// Noir doesn't have enums yet so we emulate (Lt | Eq | Gt) with a struct\n// that has 3 public functions for constructing the struct.\n/// A value with three states: `Ordering::less()`, `Ordering::equal()` or `Ordering::greater()`.\n/// Most often used to encode the result of a comparison operation.\npub struct Ordering {\n result: Field,\n}\n\nimpl Ordering {\n // Implementation note: 0, 1, and 2 for Lt, Eq, and Gt are built\n // into the compiler, do not change these without also updating\n // the compiler itself!\n pub fn less() -> Ordering {\n Ordering { result: 0 }\n }\n\n pub fn equal() -> Ordering {\n Ordering { result: 1 }\n }\n\n pub fn greater() -> Ordering {\n Ordering { result: 2 }\n }\n}\n\n/// Compare one object to another, returning whether it is less-than, equal-to,\n/// or greater-than the other object.\n#[derive_via(derive_ord)]\n// docs:start:ord-trait\npub trait Ord {\n fn cmp(self, other: Self) -> Ordering;\n}\n// docs:end:ord-trait\n\n// docs:start:derive_ord\ncomptime fn derive_ord(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::cmp::Ord };\n let signature = quote { fn cmp(_self: Self, _other: Self) -> $crate::cmp::Ordering };\n let for_each_field = |name| quote {\n if result == $crate::cmp::Ordering::equal() {\n result = _self.$name.cmp(_other.$name);\n }\n };\n let body = |fields| quote {\n let mut result = $crate::cmp::Ordering::equal();\n $fields\n result\n };\n crate::meta::make_trait_impl(s, name, signature, for_each_field, quote {}, body)\n}\n// docs:end:derive_ord\n\n// Note: Field deliberately does not implement Ord\n\nimpl Ord for u128 {\n fn cmp(self, other: u128) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\nimpl Ord for u64 {\n fn cmp(self, other: u64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u32 {\n fn cmp(self, other: u32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u16 {\n fn cmp(self, other: u16) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u8 {\n fn cmp(self, other: u8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i8 {\n fn cmp(self, other: i8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i16 {\n fn cmp(self, other: i16) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i32 {\n fn cmp(self, other: i32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i64 {\n fn cmp(self, other: i64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for () {\n fn cmp(_self: Self, _other: ()) -> Ordering {\n Ordering::equal()\n }\n}\n\nimpl Ord for bool {\n fn cmp(self, other: bool) -> Ordering {\n if self {\n if other {\n Ordering::equal()\n } else {\n Ordering::greater()\n }\n } else if other {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl<T, let N: u32> Ord for [T; N]\nwhere\n T: Ord,\n{\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T; N]) -> Ordering {\n let mut result = Ordering::equal();\n for i in 0..self.len() {\n if result == Ordering::equal() {\n result = self[i].cmp(other[i]);\n }\n }\n result\n }\n}\n\nimpl<T> Ord for [T]\nwhere\n T: Ord,\n{\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T]) -> Ordering {\n let self_len = self.len();\n let other_len = other.len();\n let min_len = if self_len < other_len {\n self_len\n } else {\n other_len\n };\n\n let mut result = Ordering::equal();\n for i in 0..min_len {\n if result == Ordering::equal() {\n result = self[i].cmp(other[i]);\n }\n }\n\n if result != Ordering::equal() {\n result\n } else {\n self_len.cmp(other_len)\n }\n }\n}\n\ncomptime fn make_tuple_ord_body(n: u32) -> Quoted {\n let last = n - 1u32;\n let mut body = if last == 1 {\n f\"let result = self.0.cmp(other.0);\".as_ctstring()\n } else {\n f\"let mut result = self.0.cmp(other.0);\".as_ctstring()\n };\n for i in 1u32..last {\n body = body.append_fmtstr(\n f\" if result == Ordering::equal() {{ result = self.{i}.cmp(other.{i}); }}\",\n );\n }\n body = body.append_fmtstr(\n f\" if result != Ordering::equal() {{ result }} else {{ self.{last}.cmp(other.{last}) }}\",\n );\n f\"{body}\".quoted_contents()\n}\n\nimpl<A: Ord, B: Ord> Ord for (A, B) {\n fn cmp(self, other: (A, B)) -> Ordering {\n make_tuple_ord_body!(2u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord> Ord for (A, B, C) {\n fn cmp(self, other: (A, B, C)) -> Ordering {\n make_tuple_ord_body!(3u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord> Ord for (A, B, C, D) {\n fn cmp(self, other: (A, B, C, D)) -> Ordering {\n make_tuple_ord_body!(4u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord, E: Ord> Ord for (A, B, C, D, E) {\n fn cmp(self, other: (A, B, C, D, E)) -> Ordering {\n make_tuple_ord_body!(5u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord, E: Ord, F: Ord> Ord for (A, B, C, D, E, F) {\n fn cmp(self, other: (A, B, C, D, E, F)) -> Ordering {\n make_tuple_ord_body!(6u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord, E: Ord, F: Ord, G: Ord> Ord for (A, B, C, D, E, F, G) {\n fn cmp(self, other: (A, B, C, D, E, F, G)) -> Ordering {\n make_tuple_ord_body!(7u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord, E: Ord, F: Ord, G: Ord, H: Ord> Ord for (A, B, C, D, E, F, G, H) {\n fn cmp(self, other: (A, B, C, D, E, F, G, H)) -> Ordering {\n make_tuple_ord_body!(8u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord, E: Ord, F: Ord, G: Ord, H: Ord, I: Ord> Ord for (A, B, C, D, E, F, G, H, I) {\n fn cmp(self, other: (A, B, C, D, E, F, G, H, I)) -> Ordering {\n make_tuple_ord_body!(9u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord, E: Ord, F: Ord, G: Ord, H: Ord, I: Ord, J: Ord> Ord for (A, B, C, D, E, F, G, H, I, J) {\n fn cmp(self, other: (A, B, C, D, E, F, G, H, I, J)) -> Ordering {\n make_tuple_ord_body!(10u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord, E: Ord, F: Ord, G: Ord, H: Ord, I: Ord, J: Ord, K: Ord> Ord for (A, B, C, D, E, F, G, H, I, J, K) {\n fn cmp(self, other: (A, B, C, D, E, F, G, H, I, J, K)) -> Ordering {\n make_tuple_ord_body!(11u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord, E: Ord, F: Ord, G: Ord, H: Ord, I: Ord, J: Ord, K: Ord, L: Ord> Ord for (A, B, C, D, E, F, G, H, I, J, K, L) {\n fn cmp(self, other: (A, B, C, D, E, F, G, H, I, J, K, L)) -> Ordering {\n make_tuple_ord_body!(12u32)\n }\n}\n\n/// Compares and returns the maximum of two values.\n///\n/// Returns the second argument if the comparison determines them to be equal.\n///\n/// # Examples\n///\n/// ```\n/// use std::cmp;\n///\n/// assert_eq(cmp::max(1, 2), 2);\n/// assert_eq(cmp::max(2, 2), 2);\n/// ```\npub fn max<T>(v1: T, v2: T) -> T\nwhere\n T: Ord,\n{\n if v1 > v2 {\n v1\n } else {\n v2\n }\n}\n\n/// Compares and returns the minimum of two values.\n///\n/// Returns the first argument if the comparison determines them to be equal.\n///\n/// # Examples\n///\n/// ```\n/// use std::cmp;\n///\n/// assert_eq(cmp::min(1, 2), 1);\n/// assert_eq(cmp::min(2, 2), 2);\n/// ```\npub fn min<T>(v1: T, v2: T) -> T\nwhere\n T: Ord,\n{\n if v1 > v2 {\n v2\n } else {\n v1\n }\n}\n\nmod cmp_tests {\n use super::{Eq, max, min, Ord};\n\n #[test]\n fn sanity_check_min() {\n assert_eq(min(0_u64, 1), 0);\n assert_eq(min(0_u64, 0), 0);\n assert_eq(min(1_u64, 1), 1);\n assert_eq(min(255_u8, 0), 0);\n }\n\n #[test]\n fn sanity_check_max() {\n assert_eq(max(0_u64, 1), 1);\n assert_eq(max(0_u64, 0), 0);\n assert_eq(max(1_u64, 1), 1);\n assert_eq(max(255_u8, 0), 255);\n }\n\n #[test]\n fn correctly_handles_unequal_length_vectors() {\n let vector_1 = [0, 1, 2, 3].as_vector();\n let vector_2 = [0, 1, 2].as_vector();\n assert(!vector_1.eq(vector_2));\n }\n\n #[test]\n fn lexicographic_ordering_for_vectors() {\n assert(\n [2_u32].as_vector().cmp([1_u32, 1_u32, 1_u32].as_vector())\n == super::Ordering::greater(),\n );\n assert(\n [1_u32, 2_u32].as_vector().cmp([1_u32, 2_u32, 3_u32].as_vector())\n == super::Ordering::less(),\n );\n }\n}\n"
|
|
2467
|
+
"source": "use crate::meta::ctstring::AsCtString;\nuse crate::meta::derive_via;\n\n/// Compare two values for equality\n#[derive_via(derive_eq)]\n// docs:start:eq-trait\npub trait Eq {\n fn eq(self, other: Self) -> bool;\n}\n// docs:end:eq-trait\n\n// docs:start:derive_eq\ncomptime fn derive_eq(s: TypeDefinition) -> Quoted {\n let signature = quote { fn eq(_self: Self, _other: Self) -> bool };\n let for_each_field = |name| quote { (_self.$name == _other.$name) };\n let body = |fields| {\n if s.fields_as_written().len() == 0 {\n quote { true }\n } else {\n fields\n }\n };\n crate::meta::make_trait_impl(\n s,\n quote { $crate::cmp::Eq },\n signature,\n for_each_field,\n quote { & },\n body,\n )\n}\n// docs:end:derive_eq\n\nimpl Eq for Field {\n fn eq(self, other: Field) -> bool {\n self == other\n }\n}\n\nimpl Eq for u128 {\n fn eq(self, other: u128) -> bool {\n self == other\n }\n}\nimpl Eq for u64 {\n fn eq(self, other: u64) -> bool {\n self == other\n }\n}\nimpl Eq for u32 {\n fn eq(self, other: u32) -> bool {\n self == other\n }\n}\nimpl Eq for u16 {\n fn eq(self, other: u16) -> bool {\n self == other\n }\n}\nimpl Eq for u8 {\n fn eq(self, other: u8) -> bool {\n self == other\n }\n}\nimpl Eq for i8 {\n fn eq(self, other: i8) -> bool {\n self == other\n }\n}\nimpl Eq for i16 {\n fn eq(self, other: i16) -> bool {\n self == other\n }\n}\nimpl Eq for i32 {\n fn eq(self, other: i32) -> bool {\n self == other\n }\n}\nimpl Eq for i64 {\n fn eq(self, other: i64) -> bool {\n self == other\n }\n}\n\nimpl Eq for () {\n fn eq(_self: Self, _other: ()) -> bool {\n true\n }\n}\nimpl Eq for bool {\n fn eq(self, other: bool) -> bool {\n self == other\n }\n}\n\nimpl<T, let N: u32> Eq for [T; N]\nwhere\n T: Eq,\n{\n fn eq(self, other: [T; N]) -> bool {\n let mut result = true;\n for i in 0..self.len() {\n result &= self[i].eq(other[i]);\n }\n result\n }\n}\n\nimpl<T> Eq for [T]\nwhere\n T: Eq,\n{\n fn eq(self, other: [T]) -> bool {\n let mut result = self.len() == other.len();\n if result {\n for i in 0..self.len() {\n result &= self[i].eq(other[i]);\n }\n }\n result\n }\n}\n\nimpl<let N: u32> Eq for str<N> {\n fn eq(self, other: str<N>) -> bool {\n let self_bytes = self.as_bytes();\n let other_bytes = other.as_bytes();\n self_bytes == other_bytes\n }\n}\n\ncomptime fn make_tuple_eq_body(n: u32) -> Quoted {\n let mut body = f\"self.0.eq(other.0)\".as_ctstring();\n for i in 1u32..n {\n body = body.append_fmtstr(f\" & self.{i}.eq(other.{i})\");\n }\n f\"{body}\".quoted_contents()\n}\n\nimpl<A: Eq> Eq for (A,) {\n fn eq(self, other: (A,)) -> bool {\n self.0 == other.0\n }\n}\n\nimpl<A: Eq, B: Eq> Eq for (A, B) {\n fn eq(self, other: (A, B)) -> bool {\n make_tuple_eq_body!(2u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq> Eq for (A, B, C) {\n fn eq(self, other: (A, B, C)) -> bool {\n make_tuple_eq_body!(3u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq> Eq for (A, B, C, D) {\n fn eq(self, other: (A, B, C, D)) -> bool {\n make_tuple_eq_body!(4u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq, E: Eq> Eq for (A, B, C, D, E) {\n fn eq(self, other: (A, B, C, D, E)) -> bool {\n make_tuple_eq_body!(5u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq> Eq for (A, B, C, D, E, F) {\n fn eq(self, other: (A, B, C, D, E, F)) -> bool {\n make_tuple_eq_body!(6u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq, G: Eq> Eq for (A, B, C, D, E, F, G) {\n fn eq(self, other: (A, B, C, D, E, F, G)) -> bool {\n make_tuple_eq_body!(7u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq, G: Eq, H: Eq> Eq for (A, B, C, D, E, F, G, H) {\n fn eq(self, other: (A, B, C, D, E, F, G, H)) -> bool {\n make_tuple_eq_body!(8u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq, G: Eq, H: Eq, I: Eq> Eq for (A, B, C, D, E, F, G, H, I) {\n fn eq(self, other: (A, B, C, D, E, F, G, H, I)) -> bool {\n make_tuple_eq_body!(9u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq, G: Eq, H: Eq, I: Eq, J: Eq> Eq for (A, B, C, D, E, F, G, H, I, J) {\n fn eq(self, other: (A, B, C, D, E, F, G, H, I, J)) -> bool {\n make_tuple_eq_body!(10u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq, G: Eq, H: Eq, I: Eq, J: Eq, K: Eq> Eq for (A, B, C, D, E, F, G, H, I, J, K) {\n fn eq(self, other: (A, B, C, D, E, F, G, H, I, J, K)) -> bool {\n make_tuple_eq_body!(11u32)\n }\n}\n\nimpl<A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq, G: Eq, H: Eq, I: Eq, J: Eq, K: Eq, L: Eq> Eq for (A, B, C, D, E, F, G, H, I, J, K, L) {\n fn eq(self, other: (A, B, C, D, E, F, G, H, I, J, K, L)) -> bool {\n make_tuple_eq_body!(12u32)\n }\n}\n\nimpl Eq for Ordering {\n fn eq(self, other: Ordering) -> bool {\n self.result == other.result\n }\n}\n\n// Noir doesn't have enums yet so we emulate (Lt | Eq | Gt) with a struct\n// that has 3 public functions for constructing the struct.\n/// A value with three states: `Ordering::less()`, `Ordering::equal()` or `Ordering::greater()`.\n/// Most often used to encode the result of a comparison operation.\npub struct Ordering {\n result: Field,\n}\n\nimpl Ordering {\n // Implementation note: 0, 1, and 2 for Lt, Eq, and Gt are built\n // into the compiler, do not change these without also updating\n // the compiler itself!\n pub fn less() -> Ordering {\n Ordering { result: 0 }\n }\n\n pub fn equal() -> Ordering {\n Ordering { result: 1 }\n }\n\n pub fn greater() -> Ordering {\n Ordering { result: 2 }\n }\n}\n\n/// Compare one object to another, returning whether it is less-than, equal-to,\n/// or greater-than the other object.\n#[derive_via(derive_ord)]\n// docs:start:ord-trait\npub trait Ord {\n fn cmp(self, other: Self) -> Ordering;\n}\n// docs:end:ord-trait\n\n// docs:start:derive_ord\ncomptime fn derive_ord(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::cmp::Ord };\n let signature = quote { fn cmp(_self: Self, _other: Self) -> $crate::cmp::Ordering };\n let for_each_field = |name| quote {\n if result == $crate::cmp::Ordering::equal() {\n result = _self.$name.cmp(_other.$name);\n }\n };\n let body = |fields| quote {\n let mut result = $crate::cmp::Ordering::equal();\n $fields\n result\n };\n crate::meta::make_trait_impl(s, name, signature, for_each_field, quote {}, body)\n}\n// docs:end:derive_ord\n\n// Note: Field deliberately does not implement Ord\n\nimpl Ord for u128 {\n fn cmp(self, other: u128) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\nimpl Ord for u64 {\n fn cmp(self, other: u64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u32 {\n fn cmp(self, other: u32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u16 {\n fn cmp(self, other: u16) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u8 {\n fn cmp(self, other: u8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i8 {\n fn cmp(self, other: i8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i16 {\n fn cmp(self, other: i16) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i32 {\n fn cmp(self, other: i32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i64 {\n fn cmp(self, other: i64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for () {\n fn cmp(_self: Self, _other: ()) -> Ordering {\n Ordering::equal()\n }\n}\n\nimpl Ord for bool {\n fn cmp(self, other: bool) -> Ordering {\n if self {\n if other {\n Ordering::equal()\n } else {\n Ordering::greater()\n }\n } else if other {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl<T, let N: u32> Ord for [T; N]\nwhere\n T: Ord,\n{\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T; N]) -> Ordering {\n let mut result = Ordering::equal();\n for i in 0..self.len() {\n if result == Ordering::equal() {\n result = self[i].cmp(other[i]);\n }\n }\n result\n }\n}\n\nimpl<T> Ord for [T]\nwhere\n T: Ord,\n{\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T]) -> Ordering {\n let self_len = self.len();\n let other_len = other.len();\n let min_len = if self_len < other_len {\n self_len\n } else {\n other_len\n };\n\n let mut result = Ordering::equal();\n for i in 0..min_len {\n if result == Ordering::equal() {\n result = self[i].cmp(other[i]);\n }\n }\n\n if result != Ordering::equal() {\n result\n } else {\n self_len.cmp(other_len)\n }\n }\n}\n\ncomptime fn make_tuple_ord_body(n: u32) -> Quoted {\n let last = n - 1u32;\n let mut body = if last == 1 {\n f\"let result = self.0.cmp(other.0);\".as_ctstring()\n } else {\n f\"let mut result = self.0.cmp(other.0);\".as_ctstring()\n };\n for i in 1u32..last {\n body = body.append_fmtstr(\n f\" if result == Ordering::equal() {{ result = self.{i}.cmp(other.{i}); }}\",\n );\n }\n body = body.append_fmtstr(\n f\" if result != Ordering::equal() {{ result }} else {{ self.{last}.cmp(other.{last}) }}\",\n );\n f\"{body}\".quoted_contents()\n}\n\nimpl<A: Ord> Ord for (A,) {\n fn cmp(self, other: (A,)) -> Ordering {\n self.0.cmp(other.0)\n }\n}\n\nimpl<A: Ord, B: Ord> Ord for (A, B) {\n fn cmp(self, other: (A, B)) -> Ordering {\n make_tuple_ord_body!(2u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord> Ord for (A, B, C) {\n fn cmp(self, other: (A, B, C)) -> Ordering {\n make_tuple_ord_body!(3u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord> Ord for (A, B, C, D) {\n fn cmp(self, other: (A, B, C, D)) -> Ordering {\n make_tuple_ord_body!(4u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord, E: Ord> Ord for (A, B, C, D, E) {\n fn cmp(self, other: (A, B, C, D, E)) -> Ordering {\n make_tuple_ord_body!(5u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord, E: Ord, F: Ord> Ord for (A, B, C, D, E, F) {\n fn cmp(self, other: (A, B, C, D, E, F)) -> Ordering {\n make_tuple_ord_body!(6u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord, E: Ord, F: Ord, G: Ord> Ord for (A, B, C, D, E, F, G) {\n fn cmp(self, other: (A, B, C, D, E, F, G)) -> Ordering {\n make_tuple_ord_body!(7u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord, E: Ord, F: Ord, G: Ord, H: Ord> Ord for (A, B, C, D, E, F, G, H) {\n fn cmp(self, other: (A, B, C, D, E, F, G, H)) -> Ordering {\n make_tuple_ord_body!(8u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord, E: Ord, F: Ord, G: Ord, H: Ord, I: Ord> Ord for (A, B, C, D, E, F, G, H, I) {\n fn cmp(self, other: (A, B, C, D, E, F, G, H, I)) -> Ordering {\n make_tuple_ord_body!(9u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord, E: Ord, F: Ord, G: Ord, H: Ord, I: Ord, J: Ord> Ord for (A, B, C, D, E, F, G, H, I, J) {\n fn cmp(self, other: (A, B, C, D, E, F, G, H, I, J)) -> Ordering {\n make_tuple_ord_body!(10u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord, E: Ord, F: Ord, G: Ord, H: Ord, I: Ord, J: Ord, K: Ord> Ord for (A, B, C, D, E, F, G, H, I, J, K) {\n fn cmp(self, other: (A, B, C, D, E, F, G, H, I, J, K)) -> Ordering {\n make_tuple_ord_body!(11u32)\n }\n}\n\nimpl<A: Ord, B: Ord, C: Ord, D: Ord, E: Ord, F: Ord, G: Ord, H: Ord, I: Ord, J: Ord, K: Ord, L: Ord> Ord for (A, B, C, D, E, F, G, H, I, J, K, L) {\n fn cmp(self, other: (A, B, C, D, E, F, G, H, I, J, K, L)) -> Ordering {\n make_tuple_ord_body!(12u32)\n }\n}\n\n/// Compares and returns the maximum of two values.\n///\n/// Returns the second argument if the comparison determines them to be equal.\n///\n/// # Examples\n///\n/// ```\n/// use std::cmp;\n///\n/// assert_eq(cmp::max(1, 2), 2);\n/// assert_eq(cmp::max(2, 2), 2);\n/// ```\npub fn max<T>(v1: T, v2: T) -> T\nwhere\n T: Ord,\n{\n if v1 > v2 {\n v1\n } else {\n v2\n }\n}\n\n/// Compares and returns the minimum of two values.\n///\n/// Returns the first argument if the comparison determines them to be equal.\n///\n/// # Examples\n///\n/// ```\n/// use std::cmp;\n///\n/// assert_eq(cmp::min(1, 2), 1);\n/// assert_eq(cmp::min(2, 2), 2);\n/// ```\npub fn min<T>(v1: T, v2: T) -> T\nwhere\n T: Ord,\n{\n if v1 > v2 {\n v2\n } else {\n v1\n }\n}\n\nmod cmp_tests {\n use crate::meta::unquote;\n use super::{Eq, max, min, Ord, Ordering};\n\n #[test]\n fn sanity_check_min() {\n assert_eq(min(0_u64, 1), 0);\n assert_eq(min(0_u64, 0), 0);\n assert_eq(min(1_u64, 1), 1);\n assert_eq(min(255_u8, 0), 0);\n }\n\n #[test]\n fn sanity_check_max() {\n assert_eq(max(0_u64, 1), 1);\n assert_eq(max(0_u64, 0), 0);\n assert_eq(max(1_u64, 1), 1);\n assert_eq(max(255_u8, 0), 255);\n }\n\n #[test]\n fn correctly_handles_unequal_length_vectors() {\n let vector_1 = [0, 1, 2, 3].as_vector();\n let vector_2 = [0, 1, 2].as_vector();\n assert(!vector_1.eq(vector_2));\n }\n\n #[test]\n fn lexicographic_ordering_for_vectors() {\n assert(\n [2_u32].as_vector().cmp([1_u32, 1_u32, 1_u32].as_vector())\n == super::Ordering::greater(),\n );\n assert(\n [1_u32, 2_u32].as_vector().cmp([1_u32, 2_u32, 3_u32].as_vector())\n == super::Ordering::less(),\n );\n }\n\n #[test]\n fn eq_unit() {\n assert(().eq(()));\n }\n\n #[test]\n fn eq_bool() {\n assert(false.eq(false));\n assert(!(false.eq(true)));\n assert(!(true.eq(false)));\n assert(true.eq(true));\n }\n\n #[test]\n fn eq_integers() {\n comptime {\n for typ in @[\n quote { u8 },\n quote { i8 },\n quote { u16 },\n quote { i16 },\n quote { u32 },\n quote { i32 },\n quote { u64 },\n quote { i64 },\n quote { u128 },\n quote { Field },\n ] {\n let one = f\"1_{typ}\".quoted_contents();\n let two = f\"2_{typ}\".quoted_contents();\n unquote!(\n quote {\n assert($one.eq($one));\n assert(!($one.eq($two)));\n },\n );\n }\n }\n }\n\n #[test]\n fn eq_tuples() {\n comptime {\n for i in 1..=12 {\n let mut tuple1 = @[];\n let mut tuple2 = @[];\n for _ in 0..i - 1 {\n tuple1 = tuple1.push_back(quote { 0 });\n tuple2 = tuple2.push_back(quote { 0 });\n }\n tuple1 = tuple1.push_back(quote { 0 });\n tuple2 = tuple2.push_back(quote { 1 });\n let tuple1 = tuple1.join(quote { , });\n let tuple2 = tuple2.join(quote { , });\n let tuple1 = quote { ($tuple1,) };\n let tuple2 = quote { ($tuple2,) };\n unquote!(\n quote {\n assert($tuple1.eq($tuple1));\n assert(!($tuple1.eq($tuple2)));\n },\n )\n }\n }\n }\n\n #[test]\n fn cmp_unit() {\n assert_eq(().cmp(()), Ordering::equal());\n }\n\n #[test]\n fn cmp_bool() {\n assert_eq(false.cmp(true), Ordering::less());\n assert_eq(false.cmp(false), Ordering::equal());\n assert_eq(true.cmp(true), Ordering::equal());\n assert_eq(true.cmp(false), Ordering::greater());\n }\n\n #[test]\n fn cmp_integers() {\n comptime {\n for typ in @[\n quote { u8 },\n quote { i8 },\n quote { u16 },\n quote { i16 },\n quote { u32 },\n quote { i32 },\n quote { u64 },\n quote { i64 },\n quote { u128 },\n ] {\n let one = f\"1_{typ}\".quoted_contents();\n let two = f\"2_{typ}\".quoted_contents();\n unquote!(\n quote {\n assert_eq($one.cmp($two), Ordering::less());\n assert_eq($one.cmp($one), Ordering::equal());\n assert_eq($two.cmp($one), Ordering::greater());\n },\n );\n }\n }\n }\n\n #[test]\n fn cmp_tuples() {\n comptime {\n for i in 1..=12 {\n let mut tuple1 = @[];\n let mut tuple2 = @[];\n for _ in 0..i - 1 {\n tuple1 = tuple1.push_back(quote { 0_u8 });\n tuple2 = tuple2.push_back(quote { 0_u8 });\n }\n tuple1 = tuple1.push_back(quote { 0_u8 });\n tuple2 = tuple2.push_back(quote { 1_u8 });\n let tuple1 = tuple1.join(quote { , });\n let tuple2 = tuple2.join(quote { , });\n let tuple1 = quote { ($tuple1,) };\n let tuple2 = quote { ($tuple2,) };\n unquote!(\n quote {\n assert_eq($tuple1.cmp($tuple1), Ordering::equal());\n assert_eq($tuple1.cmp($tuple2), Ordering::less());\n assert_eq($tuple2.cmp($tuple1), Ordering::greater());\n },\n )\n }\n }\n }\n\n #[test]\n fn cmp_array() {\n assert_eq([1_u8, 2, 3].cmp([1, 2, 3]), Ordering::equal());\n assert_eq([1_u8, 2, 3].cmp([1, 3, 2]), Ordering::less());\n assert_eq([1_u8, 3, 3].cmp([1, 2, 3]), Ordering::greater());\n }\n\n #[test]\n fn cmp_vectors() {\n // Equal lengths\n assert_eq(@[1_u8, 2, 3].cmp(@[1, 2, 3]), Ordering::equal());\n assert_eq(@[1_u8, 3, 3].cmp(@[1, 2, 3]), Ordering::greater());\n assert_eq(@[1_u8, 2, 3].cmp(@[1, 3, 3]), Ordering::less());\n\n // Different lengths\n assert_eq(@[1_u8, 2].cmp(@[1, 2, 3]), Ordering::less());\n assert_eq(@[1_u8, 2, 3].cmp(@[1, 2]), Ordering::greater());\n assert_eq(@[10_u8, 0].cmp(@[9]), Ordering::greater());\n assert_eq(@[9_u8, 0].cmp(@[10]), Ordering::less());\n assert_eq(@[9_u8].cmp(@[10, 0]), Ordering::less());\n assert_eq(@[10_u8].cmp(@[9, 0]), Ordering::greater());\n }\n}\n"
|
|
2102
2468
|
},
|
|
2103
|
-
"
|
|
2469
|
+
"52": {
|
|
2470
|
+
"function_locations": [
|
|
2471
|
+
{
|
|
2472
|
+
"name": "calculate_fee",
|
|
2473
|
+
"start": 232
|
|
2474
|
+
},
|
|
2475
|
+
{
|
|
2476
|
+
"name": "get_bridge_gas_msg_hash",
|
|
2477
|
+
"start": 747
|
|
2478
|
+
}
|
|
2479
|
+
],
|
|
2480
|
+
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-contracts/contracts/protocol/fee_juice_contract/src/lib.nr",
|
|
2481
|
+
"source": "use aztec::context::PublicContext;\nuse aztec::protocol::address::AztecAddress;\nuse aztec::protocol::hash::sha256_to_field;\nuse aztec::protocol::traits::ToField;\n\npub fn calculate_fee<TPublicContext>(context: PublicContext) -> Field {\n context.transaction_fee()\n}\n\n/// Computes the content hash for an L1-to-L2 \"bridge gas\" message, matching the hash produced on L1 by\n/// `FeeJuicePortal.depositToAztecPublic`: `sha256ToField(abi.encodeWithSignature(\"claim(bytes32,uint256)\", to,\n/// amount))`.\n///\n/// The 68-byte buffer is: [4-byte selector of \"claim(bytes32,uint256)\"][32-byte recipient][32-byte amount], hashed\n/// with `sha256_to_field` to produce a single Field.\npub fn get_bridge_gas_msg_hash(owner: AztecAddress, amount: u128) -> Field {\n let mut hash_bytes = [0; 68];\n let recipient_bytes: [u8; 32] = owner.to_field().to_be_bytes();\n let amount_bytes: [u8; 32] = (amount as Field).to_be_bytes();\n\n // The purpose of including the following selector is to make the message unique to that specific call. Note that\n // it has nothing to do with calling the function.\n let selector = comptime { keccak256::keccak256(\"claim(bytes32,uint256)\".as_bytes(), 22) };\n\n for i in 0..4 {\n hash_bytes[i] = selector[i];\n }\n\n for i in 0..32 {\n hash_bytes[i + 4] = recipient_bytes[i];\n hash_bytes[i + 36] = amount_bytes[i];\n }\n\n let content_hash = sha256_to_field(hash_bytes);\n content_hash\n}\n"
|
|
2482
|
+
},
|
|
2483
|
+
"53": {
|
|
2104
2484
|
"function_locations": [
|
|
2105
2485
|
{
|
|
2106
2486
|
"name": "FeeJuice::claim_helper",
|
|
@@ -2138,7 +2518,7 @@
|
|
|
2138
2518
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-contracts/contracts/protocol/fee_juice_contract/src/main.nr",
|
|
2139
2519
|
"source": "/// Protocol contract that manages the native gas token (\"Fee Juice\") used to pay transaction fees.\n///\n/// Fee Juice is minted on L2 by bridging from L1: a user deposits ERC-20 tokens into the L1 FeeJuicePortal, which\n/// sends an L1-to-L2 message. On L2, `claim` or `claim_and_end_setup` consumes that message and credits the\n/// recipient's balance via an enqueued public call to `_increase_public_balance`.\n///\n/// The protocol's base rollup circuits read directly from this contract's `balances` storage map (at slot 1) to verify\n/// fee payers can cover their transaction costs. This storage layout is protocol-critical and must not change without\n/// updating the base rollup circuits.\n///\n/// There is no withdrawal mechanism -- Fee Juice can only be bridged in, not withdrawn or transferred by users. Tokens\n/// leave the L1 portal only via `distributeFees` called by the Rollup contract to pay sequencers.\n\nmod lib;\n\npub contract FeeJuice {\n use crate::lib::get_bridge_gas_msg_hash;\n use aztec::{\n protocol::{\n abis::function_selector::FunctionSelector,\n address::{AztecAddress, EthAddress},\n constants::FEE_JUICE_ADDRESS,\n traits::{Deserialize, ToField},\n },\n state_vars::{Map, PublicMutable},\n };\n use std::ops::Add;\n\n struct Storage<Context> {\n // contract address --> public fee juice balance\n balances: Map<AztecAddress, PublicMutable<u128, Context>, Context>,\n }\n\n global INCREASE_PUBLIC_BALANCE_SELECTOR: Field =\n comptime { FunctionSelector::from_signature(\"_increase_public_balance((Field),u128)\").to_field() };\n\n global CHECK_BALANCE_SELECTOR: Field =\n comptime { FunctionSelector::from_signature(\"check_balance(u128)\").to_field() };\n\n global BALANCE_OF_PUBLIC_SELECTOR: Field =\n comptime { FunctionSelector::from_signature(\"balance_of_public((Field))\").to_field() };\n\n /// A helper implementing the core L1-to-L2 message claim logic shared by `claim` and `claim_and_end_setup`.\n /// Computes the expected content hash, consumes the L1-to-L2 message (emitting a nullifier to prevent\n /// double-claiming), and enqueues a public call to `_increase_public_balance` to credit the recipient.\n #[contract_library_method]\n fn claim_helper(\n context: &mut aztec::context::PrivateContext,\n to: AztecAddress,\n amount: u128,\n secret: Field,\n message_leaf_index: Field,\n ) {\n let content_hash: Field = get_bridge_gas_msg_hash(to, amount);\n // The Inbox changes the sender's address to `FEE_JUICE_ADDRESS` if it's from the FeeJuicePortal.\n // This avoids the need to store the L1 address on L2 and prevents friction if the address changes.\n let portal_address: EthAddress = EthAddress::from_field(FEE_JUICE_ADDRESS.to_field());\n assert(!portal_address.is_zero());\n\n // Consume the L1-to-L2 message (verifies existence + emits nullifier to prevent replay).\n context.consume_l1_to_l2_message(content_hash, secret, portal_address, message_leaf_index);\n\n // Enqueue a public call to _increase_public_balance to credit the recipient.\n let serialized_params: [Field; 2] = [to.to_field(), amount.to_field()];\n let calldata: [Field; 1 + 2] = [INCREASE_PUBLIC_BALANCE_SELECTOR].concat(serialized_params);\n let calldata_hash: Field = aztec::hash::hash_calldata_array(calldata);\n aztec::oracle::execution_cache::store(calldata, calldata_hash);\n context.call_public_function_with_calldata_hash(context.this_address(), calldata_hash, false, false);\n }\n\n /// Claims Fee Juice by consuming an L1-to-L2 message from the FeeJuicePortal.\n ///\n /// Use this variant when the claimed Fee Juice is NOT intended to pay for the current transaction's fees (e.g.,\n /// pre-funding an account for future transactions).\n #[aztec::macros::internals_functions_generation::abi_attributes::abi_private]\n fn claim(\n inputs: aztec::context::inputs::PrivateContextInputs,\n to: AztecAddress,\n amount: u128,\n secret: Field,\n message_leaf_index: Field,\n ) -> return_data aztec::protocol::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs {\n // MACRO CODE START\n // Note: The macros initially inserted a phase check here, but since there is no phase change in this function\n // nor in the claim helper function or the enqueued public function call, I have removed that check.\n aztec::oracle::version::assert_compatible_oracle_version();\n let serialized_params: [Field; 4] = [to.to_field(), amount.to_field(), secret, message_leaf_index];\n let args_hash: Field = aztec::hash::hash_args(serialized_params);\n let mut context: aztec::context::PrivateContext = aztec::context::PrivateContext::new(inputs, args_hash);\n // MACRO CODE END\n\n claim_helper(&mut context, to, amount, secret, message_leaf_index);\n\n // MACRO CODE START\n context.finish()\n // MACRO CODE END\n }\n\n /// Claims Fee Juice and ends the transaction setup phase.\n ///\n /// Use this variant when the claimed Fee Juice is intended to pay for THIS transaction's fees. By ending setup\n /// after the claim, the balance increase is placed in the non-revertible phase, ensuring the fee payer's balance\n /// is credited even if the revertible portion of the transaction fails. This guarantees the sequencer can collect\n /// fees.\n #[aztec::macros::internals_functions_generation::abi_attributes::abi_private]\n fn claim_and_end_setup(\n inputs: aztec::context::inputs::PrivateContextInputs,\n to: AztecAddress,\n amount: u128,\n secret: Field,\n message_leaf_index: Field,\n ) -> return_data aztec::protocol::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs {\n // MACRO CODE START\n aztec::oracle::version::assert_compatible_oracle_version();\n let serialized_params: [Field; 4] = [to.to_field(), amount.to_field(), secret, message_leaf_index];\n let args_hash: Field = aztec::hash::hash_args(serialized_params);\n let mut context: aztec::context::PrivateContext = aztec::context::PrivateContext::new(inputs, args_hash);\n // MACRO CODE END\n\n claim_helper(&mut context, to, amount, secret, message_leaf_index);\n\n // MACRO CODE START\n // End setup: everything before this point (including the enqueued _increase_public_balance\n // call) is non-revertible. Everything after is revertible.\n context.end_setup();\n context.finish()\n // MACRO CODE END\n }\n\n /// Internal function that credits a recipient's Fee Juice balance. Only callable by this contract itself\n /// (`#[only_self]`), enqueued by `claim` / `claim_and_end_setup` after consuming an L1-to-L2 message.\n #[aztec::macros::internals_functions_generation::abi_attributes::abi_public]\n #[aztec::macros::internals_functions_generation::abi_attributes::abi_only_self]\n unconstrained fn _increase_public_balance(to: AztecAddress, amount: u128) {\n // MACRO CODE START\n let context: aztec::context::PublicContext = aztec::context::PublicContext::new(\n || -> Field {\n let serialized_args: [Field; 2] = aztec::oracle::avm::calldata_copy(\n 1,\n <AztecAddress as aztec::protocol::traits::Serialize>::N\n + <u128 as aztec::protocol::traits::Serialize>::N,\n );\n aztec::hash::hash_args(serialized_args)\n },\n );\n let storage: Storage<aztec::context::PublicContext> = Storage::<aztec::context::PublicContext>::init(context);\n\n assert(\n context.maybe_msg_sender().unwrap() == context.this_address(),\n \"Function _increase_public_balance can only be called by the same contract\",\n );\n // MACRO CODE END\n\n let new_balance = storage.balances.at(to).read().add(amount);\n storage.balances.at(to).write(new_balance);\n }\n\n /// Asserts the caller has at least `fee_limit` Fee Juice. Used during transaction validation to verify the fee\n /// payer can cover the transaction's fee limit.\n #[aztec::macros::internals_functions_generation::abi_attributes::abi_public]\n #[aztec::macros::internals_functions_generation::abi_attributes::abi_view]\n unconstrained fn check_balance(fee_limit: u128) {\n // MACRO CODE START\n let context: aztec::context::PublicContext = aztec::context::PublicContext::new(\n || -> Field {\n let serialized_args: [Field; 1] =\n aztec::oracle::avm::calldata_copy(1, <u128 as aztec::protocol::traits::Serialize>::N);\n aztec::hash::hash_args(serialized_args)\n },\n );\n let storage: Storage<aztec::context::PublicContext> = Storage::<aztec::context::PublicContext>::init(context);\n\n assert(context.is_static_call(), \"Function check_balance can only be called statically\");\n // MACRO CODE END\n\n assert(storage.balances.at(context.maybe_msg_sender().unwrap()).read() >= fee_limit, \"Balance too low\");\n }\n\n /// Returns the Fee Juice balance of the given address.\n #[aztec::macros::internals_functions_generation::abi_attributes::abi_public]\n #[aztec::macros::internals_functions_generation::abi_attributes::abi_view]\n unconstrained fn balance_of_public(owner: AztecAddress) -> pub u128 {\n // MACRO CODE START\n let context: aztec::context::PublicContext = aztec::context::PublicContext::new(\n || -> Field {\n let serialized_args: [Field; 1] =\n aztec::oracle::avm::calldata_copy(1, <AztecAddress as aztec::protocol::traits::Serialize>::N);\n aztec::hash::hash_args(serialized_args)\n },\n );\n let storage: Storage<aztec::context::PublicContext> = Storage::<aztec::context::PublicContext>::init(context);\n\n assert(context.is_static_call(), \"Function balance_of_public can only be called statically\");\n // MACRO CODE END\n\n storage.balances.at(owner).read()\n }\n\n // THE REST OF THE CODE IN THIS CONTRACT WAS ORIGINALLY INJECTED BY THE #[aztec] MACRO.\n\n #[aztec::macros::internals_functions_generation::abi_attributes::abi_public]\n pub unconstrained fn public_dispatch(selector: Field) {\n if selector == INCREASE_PUBLIC_BALANCE_SELECTOR {\n let input_calldata: [Field; 2] = aztec::oracle::avm::calldata_copy(\n 1,\n <AztecAddress as aztec::protocol::traits::Serialize>::N\n + <u128 as aztec::protocol::traits::Serialize>::N,\n );\n let mut reader: aztec::protocol::utils::reader::Reader<2> =\n aztec::protocol::utils::reader::Reader::<2>::new(input_calldata);\n let arg0: AztecAddress = <AztecAddress as Deserialize>::stream_deserialize(&mut reader);\n let arg1: u128 = <u128 as Deserialize>::stream_deserialize(&mut reader);\n _increase_public_balance(arg0, arg1);\n aztec::oracle::avm::avm_return([].as_vector());\n };\n if selector == CHECK_BALANCE_SELECTOR {\n let input_calldata: [Field; 1] =\n aztec::oracle::avm::calldata_copy(1, <u128 as aztec::protocol::traits::Serialize>::N);\n let mut reader: aztec::protocol::utils::reader::Reader<1> =\n aztec::protocol::utils::reader::Reader::<1>::new(input_calldata);\n let arg0: u128 = <u128 as Deserialize>::stream_deserialize(&mut reader);\n check_balance(arg0);\n aztec::oracle::avm::avm_return([].as_vector());\n };\n if selector == BALANCE_OF_PUBLIC_SELECTOR {\n let input_calldata: [Field; 1] =\n aztec::oracle::avm::calldata_copy(1, <AztecAddress as aztec::protocol::traits::Serialize>::N);\n let mut reader: aztec::protocol::utils::reader::Reader<1> =\n aztec::protocol::utils::reader::Reader::<1>::new(input_calldata);\n let arg0: AztecAddress = <AztecAddress as Deserialize>::stream_deserialize(&mut reader);\n let return_value: [Field; 1] =\n <u128 as aztec::protocol::traits::Serialize>::serialize(balance_of_public(arg0));\n aztec::oracle::avm::avm_return(return_value.as_vector());\n };\n panic(f\"Unknown selector {selector}\")\n }\n\n pub struct StorageLayoutFields {\n pub balances: aztec::state_vars::Storable,\n }\n\n pub struct StorageLayout<let N: u32> {\n pub contract_name: str<N>,\n pub fields: StorageLayoutFields,\n }\n\n #[abi(storage)]\n pub global STORAGE_LAYOUT_FeeJuice: StorageLayout<8> = StorageLayout::<8> {\n contract_name: \"FeeJuice\",\n fields: StorageLayoutFields { balances: aztec::state_vars::Storable { slot: 1 } },\n };\n\n impl<Context> Storage<Context> {\n fn init(context: Context) -> Self {\n Self {\n balances: <Map<AztecAddress, PublicMutable<u128, Context>, Context> as aztec::state_vars::StateVariable<1, Context>>::new(\n context,\n 1,\n ),\n }\n }\n }\n\n pub struct _increase_public_balance_parameters {\n pub _to: AztecAddress,\n pub _amount: u128,\n }\n\n pub struct balance_of_public_parameters {\n pub _owner: AztecAddress,\n }\n\n pub struct check_balance_parameters {\n pub _fee_limit: u128,\n }\n\n pub struct claim_and_end_setup_parameters {\n pub _to: AztecAddress,\n pub _amount: u128,\n pub _secret: Field,\n pub _message_leaf_index: Field,\n }\n\n pub struct claim_parameters {\n pub _to: AztecAddress,\n pub _amount: u128,\n pub _secret: Field,\n pub _message_leaf_index: Field,\n }\n\n #[abi(functions)]\n pub struct _increase_public_balance_abi {\n parameters: _increase_public_balance_parameters,\n }\n\n #[abi(functions)]\n pub struct balance_of_public_abi {\n parameters: balance_of_public_parameters,\n return_type: u128,\n }\n\n #[abi(functions)]\n pub struct check_balance_abi {\n parameters: check_balance_parameters,\n }\n\n #[abi(functions)]\n pub struct claim_abi {\n parameters: claim_parameters,\n }\n\n #[abi(functions)]\n pub struct claim_and_end_setup_abi {\n parameters: claim_and_end_setup_parameters,\n }\n}\n"
|
|
2140
2520
|
},
|
|
2141
|
-
"
|
|
2521
|
+
"58": {
|
|
2142
2522
|
"function_locations": [
|
|
2143
2523
|
{
|
|
2144
2524
|
"name": "PrivateContext::new",
|
|
@@ -2186,61 +2566,61 @@
|
|
|
2186
2566
|
},
|
|
2187
2567
|
{
|
|
2188
2568
|
"name": "PrivateContext::end_setup",
|
|
2189
|
-
"start":
|
|
2569
|
+
"start": 8235
|
|
2190
2570
|
},
|
|
2191
2571
|
{
|
|
2192
2572
|
"name": "PrivateContext::in_revertible_phase",
|
|
2193
|
-
"start":
|
|
2573
|
+
"start": 8484
|
|
2194
2574
|
},
|
|
2195
2575
|
{
|
|
2196
2576
|
"name": "PrivateContext::set_expiration_timestamp",
|
|
2197
|
-
"start":
|
|
2577
|
+
"start": 9369
|
|
2198
2578
|
},
|
|
2199
2579
|
{
|
|
2200
2580
|
"name": "PrivateContext::push_nullifier",
|
|
2201
|
-
"start":
|
|
2581
|
+
"start": 9611
|
|
2202
2582
|
},
|
|
2203
2583
|
{
|
|
2204
2584
|
"name": "PrivateContext::assert_nullifier_exists",
|
|
2205
|
-
"start":
|
|
2585
|
+
"start": 9971
|
|
2206
2586
|
},
|
|
2207
2587
|
{
|
|
2208
2588
|
"name": "PrivateContext::consume_l1_to_l2_message",
|
|
2209
|
-
"start":
|
|
2589
|
+
"start": 10611
|
|
2210
2590
|
},
|
|
2211
2591
|
{
|
|
2212
2592
|
"name": "PrivateContext::emit_private_log",
|
|
2213
|
-
"start":
|
|
2593
|
+
"start": 11203
|
|
2214
2594
|
},
|
|
2215
2595
|
{
|
|
2216
2596
|
"name": "PrivateContext::emit_contract_class_log",
|
|
2217
|
-
"start":
|
|
2597
|
+
"start": 11565
|
|
2218
2598
|
},
|
|
2219
2599
|
{
|
|
2220
2600
|
"name": "PrivateContext::static_call_private_function",
|
|
2221
|
-
"start":
|
|
2601
|
+
"start": 13063
|
|
2222
2602
|
},
|
|
2223
2603
|
{
|
|
2224
2604
|
"name": "PrivateContext::call_private_function_with_args_hash",
|
|
2225
|
-
"start":
|
|
2605
|
+
"start": 13551
|
|
2226
2606
|
},
|
|
2227
2607
|
{
|
|
2228
2608
|
"name": "PrivateContext::call_public_function_with_calldata_hash",
|
|
2229
|
-
"start":
|
|
2609
|
+
"start": 15055
|
|
2230
2610
|
},
|
|
2231
2611
|
{
|
|
2232
2612
|
"name": "PrivateContext::next_counter",
|
|
2233
|
-
"start":
|
|
2613
|
+
"start": 15636
|
|
2234
2614
|
},
|
|
2235
2615
|
{
|
|
2236
2616
|
"name": "<impl Empty for PrivateContext>::empty",
|
|
2237
|
-
"start":
|
|
2617
|
+
"start": 15805
|
|
2238
2618
|
}
|
|
2239
2619
|
],
|
|
2240
2620
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-contracts/contracts/protocol/aztec_sublib/src/context/private_context.nr",
|
|
2241
|
-
"source": "use crate::{\n context::{inputs::PrivateContextInputs, NullifierExistenceRequest, ReturnsHash},\n hash::hash_args,\n messaging::process_l1_to_l2_message,\n oracle::{\n call_private_function::call_private_function_internal,\n public_call::validate_public_calldata,\n tx_phase::{in_revertible_phase, notify_revertible_phase_start},\n execution_cache,\n logs::notify_created_contract_class_log,\n nullifiers::notify_created_nullifier,\n },\n};\nuse crate::protocol::{\n abis::{\n block_header::BlockHeader,\n call_context::CallContext,\n function_selector::FunctionSelector,\n gas_settings::GasSettings,\n log_hash::LogHash,\n nullifier::Nullifier,\n private_call_request::PrivateCallRequest,\n private_circuit_public_inputs::PrivateCircuitPublicInputs,\n private_log::{PrivateLog, PrivateLogData},\n public_call_request::PublicCallRequest,\n },\n address::{AztecAddress, EthAddress},\n constants::{\n CONTRACT_CLASS_LOG_SIZE_IN_FIELDS, MAX_CONTRACT_CLASS_LOGS_PER_CALL,\n MAX_ENQUEUED_CALLS_PER_CALL, MAX_TX_LIFETIME, MAX_L2_TO_L1_MSGS_PER_CALL,\n MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PRIVATE_LOGS_PER_CALL,\n NULL_MSG_SENDER_CONTRACT_ADDRESS, PRIVATE_LOG_SIZE_IN_FIELDS,\n },\n hash::poseidon2_hash,\n messaging::l2_to_l1_message::L2ToL1Message,\n side_effect::{Counted, scoped::Scoped},\n traits::Empty,\n utils::arrays::{ClaimedLengthArray, trimmed_array_length_hint},\n};\n\n/// Minimal PrivateContext for protocol contracts going to audit.\n/// Contains only the methods actually used by: fee_juice, auth_registry, contract_class_registry, contract_instance_registry\n#[derive(Eq)]\npub struct PrivateContext {\n pub inputs: PrivateContextInputs,\n pub side_effect_counter: u32,\n\n pub min_revertible_side_effect_counter: u32,\n pub is_fee_payer: bool,\n\n pub args_hash: Field,\n pub return_hash: Field,\n\n pub expiration_timestamp: u64,\n\n pub nullifier_read_requests: BoundedVec<Scoped<Counted<Field>>, MAX_NULLIFIER_READ_REQUESTS_PER_CALL>,\n\n pub nullifiers: BoundedVec<Counted<Nullifier>, MAX_NULLIFIERS_PER_CALL>,\n\n pub private_call_requests: BoundedVec<PrivateCallRequest, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL>,\n pub public_call_requests: BoundedVec<Counted<PublicCallRequest>, MAX_ENQUEUED_CALLS_PER_CALL>,\n pub public_teardown_call_request: PublicCallRequest,\n pub l2_to_l1_msgs: BoundedVec<Counted<L2ToL1Message>, MAX_L2_TO_L1_MSGS_PER_CALL>,\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n pub anchor_block_header: BlockHeader,\n\n pub private_logs: BoundedVec<Counted<PrivateLogData>, MAX_PRIVATE_LOGS_PER_CALL>,\n pub contract_class_logs_hashes: BoundedVec<Counted<LogHash>, MAX_CONTRACT_CLASS_LOGS_PER_CALL>,\n\n pub expected_non_revertible_side_effect_counter: u32,\n pub expected_revertible_side_effect_counter: u32,\n}\n\nimpl PrivateContext {\n pub fn new(inputs: PrivateContextInputs, args_hash: Field) -> PrivateContext {\n PrivateContext {\n inputs,\n side_effect_counter: inputs.start_side_effect_counter + 1,\n min_revertible_side_effect_counter: 0,\n is_fee_payer: false,\n args_hash,\n return_hash: 0,\n expiration_timestamp: inputs.anchor_block_header.global_variables.timestamp\n + MAX_TX_LIFETIME,\n nullifier_read_requests: BoundedVec::new(),\n nullifiers: BoundedVec::new(),\n anchor_block_header: inputs.anchor_block_header,\n private_call_requests: BoundedVec::new(),\n public_call_requests: BoundedVec::new(),\n public_teardown_call_request: PublicCallRequest::empty(),\n l2_to_l1_msgs: BoundedVec::new(),\n private_logs: BoundedVec::new(),\n contract_class_logs_hashes: BoundedVec::new(),\n expected_non_revertible_side_effect_counter: 0,\n expected_revertible_side_effect_counter: 0,\n }\n }\n\n /// Returns the contract address that initiated this function call (similar to msg.sender in Solidity).\n pub fn maybe_msg_sender(self) -> Option<AztecAddress> {\n let maybe_msg_sender = self.inputs.call_context.msg_sender;\n if maybe_msg_sender == NULL_MSG_SENDER_CONTRACT_ADDRESS {\n Option::none()\n } else {\n Option::some(maybe_msg_sender)\n }\n }\n\n /// Returns the contract address of the current function being executed.\n pub fn this_address(self) -> AztecAddress {\n self.inputs.call_context.contract_address\n }\n\n /// Returns the chain ID of the current network.\n pub fn chain_id(self) -> Field {\n self.inputs.tx_context.chain_id\n }\n\n /// Returns the protocol version.\n pub fn version(self) -> Field {\n self.inputs.tx_context.version\n }\n\n /// Returns the gas settings for the current transaction.\n pub fn gas_settings(self) -> GasSettings {\n self.inputs.tx_context.gas_settings\n }\n\n /// Returns the function selector of the currently executing function.\n pub fn selector(self) -> FunctionSelector {\n self.inputs.call_context.function_selector\n }\n\n /// Returns the hash of the arguments passed to the current function.\n pub fn get_args_hash(self) -> Field {\n self.args_hash\n }\n\n /// Returns the anchor block header.\n pub fn get_anchor_block_header(self) -> BlockHeader {\n self.anchor_block_header\n }\n\n /// Sets the hash of the return values for this private function.\n pub fn set_return_hash<let N: u32>(&mut self, serialized_return_values: [Field; N]) {\n let return_hash = hash_args(serialized_return_values);\n self.return_hash = return_hash;\n execution_cache::store(serialized_return_values, return_hash);\n }\n\n /// Builds the PrivateCircuitPublicInputs for this private function.\n pub fn finish(self) -> PrivateCircuitPublicInputs {\n PrivateCircuitPublicInputs {\n call_context: self.inputs.call_context,\n args_hash: self.args_hash,\n returns_hash: self.return_hash,\n min_revertible_side_effect_counter: self.min_revertible_side_effect_counter,\n is_fee_payer: self.is_fee_payer,\n expiration_timestamp: self.expiration_timestamp,\n note_hash_read_requests: ClaimedLengthArray::empty(), // Not used by protocol contracts\n nullifier_read_requests: ClaimedLengthArray::from_bounded_vec(\n self.nullifier_read_requests,\n ),\n key_validation_requests_and_separators: ClaimedLengthArray::empty(), // Not used by protocol contracts\n note_hashes: ClaimedLengthArray::empty(), // Not used by protocol contracts\n nullifiers: ClaimedLengthArray::from_bounded_vec(self.nullifiers),\n private_call_requests: ClaimedLengthArray::from_bounded_vec(self.private_call_requests),\n public_call_requests: ClaimedLengthArray::from_bounded_vec(self.public_call_requests),\n public_teardown_call_request: self.public_teardown_call_request,\n l2_to_l1_msgs: ClaimedLengthArray::from_bounded_vec(self.l2_to_l1_msgs),\n start_side_effect_counter: self.inputs.start_side_effect_counter,\n end_side_effect_counter: self.side_effect_counter,\n private_logs: ClaimedLengthArray::from_bounded_vec(self.private_logs),\n contract_class_logs_hashes: ClaimedLengthArray::from_bounded_vec(\n self.contract_class_logs_hashes,\n ),\n anchor_block_header: self.anchor_block_header,\n tx_context: self.inputs.tx_context,\n expected_non_revertible_side_effect_counter: self\n .expected_non_revertible_side_effect_counter,\n expected_revertible_side_effect_counter: self.expected_revertible_side_effect_counter,\n }\n }\n\n /// Declares the end of the \"setup phase\" of this tx. Used by fee_juice.\n pub fn end_setup(&mut self) {\n self.side_effect_counter += 1;\n self.min_revertible_side_effect_counter = self.next_counter();\n notify_revertible_phase_start(self.min_revertible_side_effect_counter);\n }\n\n pub fn in_revertible_phase(&mut self) -> bool {\n let current_counter = self.side_effect_counter;\n\n // Safety: Kernel will validate that the claim is correct by validating the expected counters.\n let is_revertible =\n unsafe { in_revertible_phase(current_counter) };\n\n if is_revertible {\n if (self.expected_revertible_side_effect_counter == 0)\n | (current_counter < self.expected_revertible_side_effect_counter) {\n self.expected_revertible_side_effect_counter = current_counter;\n }\n } else if current_counter > self.expected_non_revertible_side_effect_counter {\n self.expected_non_revertible_side_effect_counter = current_counter;\n }\n\n is_revertible\n }\n\n /// Sets a deadline for when this transaction must be included in a block.\n pub fn set_expiration_timestamp(&mut self, expiration_timestamp: u64) {\n self.expiration_timestamp = std::cmp::min(self.expiration_timestamp, expiration_timestamp);\n }\n\n /// Pushes a new nullifier. Used by class_registry and instance_registry.\n pub fn push_nullifier(&mut self, nullifier: Field) {\n notify_created_nullifier(nullifier);\n self.nullifiers.push(Nullifier { value: nullifier, note_hash: 0 }.count(self.next_counter()));\n }\n\n /// Asserts that a nullifier has been emitted. Used by instance_registry.\n pub fn assert_nullifier_exists(\n &mut self,\n nullifier_existence_request: NullifierExistenceRequest,\n ) {\n let nullifier = nullifier_existence_request.nullifier();\n let contract_address =\n nullifier_existence_request.maybe_contract_address().unwrap_or(AztecAddress::zero());\n\n let request = Scoped::new(\n Counted::new(nullifier, self.next_counter()),\n contract_address,\n );\n\n self.nullifier_read_requests.push(request);\n }\n\n /// Consumes a message sent from Ethereum (L1) to Aztec (L2). Used by fee_juice.\n pub fn consume_l1_to_l2_message(\n &mut self,\n content: Field,\n secret: Field,\n sender: EthAddress,\n leaf_index: Field,\n ) {\n let nullifier = process_l1_to_l2_message(\n self.anchor_block_header.state.l1_to_l2_message_tree.root,\n self.this_address(),\n sender,\n self.chain_id(),\n self.version(),\n content,\n secret,\n leaf_index,\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_nullifier(nullifier)\n }\n\n /// Emits a private log. Used by instance_registry.\n pub fn emit_private_log(&mut self, log: [Field; PRIVATE_LOG_SIZE_IN_FIELDS], length: u32) {\n let counter = self.next_counter();\n let private_log = PrivateLogData { log: PrivateLog::new(log, length), note_hash_counter: 0 }\n .count(counter);\n self.private_logs.push(private_log);\n }\n\n /// Emits a contract class log. Used by class_registry.\n pub fn emit_contract_class_log<let N: u32>(&mut self, log: [Field; N]) {\n let contract_address = self.this_address();\n let counter = self.next_counter();\n\n let log_to_emit: [Field; CONTRACT_CLASS_LOG_SIZE_IN_FIELDS] =\n log.concat([0; CONTRACT_CLASS_LOG_SIZE_IN_FIELDS - N]);\n // Safety: The below length is constrained in the base rollup, which will make sure that all the fields beyond\n // length are zero. However, it won't be able to check that we didn't add extra padding (trailing zeroes) or\n // that we cut trailing zeroes from the end.\n let length = unsafe { trimmed_array_length_hint(log_to_emit) };\n // We hash the entire padded log to ensure a user cannot pass a shorter length and so emit incorrect shorter\n // bytecode.\n let log_hash = poseidon2_hash(log_to_emit);\n // Safety: the below only exists to broadcast the raw log, so we can provide it to the base rollup later to be\n // constrained.\n unsafe {\n notify_created_contract_class_log(contract_address, log_to_emit, length, counter);\n }\n\n self.contract_class_logs_hashes.push(LogHash { value: log_hash, length: length }.count(\n counter,\n ));\n }\n\n /// Makes a read-only call to a private function. Used by auth_registry for authwit.\n pub fn static_call_private_function<let ArgsCount: u32>(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ArgsCount],\n ) -> ReturnsHash {\n let args_hash = hash_args(args);\n execution_cache::store(args, args_hash);\n self.call_private_function_with_args_hash(\n contract_address,\n function_selector,\n args_hash,\n true,\n )\n }\n\n fn call_private_function_with_args_hash(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n ) -> ReturnsHash {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let start_side_effect_counter = self.side_effect_counter;\n\n // Safety: The oracle simulates the private call and returns the value of the side effects counter after\n // execution of the call.\n let (end_side_effect_counter, returns_hash) = unsafe {\n call_private_function_internal(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n )\n };\n\n self.private_call_requests.push(\n PrivateCallRequest {\n call_context: CallContext {\n msg_sender: self.this_address(),\n contract_address,\n function_selector,\n is_static_call,\n },\n args_hash,\n returns_hash,\n start_side_effect_counter,\n end_side_effect_counter,\n },\n );\n\n self.side_effect_counter = end_side_effect_counter + 1;\n ReturnsHash::new(returns_hash)\n }\n\n /// Enqueues a call to a public function with a calldata hash. Used by fee_juice and auth_registry.\n pub fn call_public_function_with_calldata_hash(\n &mut self,\n contract_address: AztecAddress,\n calldata_hash: Field,\n is_static_call: bool,\n hide_msg_sender: bool,\n ) {\n let counter = self.next_counter();\n\n let is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n\n validate_public_calldata(calldata_hash);\n\n let msg_sender = if hide_msg_sender {\n NULL_MSG_SENDER_CONTRACT_ADDRESS\n } else {\n self.this_address()\n };\n\n let call_request =\n PublicCallRequest { msg_sender, contract_address, is_static_call, calldata_hash };\n\n self.public_call_requests.push(Counted::new(call_request, counter));\n }\n\n fn next_counter(&mut self) -> u32 {\n let counter = self.side_effect_counter;\n self.side_effect_counter += 1;\n counter\n }\n}\n\nimpl Empty for PrivateContext {\n fn empty() -> Self {\n PrivateContext {\n inputs: PrivateContextInputs::empty(),\n side_effect_counter: 0 as u32,\n min_revertible_side_effect_counter: 0 as u32,\n is_fee_payer: false,\n args_hash: 0,\n return_hash: 0,\n expiration_timestamp: 0,\n nullifier_read_requests: BoundedVec::new(),\n nullifiers: BoundedVec::new(),\n private_call_requests: BoundedVec::new(),\n public_call_requests: BoundedVec::new(),\n public_teardown_call_request: PublicCallRequest::empty(),\n l2_to_l1_msgs: BoundedVec::new(),\n anchor_block_header: BlockHeader::empty(),\n private_logs: BoundedVec::new(),\n contract_class_logs_hashes: BoundedVec::new(),\n expected_non_revertible_side_effect_counter: 0,\n expected_revertible_side_effect_counter: 0,\n }\n }\n}\n"
|
|
2621
|
+
"source": "use crate::{\n context::{inputs::PrivateContextInputs, NullifierExistenceRequest, ReturnsHash},\n hash::hash_args,\n messaging::process_l1_to_l2_message,\n oracle::{\n call_private_function::call_private_function_internal,\n public_call::validate_public_calldata,\n tx_phase::{in_revertible_phase, notify_revertible_phase_start},\n execution_cache,\n logs::notify_created_contract_class_log,\n nullifiers::notify_created_nullifier,\n },\n};\nuse crate::protocol::{\n abis::{\n block_header::BlockHeader,\n call_context::CallContext,\n function_selector::FunctionSelector,\n gas_settings::GasSettings,\n log_hash::LogHash,\n nullifier::Nullifier,\n private_call_request::PrivateCallRequest,\n private_circuit_public_inputs::PrivateCircuitPublicInputs,\n private_log::{PrivateLog, PrivateLogData},\n public_call_request::PublicCallRequest,\n },\n address::{AztecAddress, EthAddress},\n constants::{\n CONTRACT_CLASS_LOG_SIZE_IN_FIELDS, MAX_CONTRACT_CLASS_LOGS_PER_CALL,\n MAX_ENQUEUED_CALLS_PER_CALL, MAX_TX_LIFETIME, MAX_L2_TO_L1_MSGS_PER_CALL,\n MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PRIVATE_LOGS_PER_CALL,\n NULL_MSG_SENDER_CONTRACT_ADDRESS, PRIVATE_LOG_SIZE_IN_FIELDS,\n },\n hash::poseidon2_hash,\n messaging::l2_to_l1_message::L2ToL1Message,\n side_effect::{Counted, scoped::Scoped},\n traits::Empty,\n utils::arrays::{ClaimedLengthArray, trimmed_array_length_hint},\n};\n\n/// Minimal PrivateContext for protocol contracts going to audit.\n/// Contains only the methods actually used by: fee_juice, auth_registry, contract_class_registry, contract_instance_registry\n#[derive(Eq)]\npub struct PrivateContext {\n pub inputs: PrivateContextInputs,\n pub side_effect_counter: u32,\n\n pub min_revertible_side_effect_counter: u32,\n pub is_fee_payer: bool,\n\n pub args_hash: Field,\n pub return_hash: Field,\n\n pub expiration_timestamp: u64,\n\n pub nullifier_read_requests: BoundedVec<Scoped<Counted<Field>>, MAX_NULLIFIER_READ_REQUESTS_PER_CALL>,\n\n pub nullifiers: BoundedVec<Counted<Nullifier>, MAX_NULLIFIERS_PER_CALL>,\n\n pub private_call_requests: BoundedVec<PrivateCallRequest, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL>,\n pub public_call_requests: BoundedVec<Counted<PublicCallRequest>, MAX_ENQUEUED_CALLS_PER_CALL>,\n pub public_teardown_call_request: PublicCallRequest,\n pub l2_to_l1_msgs: BoundedVec<Counted<L2ToL1Message>, MAX_L2_TO_L1_MSGS_PER_CALL>,\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n pub anchor_block_header: BlockHeader,\n\n pub private_logs: BoundedVec<Counted<PrivateLogData>, MAX_PRIVATE_LOGS_PER_CALL>,\n pub contract_class_logs_hashes: BoundedVec<Counted<LogHash>, MAX_CONTRACT_CLASS_LOGS_PER_CALL>,\n\n pub expected_non_revertible_side_effect_counter: u32,\n pub expected_revertible_side_effect_counter: u32,\n}\n\nimpl PrivateContext {\n pub fn new(inputs: PrivateContextInputs, args_hash: Field) -> PrivateContext {\n PrivateContext {\n inputs,\n side_effect_counter: inputs.start_side_effect_counter + 1,\n min_revertible_side_effect_counter: 0,\n is_fee_payer: false,\n args_hash,\n return_hash: 0,\n expiration_timestamp: inputs.anchor_block_header.global_variables.timestamp\n + MAX_TX_LIFETIME,\n nullifier_read_requests: BoundedVec::new(),\n nullifiers: BoundedVec::new(),\n anchor_block_header: inputs.anchor_block_header,\n private_call_requests: BoundedVec::new(),\n public_call_requests: BoundedVec::new(),\n public_teardown_call_request: PublicCallRequest::empty(),\n l2_to_l1_msgs: BoundedVec::new(),\n private_logs: BoundedVec::new(),\n contract_class_logs_hashes: BoundedVec::new(),\n expected_non_revertible_side_effect_counter: 0,\n expected_revertible_side_effect_counter: 0,\n }\n }\n\n /// Returns the contract address that initiated this function call (similar to msg.sender in Solidity).\n pub fn maybe_msg_sender(self) -> Option<AztecAddress> {\n let maybe_msg_sender = self.inputs.call_context.msg_sender;\n if maybe_msg_sender == NULL_MSG_SENDER_CONTRACT_ADDRESS {\n Option::none()\n } else {\n Option::some(maybe_msg_sender)\n }\n }\n\n /// Returns the contract address of the current function being executed.\n pub fn this_address(self) -> AztecAddress {\n self.inputs.call_context.contract_address\n }\n\n /// Returns the chain ID of the current network.\n pub fn chain_id(self) -> Field {\n self.inputs.tx_context.chain_id\n }\n\n /// Returns the protocol version.\n pub fn version(self) -> Field {\n self.inputs.tx_context.version\n }\n\n /// Returns the gas settings for the current transaction.\n pub fn gas_settings(self) -> GasSettings {\n self.inputs.tx_context.gas_settings\n }\n\n /// Returns the function selector of the currently executing function.\n pub fn selector(self) -> FunctionSelector {\n self.inputs.call_context.function_selector\n }\n\n /// Returns the hash of the arguments passed to the current function.\n pub fn get_args_hash(self) -> Field {\n self.args_hash\n }\n\n /// Returns the anchor block header.\n pub fn get_anchor_block_header(self) -> BlockHeader {\n self.anchor_block_header\n }\n\n /// Sets the hash of the return values for this private function.\n pub fn set_return_hash<let N: u32>(&mut self, serialized_return_values: [Field; N]) {\n let return_hash = hash_args(serialized_return_values);\n self.return_hash = return_hash;\n execution_cache::store(serialized_return_values, return_hash);\n }\n\n /// Builds the PrivateCircuitPublicInputs for this private function.\n pub fn finish(self) -> PrivateCircuitPublicInputs {\n PrivateCircuitPublicInputs {\n call_context: self.inputs.call_context,\n args_hash: self.args_hash,\n returns_hash: self.return_hash,\n min_revertible_side_effect_counter: self.min_revertible_side_effect_counter,\n is_fee_payer: self.is_fee_payer,\n expiration_timestamp: self.expiration_timestamp,\n note_hash_read_requests: ClaimedLengthArray::empty(), // Not used by protocol contracts\n nullifier_read_requests: ClaimedLengthArray::from_bounded_vec(\n self.nullifier_read_requests,\n ),\n key_validation_requests_and_separators: ClaimedLengthArray::empty(), // Not used by protocol contracts\n note_hashes: ClaimedLengthArray::empty(), // Not used by protocol contracts\n nullifiers: ClaimedLengthArray::from_bounded_vec(self.nullifiers),\n private_call_requests: ClaimedLengthArray::from_bounded_vec(self.private_call_requests),\n public_call_requests: ClaimedLengthArray::from_bounded_vec(self.public_call_requests),\n public_teardown_call_request: self.public_teardown_call_request,\n l2_to_l1_msgs: ClaimedLengthArray::from_bounded_vec(self.l2_to_l1_msgs),\n start_side_effect_counter: self.inputs.start_side_effect_counter,\n end_side_effect_counter: self.side_effect_counter,\n private_logs: ClaimedLengthArray::from_bounded_vec(self.private_logs),\n contract_class_logs_hashes: ClaimedLengthArray::from_bounded_vec(\n self.contract_class_logs_hashes,\n ),\n anchor_block_header: self.anchor_block_header,\n tx_context: self.inputs.tx_context,\n expected_non_revertible_side_effect_counter: self\n .expected_non_revertible_side_effect_counter,\n expected_revertible_side_effect_counter: self.expected_revertible_side_effect_counter,\n tx_request_salt: self.inputs.tx_request_salt,\n }\n }\n\n /// Declares the end of the \"setup phase\" of this tx. Used by fee_juice.\n pub fn end_setup(&mut self) {\n self.side_effect_counter += 1;\n self.min_revertible_side_effect_counter = self.next_counter();\n notify_revertible_phase_start(self.min_revertible_side_effect_counter);\n }\n\n pub fn in_revertible_phase(&mut self) -> bool {\n let current_counter = self.side_effect_counter;\n\n // Safety: Kernel will validate that the claim is correct by validating the expected counters.\n let is_revertible =\n unsafe { in_revertible_phase(current_counter) };\n\n if is_revertible {\n if (self.expected_revertible_side_effect_counter == 0)\n | (current_counter < self.expected_revertible_side_effect_counter) {\n self.expected_revertible_side_effect_counter = current_counter;\n }\n } else if current_counter > self.expected_non_revertible_side_effect_counter {\n self.expected_non_revertible_side_effect_counter = current_counter;\n }\n\n is_revertible\n }\n\n /// Sets a deadline for when this transaction must be included in a block.\n pub fn set_expiration_timestamp(&mut self, expiration_timestamp: u64) {\n self.expiration_timestamp = std::cmp::min(self.expiration_timestamp, expiration_timestamp);\n }\n\n /// Pushes a new nullifier. Used by class_registry and instance_registry.\n pub fn push_nullifier(&mut self, nullifier: Field) {\n notify_created_nullifier(nullifier);\n self.nullifiers.push(Nullifier { value: nullifier, note_hash: 0 }.count(self.next_counter()));\n }\n\n /// Asserts that a nullifier has been emitted. Used by instance_registry.\n pub fn assert_nullifier_exists(\n &mut self,\n nullifier_existence_request: NullifierExistenceRequest,\n ) {\n let nullifier = nullifier_existence_request.nullifier();\n let contract_address =\n nullifier_existence_request.maybe_contract_address().unwrap_or(AztecAddress::zero());\n\n let request = Scoped::new(\n Counted::new(nullifier, self.next_counter()),\n contract_address,\n );\n\n self.nullifier_read_requests.push(request);\n }\n\n /// Consumes a message sent from Ethereum (L1) to Aztec (L2). Used by fee_juice.\n pub fn consume_l1_to_l2_message(\n &mut self,\n content: Field,\n secret: Field,\n sender: EthAddress,\n leaf_index: Field,\n ) {\n let nullifier = process_l1_to_l2_message(\n self.anchor_block_header.state.l1_to_l2_message_tree.root,\n self.this_address(),\n sender,\n self.chain_id(),\n self.version(),\n content,\n secret,\n leaf_index,\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_nullifier(nullifier)\n }\n\n /// Emits a private log. Used by instance_registry.\n pub fn emit_private_log(&mut self, log: [Field; PRIVATE_LOG_SIZE_IN_FIELDS], length: u32) {\n let counter = self.next_counter();\n let private_log = PrivateLogData { log: PrivateLog::new(log, length), note_hash_counter: 0 }\n .count(counter);\n self.private_logs.push(private_log);\n }\n\n /// Emits a contract class log. Used by class_registry.\n pub fn emit_contract_class_log<let N: u32>(&mut self, log: [Field; N]) {\n let contract_address = self.this_address();\n let counter = self.next_counter();\n\n let log_to_emit: [Field; CONTRACT_CLASS_LOG_SIZE_IN_FIELDS] =\n log.concat([0; CONTRACT_CLASS_LOG_SIZE_IN_FIELDS - N]);\n // Safety: The below length is constrained in the base rollup, which will make sure that all the fields beyond\n // length are zero. However, it won't be able to check that we didn't add extra padding (trailing zeroes) or\n // that we cut trailing zeroes from the end.\n let length = unsafe { trimmed_array_length_hint(log_to_emit) };\n // We hash the entire padded log to ensure a user cannot pass a shorter length and so emit incorrect shorter\n // bytecode.\n let log_hash = poseidon2_hash(log_to_emit);\n // Safety: the below only exists to broadcast the raw log, so we can provide it to the base rollup later to be\n // constrained.\n unsafe {\n notify_created_contract_class_log(contract_address, log_to_emit, length, counter);\n }\n\n self.contract_class_logs_hashes.push(LogHash { value: log_hash, length: length }.count(\n counter,\n ));\n }\n\n /// Makes a read-only call to a private function. Used by auth_registry for authwit.\n pub fn static_call_private_function<let ArgsCount: u32>(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ArgsCount],\n ) -> ReturnsHash {\n let args_hash = hash_args(args);\n execution_cache::store(args, args_hash);\n self.call_private_function_with_args_hash(\n contract_address,\n function_selector,\n args_hash,\n true,\n )\n }\n\n fn call_private_function_with_args_hash(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n ) -> ReturnsHash {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let start_side_effect_counter = self.side_effect_counter;\n\n // Safety: The oracle simulates the private call and returns the value of the side effects counter after\n // execution of the call.\n let (end_side_effect_counter, returns_hash) = unsafe {\n call_private_function_internal(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n )\n };\n\n self.private_call_requests.push(\n PrivateCallRequest {\n call_context: CallContext {\n msg_sender: self.this_address(),\n contract_address,\n function_selector,\n is_static_call,\n },\n args_hash,\n returns_hash,\n start_side_effect_counter,\n end_side_effect_counter,\n },\n );\n\n self.side_effect_counter = end_side_effect_counter + 1;\n ReturnsHash::new(returns_hash)\n }\n\n /// Enqueues a call to a public function with a calldata hash. Used by fee_juice and auth_registry.\n pub fn call_public_function_with_calldata_hash(\n &mut self,\n contract_address: AztecAddress,\n calldata_hash: Field,\n is_static_call: bool,\n hide_msg_sender: bool,\n ) {\n let counter = self.next_counter();\n\n let is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n\n validate_public_calldata(calldata_hash);\n\n let msg_sender = if hide_msg_sender {\n NULL_MSG_SENDER_CONTRACT_ADDRESS\n } else {\n self.this_address()\n };\n\n let call_request =\n PublicCallRequest { msg_sender, contract_address, is_static_call, calldata_hash };\n\n self.public_call_requests.push(Counted::new(call_request, counter));\n }\n\n fn next_counter(&mut self) -> u32 {\n let counter = self.side_effect_counter;\n self.side_effect_counter += 1;\n counter\n }\n}\n\nimpl Empty for PrivateContext {\n fn empty() -> Self {\n PrivateContext {\n inputs: PrivateContextInputs::empty(),\n side_effect_counter: 0 as u32,\n min_revertible_side_effect_counter: 0 as u32,\n is_fee_payer: false,\n args_hash: 0,\n return_hash: 0,\n expiration_timestamp: 0,\n nullifier_read_requests: BoundedVec::new(),\n nullifiers: BoundedVec::new(),\n private_call_requests: BoundedVec::new(),\n public_call_requests: BoundedVec::new(),\n public_teardown_call_request: PublicCallRequest::empty(),\n l2_to_l1_msgs: BoundedVec::new(),\n anchor_block_header: BlockHeader::empty(),\n private_logs: BoundedVec::new(),\n contract_class_logs_hashes: BoundedVec::new(),\n expected_non_revertible_side_effect_counter: 0,\n expected_revertible_side_effect_counter: 0,\n }\n }\n}\n"
|
|
2242
2622
|
},
|
|
2243
|
-
"
|
|
2623
|
+
"59": {
|
|
2244
2624
|
"function_locations": [
|
|
2245
2625
|
{
|
|
2246
2626
|
"name": "<impl Eq for PublicContext>::eq",
|
|
@@ -2370,7 +2750,7 @@
|
|
|
2370
2750
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-contracts/contracts/protocol/aztec_sublib/src/context/public_context.nr",
|
|
2371
2751
|
"source": "use crate::{\n context::gas::GasOpts,\n hash::{\n compute_l1_to_l2_message_hash, compute_l1_to_l2_message_nullifier, compute_secret_hash,\n compute_siloed_nullifier,\n },\n oracle::avm,\n};\nuse crate::protocol::{\n abis::function_selector::FunctionSelector,\n address::{AztecAddress, EthAddress},\n constants::{MAX_U32_VALUE, NULL_MSG_SENDER_CONTRACT_ADDRESS},\n traits::{Empty, FromField, Packable, Serialize, ToField},\n};\n\n/// Minimal PublicContext for protocol contracts going to audit.\npub struct PublicContext {\n pub args_hash: Option<Field>,\n pub compute_args_hash: fn() -> Field,\n}\n\nimpl Eq for PublicContext {\n fn eq(self, other: Self) -> bool {\n (self.args_hash == other.args_hash)\n // Can't compare the function compute_args_hash\n }\n}\n\nimpl PublicContext {\n pub fn new(compute_args_hash: fn() -> Field) -> Self {\n PublicContext { args_hash: Option::none(), compute_args_hash }\n }\n\n /// Emits a _public_ log that will be visible onchain to everyone.\n pub fn emit_public_log<T>(_self: Self, log: T)\n where\n T: Serialize,\n {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { avm::emit_public_log(Serialize::serialize(log).as_vector()) };\n }\n\n /// Checks if a given note hash exists in the note hash tree at a particular leaf_index.\n pub fn note_hash_exists(_self: Self, note_hash: Field, leaf_index: u64) -> bool {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { avm::note_hash_exists(note_hash, leaf_index) }\n }\n\n /// Checks if a specific L1-to-L2 message exists in the L1-to-L2 message tree at a particular leaf index.\n pub fn l1_to_l2_msg_exists(_self: Self, msg_hash: Field, msg_leaf_index: Field) -> bool {\n // Safety: AVM opcodes are constrained by the AVM itself TODO(alvaro): Make l1l2msg leaf index a u64 upstream\n unsafe { avm::l1_to_l2_msg_exists(msg_hash, msg_leaf_index as u64) }\n }\n\n /// Returns `true` if an `unsiloed_nullifier` has been emitted by `contract_address`.\n pub fn nullifier_exists_unsafe(\n _self: Self,\n unsiloed_nullifier: Field,\n contract_address: AztecAddress,\n ) -> bool {\n let siloed_nullifier = compute_siloed_nullifier(contract_address, unsiloed_nullifier);\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { avm::nullifier_exists(siloed_nullifier) }\n }\n\n /// Consumes a message sent from Ethereum (L1) to Aztec (L2).\n pub fn consume_l1_to_l2_message(\n self: Self,\n content: Field,\n secret: Field,\n sender: EthAddress,\n leaf_index: Field,\n ) {\n let secret_hash = compute_secret_hash(secret);\n let message_hash = compute_l1_to_l2_message_hash(\n sender,\n self.chain_id(),\n /*recipient=*/\n self.this_address(),\n self.version(),\n content,\n secret_hash,\n leaf_index,\n );\n let nullifier = compute_l1_to_l2_message_nullifier(message_hash, secret);\n\n assert(\n !self.nullifier_exists_unsafe(nullifier, self.this_address()),\n \"L1-to-L2 message is already nullified\",\n );\n assert(\n self.l1_to_l2_msg_exists(message_hash, leaf_index),\n \"Tried to consume nonexistent L1-to-L2 message\",\n );\n\n self.push_nullifier(nullifier);\n }\n\n /// Sends an \"L2 -> L1 message\".\n pub fn message_portal(_self: Self, recipient: EthAddress, content: Field) {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { avm::send_l2_to_l1_msg(recipient, content) };\n }\n\n /// Calls a public function on another contract.\n pub unconstrained fn call_public_function<let N: u32>(\n _self: Self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; N],\n gas_opts: GasOpts,\n ) -> [Field] {\n let calldata = [function_selector.to_field()].concat(args);\n\n avm::call(\n gas_opts.l2_gas.unwrap_or(MAX_U32_VALUE),\n gas_opts.da_gas.unwrap_or(MAX_U32_VALUE),\n contract_address,\n calldata,\n );\n // Use success_copy to determine whether the call succeeded\n let success = avm::success_copy();\n\n let result_data = avm::returndata_copy(0, avm::returndata_size());\n if !success {\n // Rethrow the revert data.\n avm::revert(result_data);\n }\n result_data\n }\n\n /// Makes a read-only call to a public function on another contract.\n pub unconstrained fn static_call_public_function<let N: u32>(\n _self: Self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; N],\n gas_opts: GasOpts,\n ) -> [Field] {\n let calldata = [function_selector.to_field()].concat(args);\n\n avm::call_static(\n gas_opts.l2_gas.unwrap_or(MAX_U32_VALUE),\n gas_opts.da_gas.unwrap_or(MAX_U32_VALUE),\n contract_address,\n calldata,\n );\n // Use success_copy to determine whether the call succeeded\n let success = avm::success_copy();\n\n let result_data = avm::returndata_copy(0, avm::returndata_size());\n if !success {\n // Rethrow the revert data.\n avm::revert(result_data);\n }\n result_data\n }\n\n /// Adds a new note hash to the Note Hash Tree.\n pub fn push_note_hash(_self: Self, note_hash: Field) {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { avm::emit_note_hash(note_hash) };\n }\n\n /// Adds a new nullifier to the Nullifier Tree.\n pub fn push_nullifier(_self: Self, nullifier: Field) {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { avm::emit_nullifier(nullifier) };\n }\n\n /// Returns the address of the current contract being executed.\n pub fn this_address(_self: Self) -> AztecAddress {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n avm::address()\n }\n }\n\n /// Returns the contract address that initiated this function call.\n pub fn maybe_msg_sender(_self: Self) -> Option<AztecAddress> {\n // Safety: AVM opcodes are constrained by the AVM itself\n let maybe_msg_sender = unsafe { avm::sender() };\n if maybe_msg_sender == NULL_MSG_SENDER_CONTRACT_ADDRESS {\n Option::none()\n } else {\n Option::some(maybe_msg_sender)\n }\n }\n\n /// Returns the function selector of the currently-executing function.\n pub fn selector(_self: Self) -> FunctionSelector {\n // The selector is the first element of the calldata when calling a public function through dispatch.\n // Safety: AVM opcodes are constrained by the AVM itself.\n let raw_selector: [Field; 1] = unsafe { avm::calldata_copy(0, 1) };\n FunctionSelector::from_field(raw_selector[0])\n }\n\n /// Returns the hash of the arguments passed to the current function.\n pub fn get_args_hash(mut self) -> Field {\n if !self.args_hash.is_some() {\n self.args_hash = Option::some((self.compute_args_hash)());\n }\n\n self.args_hash.unwrap_unchecked()\n }\n\n /// Returns the \"transaction fee\" for the current transaction.\n pub fn transaction_fee(_self: Self) -> Field {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n avm::transaction_fee()\n }\n }\n\n /// Returns the chain ID of the current network.\n pub fn chain_id(_self: Self) -> Field {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n avm::chain_id()\n }\n }\n\n /// Returns the protocol version.\n pub fn version(_self: Self) -> Field {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n avm::version()\n }\n }\n\n /// Returns the current block number.\n pub fn block_number(_self: Self) -> u32 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n avm::block_number()\n }\n }\n\n /// Returns the timestamp of the current block.\n pub fn timestamp(_self: Self) -> u64 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n avm::timestamp()\n }\n }\n\n /// Returns the fee per unit of L2 gas.\n pub fn min_fee_per_l2_gas(_self: Self) -> u128 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n avm::min_fee_per_l2_gas()\n }\n }\n\n /// Returns the fee per unit of DA gas.\n pub fn min_fee_per_da_gas(_self: Self) -> u128 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n avm::min_fee_per_da_gas()\n }\n }\n\n /// Returns the remaining L2 gas available.\n pub fn l2_gas_left(_self: Self) -> u32 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n avm::l2_gas_left()\n }\n }\n\n /// Returns the remaining DA gas available.\n pub fn da_gas_left(_self: Self) -> u32 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n avm::da_gas_left()\n }\n }\n\n /// Checks if the current execution is within a staticcall context.\n pub fn is_static_call(_self: Self) -> bool {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { avm::is_static_call() }\n }\n\n /// Reads raw field values from public storage.\n pub fn raw_storage_read<let N: u32>(self: Self, storage_slot: Field) -> [Field; N] {\n let mut out = [0; N];\n for i in 0..N {\n // Safety: AVM opcodes are constrained by the AVM itself\n out[i] = unsafe {\n avm::storage_read(storage_slot + i as Field, self.this_address().to_field())\n };\n }\n out\n }\n\n /// Reads a typed value from public storage.\n pub fn storage_read<T>(self, storage_slot: Field) -> T\n where\n T: Packable,\n {\n T::unpack(self.raw_storage_read(storage_slot))\n }\n\n /// Writes raw field values to public storage.\n pub fn raw_storage_write<let N: u32>(_self: Self, storage_slot: Field, values: [Field; N]) {\n for i in 0..N {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { avm::storage_write(storage_slot + i as Field, values[i]) };\n }\n }\n\n /// Writes a typed value to public storage.\n pub fn storage_write<T>(self, storage_slot: Field, value: T)\n where\n T: Packable,\n {\n self.raw_storage_write(storage_slot, value.pack());\n }\n}\n\nimpl Empty for PublicContext {\n fn empty() -> Self {\n PublicContext::new(|| 0)\n }\n}\n"
|
|
2372
2752
|
},
|
|
2373
|
-
"
|
|
2753
|
+
"62": {
|
|
2374
2754
|
"function_locations": [
|
|
2375
2755
|
{
|
|
2376
2756
|
"name": "compute_secret_hash",
|
|
@@ -2400,7 +2780,7 @@
|
|
|
2400
2780
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-contracts/contracts/protocol/aztec_sublib/src/hash.nr",
|
|
2401
2781
|
"source": "//! Aztec hash functions.\n\nuse crate::protocol::{\n address::{AztecAddress, EthAddress},\n constants::{\n DOM_SEP__FUNCTION_ARGS, DOM_SEP__MESSAGE_NULLIFIER, DOM_SEP__PUBLIC_BYTECODE,\n DOM_SEP__PUBLIC_CALLDATA, DOM_SEP__SECRET_HASH, MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS,\n },\n hash::{poseidon2_hash_subarray, poseidon2_hash_with_separator, sha256_to_field},\n traits::ToField,\n};\n\npub use crate::protocol::hash::compute_siloed_nullifier;\n\npub fn compute_secret_hash(secret: Field) -> Field {\n poseidon2_hash_with_separator([secret], DOM_SEP__SECRET_HASH)\n}\n\npub fn compute_l1_to_l2_message_hash(\n sender: EthAddress,\n chain_id: Field,\n recipient: AztecAddress,\n version: Field,\n content: Field,\n secret_hash: Field,\n leaf_index: Field,\n) -> Field {\n let mut hash_bytes = [0 as u8; 224];\n let sender_bytes: [u8; 32] = sender.to_field().to_be_bytes();\n let chain_id_bytes: [u8; 32] = chain_id.to_be_bytes();\n let recipient_bytes: [u8; 32] = recipient.to_field().to_be_bytes();\n let version_bytes: [u8; 32] = version.to_be_bytes();\n let content_bytes: [u8; 32] = content.to_be_bytes();\n let secret_hash_bytes: [u8; 32] = secret_hash.to_be_bytes();\n let leaf_index_bytes: [u8; 32] = leaf_index.to_be_bytes();\n\n for i in 0..32 {\n hash_bytes[i] = sender_bytes[i];\n hash_bytes[i + 32] = chain_id_bytes[i];\n hash_bytes[i + 64] = recipient_bytes[i];\n hash_bytes[i + 96] = version_bytes[i];\n hash_bytes[i + 128] = content_bytes[i];\n hash_bytes[i + 160] = secret_hash_bytes[i];\n hash_bytes[i + 192] = leaf_index_bytes[i];\n }\n\n sha256_to_field(hash_bytes)\n}\n\n// The nullifier of a l1 to l2 message is the hash of the message salted with the secret\npub fn compute_l1_to_l2_message_nullifier(message_hash: Field, secret: Field) -> Field {\n poseidon2_hash_with_separator([message_hash, secret], DOM_SEP__MESSAGE_NULLIFIER)\n}\n\n// Computes the hash of input arguments or return values for private functions, or for authwit creation.\npub fn hash_args<let N: u32>(args: [Field; N]) -> Field {\n if args.len() == 0 {\n 0\n } else {\n poseidon2_hash_with_separator(args, DOM_SEP__FUNCTION_ARGS)\n }\n}\n\n// Computes the hash of calldata for public functions.\npub fn hash_calldata_array<let N: u32>(calldata: [Field; N]) -> Field {\n poseidon2_hash_with_separator(calldata, DOM_SEP__PUBLIC_CALLDATA)\n}\n\n/// Computes the public bytecode commitment for a contract class. The commitment is `hash([(length | separator),\n/// ...bytecode])`.\n///\n/// @param packed_bytecode - The packed bytecode of the contract class. 0th word is the length in bytes.\n/// packed_bytecode is mutable so that we can avoid copying the array to construct one starting with first_field\n/// instead of length. @returns The public bytecode commitment.\npub fn compute_public_bytecode_commitment(\n mut packed_public_bytecode: [Field; MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS],\n) -> Field {\n // First field element contains the length of the bytecode\n let bytecode_length_in_bytes: u32 = packed_public_bytecode[0] as u32;\n let bytecode_length_in_fields: u32 = (bytecode_length_in_bytes / 31) + (bytecode_length_in_bytes % 31 != 0) as u32;\n // Don't allow empty public bytecode. AVM doesn't handle execution of contracts that exist with empty bytecode.\n assert(bytecode_length_in_fields != 0);\n assert(bytecode_length_in_fields < MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS);\n\n // Packed_bytecode's 0th entry is the length. Append it to the separator before hashing.\n let first_field = DOM_SEP__PUBLIC_BYTECODE.to_field() + (packed_public_bytecode[0] as u64 << 32) as Field;\n packed_public_bytecode[0] = first_field;\n\n // `fields_to_hash` is the number of fields from the start of `packed_public_bytecode` that should be included in\n // the hash. Fields after this length are ignored. +1 to account for the separator.\n let num_fields_to_hash = bytecode_length_in_fields + 1;\n\n poseidon2_hash_subarray(packed_public_bytecode, num_fields_to_hash)\n}\n"
|
|
2402
2782
|
},
|
|
2403
|
-
"
|
|
2783
|
+
"69": {
|
|
2404
2784
|
"function_locations": [
|
|
2405
2785
|
{
|
|
2406
2786
|
"name": "process_l1_to_l2_message",
|
|
@@ -2410,7 +2790,7 @@
|
|
|
2410
2790
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-contracts/contracts/protocol/aztec_sublib/src/messaging.nr",
|
|
2411
2791
|
"source": "use crate::{\n hash::{compute_l1_to_l2_message_hash, compute_l1_to_l2_message_nullifier, compute_secret_hash},\n oracle::get_l1_to_l2_membership_witness::get_l1_to_l2_membership_witness,\n};\n\nuse crate::protocol::{\n address::{AztecAddress, EthAddress},\n merkle_tree::root::root_from_sibling_path,\n};\n\npub fn process_l1_to_l2_message(\n l1_to_l2_root: Field,\n contract_address: AztecAddress,\n portal_contract_address: EthAddress,\n chain_id: Field,\n version: Field,\n content: Field,\n secret: Field,\n leaf_index: Field,\n) -> Field {\n let secret_hash = compute_secret_hash(secret);\n let message_hash = compute_l1_to_l2_message_hash(\n portal_contract_address,\n chain_id,\n contract_address,\n version,\n content,\n secret_hash,\n leaf_index,\n );\n\n // We prove that `message_hash` is in the tree by showing the derivation of the tree root, using a merkle path we\n // get from an oracle.\n // Safety: The witness is only used as a \"magical value\" that makes the merkle proof below pass. Hence it's safe.\n let (_leaf_index, sibling_path) =\n unsafe { get_l1_to_l2_membership_witness(contract_address, message_hash, secret) };\n\n let root = root_from_sibling_path(message_hash, leaf_index, sibling_path);\n assert_eq(root, l1_to_l2_root, \"Message not in state\");\n\n compute_l1_to_l2_message_nullifier(message_hash, secret)\n}\n"
|
|
2412
2792
|
},
|
|
2413
|
-
"
|
|
2793
|
+
"72": {
|
|
2414
2794
|
"function_locations": [
|
|
2415
2795
|
{
|
|
2416
2796
|
"name": "address",
|
|
@@ -2648,7 +3028,7 @@
|
|
|
2648
3028
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-contracts/contracts/protocol/aztec_sublib/src/oracle/avm.nr",
|
|
2649
3029
|
"source": "//! AVM oracles.\n//!\n//! There are only available during public execution. Calling any of them from a private or utility function will\n//! result in runtime errors.\n\nuse crate::protocol::address::{AztecAddress, EthAddress};\n\npub unconstrained fn address() -> AztecAddress {\n address_opcode()\n}\npub unconstrained fn sender() -> AztecAddress {\n sender_opcode()\n}\npub unconstrained fn transaction_fee() -> Field {\n transaction_fee_opcode()\n}\npub unconstrained fn chain_id() -> Field {\n chain_id_opcode()\n}\npub unconstrained fn version() -> Field {\n version_opcode()\n}\npub unconstrained fn block_number() -> u32 {\n block_number_opcode()\n}\npub unconstrained fn timestamp() -> u64 {\n timestamp_opcode()\n}\npub unconstrained fn min_fee_per_l2_gas() -> u128 {\n min_fee_per_l2_gas_opcode()\n}\npub unconstrained fn min_fee_per_da_gas() -> u128 {\n min_fee_per_da_gas_opcode()\n}\npub unconstrained fn l2_gas_left() -> u32 {\n l2_gas_left_opcode()\n}\npub unconstrained fn da_gas_left() -> u32 {\n da_gas_left_opcode()\n}\npub unconstrained fn is_static_call() -> bool {\n is_static_call_opcode()\n}\npub unconstrained fn note_hash_exists(note_hash: Field, leaf_index: u64) -> bool {\n note_hash_exists_opcode(note_hash, leaf_index)\n}\npub unconstrained fn emit_note_hash(note_hash: Field) {\n emit_note_hash_opcode(note_hash)\n}\npub unconstrained fn nullifier_exists(siloed_nullifier: Field) -> bool {\n nullifier_exists_opcode(siloed_nullifier)\n}\npub unconstrained fn emit_nullifier(nullifier: Field) {\n emit_nullifier_opcode(nullifier)\n}\npub unconstrained fn emit_public_log(message: [Field]) {\n emit_public_log_opcode(message)\n}\npub unconstrained fn l1_to_l2_msg_exists(msg_hash: Field, msg_leaf_index: u64) -> bool {\n l1_to_l2_msg_exists_opcode(msg_hash, msg_leaf_index)\n}\npub unconstrained fn send_l2_to_l1_msg(recipient: EthAddress, content: Field) {\n send_l2_to_l1_msg_opcode(recipient, content)\n}\n\npub unconstrained fn call<let N: u32>(\n l2_gas_allocation: u32,\n da_gas_allocation: u32,\n address: AztecAddress,\n args: [Field; N],\n) {\n call_opcode(l2_gas_allocation, da_gas_allocation, address, N, args)\n}\n\npub unconstrained fn call_static<let N: u32>(\n l2_gas_allocation: u32,\n da_gas_allocation: u32,\n address: AztecAddress,\n args: [Field; N],\n) {\n call_static_opcode(l2_gas_allocation, da_gas_allocation, address, N, args)\n}\n\npub unconstrained fn calldata_copy<let N: u32>(cdoffset: u32, copy_size: u32) -> [Field; N] {\n calldata_copy_opcode(cdoffset, copy_size)\n}\n\n/// `success_copy` is placed immediately after the CALL opcode to get the success value\npub unconstrained fn success_copy() -> bool {\n success_copy_opcode()\n}\n\npub unconstrained fn returndata_size() -> u32 {\n returndata_size_opcode()\n}\n\npub unconstrained fn returndata_copy(rdoffset: u32, copy_size: u32) -> [Field] {\n returndata_copy_opcode(rdoffset, copy_size)\n}\n\n/// The additional prefix is to avoid clashing with the `return` Noir keyword.\npub unconstrained fn avm_return(returndata: [Field]) {\n return_opcode(returndata)\n}\n\n/// This opcode reverts using the exact data given. In general it should only be used to do rethrows, where the revert\n/// data is the same as the original revert data. For normal reverts, use Noir's `assert` which, on top of reverting,\n/// will also add an error selector to the revert data.\npub unconstrained fn revert(revertdata: [Field]) {\n revert_opcode(revertdata)\n}\n\npub unconstrained fn storage_read(storage_slot: Field, contract_address: Field) -> Field {\n storage_read_opcode(storage_slot, contract_address)\n}\n\npub unconstrained fn storage_write(storage_slot: Field, value: Field) {\n storage_write_opcode(storage_slot, value);\n}\n\n#[oracle(aztec_avm_address)]\nunconstrained fn address_opcode() -> AztecAddress {}\n\n#[oracle(aztec_avm_sender)]\nunconstrained fn sender_opcode() -> AztecAddress {}\n\n#[oracle(aztec_avm_transactionFee)]\nunconstrained fn transaction_fee_opcode() -> Field {}\n\n#[oracle(aztec_avm_chainId)]\nunconstrained fn chain_id_opcode() -> Field {}\n\n#[oracle(aztec_avm_version)]\nunconstrained fn version_opcode() -> Field {}\n\n#[oracle(aztec_avm_blockNumber)]\nunconstrained fn block_number_opcode() -> u32 {}\n\n#[oracle(aztec_avm_timestamp)]\nunconstrained fn timestamp_opcode() -> u64 {}\n\n#[oracle(aztec_avm_minFeePerL2Gas)]\nunconstrained fn min_fee_per_l2_gas_opcode() -> u128 {}\n\n#[oracle(aztec_avm_minFeePerDaGas)]\nunconstrained fn min_fee_per_da_gas_opcode() -> u128 {}\n\n#[oracle(aztec_avm_l2GasLeft)]\nunconstrained fn l2_gas_left_opcode() -> u32 {}\n\n#[oracle(aztec_avm_daGasLeft)]\nunconstrained fn da_gas_left_opcode() -> u32 {}\n\n#[oracle(aztec_avm_isStaticCall)]\nunconstrained fn is_static_call_opcode() -> bool {}\n\n#[oracle(aztec_avm_noteHashExists)]\nunconstrained fn note_hash_exists_opcode(note_hash: Field, leaf_index: u64) -> bool {}\n\n#[oracle(aztec_avm_emitNoteHash)]\nunconstrained fn emit_note_hash_opcode(note_hash: Field) {}\n\n#[oracle(aztec_avm_nullifierExists)]\nunconstrained fn nullifier_exists_opcode(siloed_nullifier: Field) -> bool {}\n\n#[oracle(aztec_avm_emitNullifier)]\nunconstrained fn emit_nullifier_opcode(nullifier: Field) {}\n\n#[oracle(aztec_avm_emitPublicLog)]\nunconstrained fn emit_public_log_opcode(message: [Field]) {}\n\n#[oracle(aztec_avm_l1ToL2MsgExists)]\nunconstrained fn l1_to_l2_msg_exists_opcode(msg_hash: Field, msg_leaf_index: u64) -> bool {}\n\n#[oracle(aztec_avm_sendL2ToL1Msg)]\nunconstrained fn send_l2_to_l1_msg_opcode(recipient: EthAddress, content: Field) {}\n\n#[oracle(aztec_avm_calldataCopy)]\nunconstrained fn calldata_copy_opcode<let N: u32>(cdoffset: u32, copy_size: u32) -> [Field; N] {}\n\n#[oracle(aztec_avm_returndataSize)]\nunconstrained fn returndata_size_opcode() -> u32 {}\n\n#[oracle(aztec_avm_returndataCopy)]\nunconstrained fn returndata_copy_opcode(rdoffset: u32, copy_size: u32) -> [Field] {}\n\n#[oracle(aztec_avm_return)]\nunconstrained fn return_opcode(returndata: [Field]) {}\n\n#[oracle(aztec_avm_revert)]\nunconstrained fn revert_opcode(revertdata: [Field]) {}\n\n// While the length parameter might seem unnecessary given that we have N we keep it around because at the AVM bytecode\n// level, we want to support non-comptime-known lengths for such opcodes, even if Noir code will not generally take\n// that route.\n#[oracle(aztec_avm_call)]\nunconstrained fn call_opcode<let N: u32>(\n l2_gas_allocation: u32,\n da_gas_allocation: u32,\n address: AztecAddress,\n length: u32,\n args: [Field; N],\n) {}\n\n// While the length parameter might seem unnecessary given that we have N we keep it around because at the AVM bytecode\n// level, we want to support non-comptime-known lengths for such opcodes, even if Noir code will not generally take\n// that route.\n#[oracle(aztec_avm_staticCall)]\nunconstrained fn call_static_opcode<let N: u32>(\n l2_gas_allocation: u32,\n da_gas_allocation: u32,\n address: AztecAddress,\n length: u32,\n args: [Field; N],\n) {}\n\n#[oracle(aztec_avm_successCopy)]\nunconstrained fn success_copy_opcode() -> bool {}\n\n#[oracle(aztec_avm_storageRead)]\nunconstrained fn storage_read_opcode(storage_slot: Field, contract_address: Field) -> Field {}\n\n#[oracle(aztec_avm_storageWrite)]\nunconstrained fn storage_write_opcode(storage_slot: Field, value: Field) {}\n"
|
|
2650
3030
|
},
|
|
2651
|
-
"
|
|
3031
|
+
"76": {
|
|
2652
3032
|
"function_locations": [
|
|
2653
3033
|
{
|
|
2654
3034
|
"name": "store",
|
|
@@ -2674,7 +3054,7 @@
|
|
|
2674
3054
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-contracts/contracts/protocol/aztec_sublib/src/oracle/execution_cache.nr",
|
|
2675
3055
|
"source": "/// Stores values represented as slice in execution cache to be later obtained by its hash.\npub fn store<let N: u32>(values: [Field; N], hash: Field) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe to\n // call. When loading the values, however, the caller must check that the values are indeed the preimage.\n unsafe { store_in_execution_cache_oracle_wrapper(values, hash) };\n}\n\nunconstrained fn store_in_execution_cache_oracle_wrapper<let N: u32>(\n values: [Field; N],\n hash: Field,\n) {\n store_in_execution_cache_oracle(values, hash);\n}\n\npub unconstrained fn load<let N: u32>(hash: Field) -> [Field; N] {\n load_from_execution_cache_oracle(hash)\n}\n\n// TODO(F-498): review naming consistency\n#[oracle(aztec_prv_setHashPreimage)]\nunconstrained fn store_in_execution_cache_oracle<let N: u32>(_values: [Field; N], _hash: Field) {}\n\n// TODO(F-498): review naming consistency\n#[oracle(aztec_prv_getHashPreimage)]\nunconstrained fn load_from_execution_cache_oracle<let N: u32>(_hash: Field) -> [Field; N] {}\n"
|
|
2676
3056
|
},
|
|
2677
|
-
"
|
|
3057
|
+
"77": {
|
|
2678
3058
|
"function_locations": [
|
|
2679
3059
|
{
|
|
2680
3060
|
"name": "get_l1_to_l2_membership_witness",
|
|
@@ -2688,7 +3068,7 @@
|
|
|
2688
3068
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-contracts/contracts/protocol/aztec_sublib/src/oracle/get_l1_to_l2_membership_witness.nr",
|
|
2689
3069
|
"source": "use crate::protocol::{address::AztecAddress, constants::L1_TO_L2_MSG_TREE_HEIGHT};\n\n/// Returns the leaf index and sibling path of an entry in the L1 to L2 messaging tree, which can then be used to prove\n/// its existence.\npub unconstrained fn get_l1_to_l2_membership_witness(\n contract_address: AztecAddress,\n message_hash: Field,\n secret: Field,\n) -> (Field, [Field; L1_TO_L2_MSG_TREE_HEIGHT]) {\n get_l1_to_l2_membership_witness_oracle(contract_address, message_hash, secret)\n}\n\n// Obtains membership witness (index and sibling path) for a message in the L1 to L2 message tree.\n#[oracle(aztec_utl_getL1ToL2MembershipWitness)]\nunconstrained fn get_l1_to_l2_membership_witness_oracle(\n _contract_address: AztecAddress,\n _message_hash: Field,\n _secret: Field,\n) -> (Field, [Field; L1_TO_L2_MSG_TREE_HEIGHT]) {}\n"
|
|
2690
3070
|
},
|
|
2691
|
-
"
|
|
3071
|
+
"80": {
|
|
2692
3072
|
"function_locations": [
|
|
2693
3073
|
{
|
|
2694
3074
|
"name": "notify_created_nullifier",
|
|
@@ -2718,7 +3098,7 @@
|
|
|
2718
3098
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-contracts/contracts/protocol/aztec_sublib/src/oracle/nullifiers.nr",
|
|
2719
3099
|
"source": "//! Nullifier creation, existence checks, etc.\n\nuse crate::protocol::address::aztec_address::AztecAddress;\n\n/// Notifies the simulator that a nullifier has been created, so that its correct status (pending or settled) can be\n/// determined when reading nullifiers in subsequent private function calls. The first non-revertible nullifier emitted\n/// is also used to compute note nonces.\npub fn notify_created_nullifier(inner_nullifier: Field) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe to\n // call.\n unsafe { notify_created_nullifier_oracle(inner_nullifier) };\n}\n\n#[oracle(aztec_prv_notifyCreatedNullifier)]\nunconstrained fn notify_created_nullifier_oracle(_inner_nullifier: Field) {}\n\n/// Returns true if the nullifier has been emitted in the same transaction, i.e. if [notify_created_nullifier] has been\n/// called for this inner nullifier from the contract with the specified address.\n///\n/// Note that despite sharing pending transaction information with the app, this is not a privacy leak: anyone in the\n/// network can always determine in which transaction a inner nullifier was emitted by a given contract by simply\n/// inspecting transaction effects. What _would_ constitute a leak would be to share the list of inner pending\n/// nullifiers, as that would reveal their preimages.\npub unconstrained fn is_nullifier_pending(\n inner_nullifier: Field,\n contract_address: AztecAddress,\n) -> bool {\n is_nullifier_pending_oracle(inner_nullifier, contract_address)\n}\n\n#[oracle(aztec_prv_isNullifierPending)]\nunconstrained fn is_nullifier_pending_oracle(\n _inner_nullifier: Field,\n _contract_address: AztecAddress,\n) -> bool {}\n\n/// Returns true if the nullifier exists. Note that a `true` value can be constrained by proving existence of the\n/// nullifier, but a `false` value should not be relied upon since other transactions may emit this nullifier before\n/// the current transaction is included in a block. While this might seem of little use at first, certain design\n/// patterns benefit from this abstraction (see e.g. `PrivateMutable`).\npub unconstrained fn check_nullifier_exists(inner_nullifier: Field) -> bool {\n check_nullifier_exists_oracle(inner_nullifier)\n}\n\n// TODO(F-498): review naming consistency\n#[oracle(aztec_utl_doesNullifierExist)]\nunconstrained fn check_nullifier_exists_oracle(_inner_nullifier: Field) -> bool {}\n"
|
|
2720
3100
|
},
|
|
2721
|
-
"
|
|
3101
|
+
"81": {
|
|
2722
3102
|
"function_locations": [
|
|
2723
3103
|
{
|
|
2724
3104
|
"name": "validate_public_calldata",
|
|
@@ -2736,7 +3116,7 @@
|
|
|
2736
3116
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-contracts/contracts/protocol/aztec_sublib/src/oracle/public_call.nr",
|
|
2737
3117
|
"source": "/// Validates public calldata by checking that the preimage exists and the cumulative size is within limits.\n///\n/// The check is unconstrained and the only purpose of it is to fail early in case of calldata overflow or a bug in\n/// calldata hashing.\npub(crate) fn validate_public_calldata(calldata_hash: Field) {\n // Safety: This oracle call returns nothing: we only call it for its side effects (validating the calldata).\n // It is therefore always safe to call.\n unsafe {\n validate_public_calldata_wrapper(calldata_hash)\n }\n}\n\nunconstrained fn validate_public_calldata_wrapper(calldata_hash: Field) {\n validate_public_calldata_oracle(calldata_hash)\n}\n\n// TODO(F-498): review naming consistency\n#[oracle(aztec_prv_assertValidPublicCalldata)]\nunconstrained fn validate_public_calldata_oracle(_calldata_hash: Field) {}\n"
|
|
2738
3118
|
},
|
|
2739
|
-
"
|
|
3119
|
+
"83": {
|
|
2740
3120
|
"function_locations": [
|
|
2741
3121
|
{
|
|
2742
3122
|
"name": "notify_revertible_phase_start",
|
|
@@ -2762,7 +3142,7 @@
|
|
|
2762
3142
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-contracts/contracts/protocol/aztec_sublib/src/oracle/tx_phase.nr",
|
|
2763
3143
|
"source": "/// Notifies PXE of the side effect counter at which the revertible phase begins.\n///\n/// PXE uses it to classify notes and nullifiers as revertible or non-revertible in its note cache. This information is\n/// then fed to kernels as hints.\npub(crate) fn notify_revertible_phase_start(counter: u32) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe to\n // call.\n unsafe { notify_revertible_phase_start_oracle_wrapper(counter) };\n}\n\n/// Returns whether a side effect counter falls in the revertible phase of the transaction.\npub(crate) unconstrained fn in_revertible_phase(current_counter: u32) -> bool {\n in_revertible_phase_oracle(current_counter)\n}\n\nunconstrained fn notify_revertible_phase_start_oracle_wrapper(counter: u32) {\n notify_revertible_phase_start_oracle(counter);\n}\n\n#[oracle(aztec_prv_notifyRevertiblePhaseStart)]\nunconstrained fn notify_revertible_phase_start_oracle(_counter: u32) {}\n\n// TODO(F-498): review naming consistency\n#[oracle(aztec_prv_isExecutionInRevertiblePhase)]\nunconstrained fn in_revertible_phase_oracle(current_counter: u32) -> bool {}\n"
|
|
2764
3144
|
},
|
|
2765
|
-
"
|
|
3145
|
+
"84": {
|
|
2766
3146
|
"function_locations": [
|
|
2767
3147
|
{
|
|
2768
3148
|
"name": "assert_compatible_oracle_version",
|
|
@@ -2786,7 +3166,7 @@
|
|
|
2786
3166
|
}
|
|
2787
3167
|
],
|
|
2788
3168
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/noir-contracts/contracts/protocol/aztec_sublib/src/oracle/version.nr",
|
|
2789
|
-
"source": "/// The oracle version constants are used to check that the oracle interface is in sync between PXE and Aztec.nr.\n/// We version the oracle interface as `major.minor` where:\n/// - `major` = backward-breaking changes (must match exactly between PXE and Aztec.nr)\n/// - `minor` = oracle additions (non-breaking; PXE minor >= contract minor)\n///\n/// The TypeScript counterparts are in `oracle_version.ts`.\n///\n/// @dev Whenever a contract function or Noir test is run, the `aztec_misc_assertCompatibleOracleVersion` oracle is\n/// called. If the major version is incompatible, an error is thrown immediately. The minor version is recorded by\n/// the PXE and used to provide helpful error messages if a contract calls an oracle that doesn't exist. We don't throw\n/// immediately if AZTEC_NR_MINOR > PXE_MINOR because if a contract is updated to use a newer Aztec.nr dependency\n/// without actually using any of the new oracles then there is no reason to throw.\npub global ORACLE_VERSION_MAJOR: Field =
|
|
3169
|
+
"source": "/// The oracle version constants are used to check that the oracle interface is in sync between PXE and Aztec.nr.\n/// We version the oracle interface as `major.minor` where:\n/// - `major` = backward-breaking changes (must match exactly between PXE and Aztec.nr)\n/// - `minor` = oracle additions (non-breaking; PXE minor >= contract minor)\n///\n/// The TypeScript counterparts are in `oracle_version.ts`.\n///\n/// @dev Whenever a contract function or Noir test is run, the `aztec_misc_assertCompatibleOracleVersion` oracle is\n/// called. If the major version is incompatible, an error is thrown immediately. The minor version is recorded by\n/// the PXE and used to provide helpful error messages if a contract calls an oracle that doesn't exist. We don't throw\n/// immediately if AZTEC_NR_MINOR > PXE_MINOR because if a contract is updated to use a newer Aztec.nr dependency\n/// without actually using any of the new oracles then there is no reason to throw.\npub global ORACLE_VERSION_MAJOR: Field = 30;\npub global ORACLE_VERSION_MINOR: Field = 0;\n\n/// Asserts that the version of the oracle is compatible with the version expected by the contract.\npub fn assert_compatible_oracle_version() {\n // Safety: This oracle call returns nothing: we only call it to check Aztec.nr and Oracle interface versions are\n // compatible. It is therefore always safe to call.\n unsafe {\n assert_compatible_oracle_version_wrapper();\n }\n}\n\nunconstrained fn assert_compatible_oracle_version_wrapper() {\n assert_compatible_oracle_version_oracle(ORACLE_VERSION_MAJOR, ORACLE_VERSION_MINOR);\n}\n\n#[oracle(aztec_misc_assertCompatibleOracleVersion)]\nunconstrained fn assert_compatible_oracle_version_oracle(major: Field, minor: Field) {}\n\nmod test {\n use super::{\n assert_compatible_oracle_version_oracle, ORACLE_VERSION_MAJOR, ORACLE_VERSION_MINOR,\n };\n\n #[test]\n unconstrained fn compatible_oracle_version() {\n assert_compatible_oracle_version_oracle(ORACLE_VERSION_MAJOR, ORACLE_VERSION_MINOR);\n }\n\n #[test(should_fail_with = \"Incompatible aztec cli version:\")]\n unconstrained fn incompatible_oracle_version_major() {\n let arbitrary_incorrect_major = 318183437;\n assert_compatible_oracle_version_oracle(arbitrary_incorrect_major, ORACLE_VERSION_MINOR);\n }\n}\n"
|
|
2790
3170
|
},
|
|
2791
3171
|
"86": {
|
|
2792
3172
|
"function_locations": [
|
|
@@ -2884,7 +3264,7 @@
|
|
|
2884
3264
|
"abi_public",
|
|
2885
3265
|
"abi_only_self"
|
|
2886
3266
|
],
|
|
2887
|
-
"debug_symbols": "
|
|
3267
|
+
"debug_symbols": "pVjdbuowDH6XXnMR/+SPVzmaJrZ1E1IFqIMjHU28+3EgTgtSomrdxfLVpR+289kO/ek++rfL1+v+8Hn87rZ/frq3cT8M+6/X4fi+O++PB7H+dCb9A8BuSxtZfbe1siLm1d3tBHmVay8rQ17zteW8xvvqqNuCSSAIAAGeMgigQJ6FICDCHaAxGaBa0GZAeovUwmrhYokZWFIQMnCowGfg9St8dgODEKJJgBXEDKJaYraQYQVqAXEDJS5Co6BY0mckfUSsIFlYAHMGFhWIh5QIk8+EArwQUrrlbQZBLSFZnIBoFGQLG1IgSWD5Uk6bfAc+g5RntgnYDFKe70Ac45iAuGrxet10qpvX89j3STYzIYm8TruxP5y77eEyDJvu72643D70fdodbut5N8pdiaw/fMgqhJ/7oU/oupmeNvVHvfzlp30wUAgsPTBAncFxCunG4NjhxBAfGLDOQIWAHJfnPS73oMTgLMaaB1xnYNQUWjAzgl9lEUwti67OEE3IBHEWAdNiDwK44gG5mgehkUVpJ5pFCL6WxVhnQK8xSHHX9rGZRVuyGCnUYmgxxKgxiJixquaGGAFTqd4oAKMtFME9UlAjD0HVRHGKAuHJiYYeIxl1IhJPcUB4LGywLUWx5iKaaOocrlWZSkFhFgk/MfhGLsCrLhEC/44DSd1AdA0/GtqkWMTJBqZtBb/YDaGAsq8+1t1oqQui9jog42rqwgaFDaVMzbSrsj2LCcqOOGdrBEuLDKsjA1vaZC306LEaQ0OYYJA0CsG22q6wsaExRl84DHCVY33XxLVtsx2HxSkODDUnqDFDydoibmew6kZ7T3C2J756FKBW77SkzRMtT/mU4+vv9Olr+qSGPrFUKcEkcF58qgqmDJFgZmeaZxf86jlEYe0corh+DrFZP4cY1s4hxvVzqMmxcA4xr55DS7Xlq9riVqVC2VaQn6G1BswteZqQDjC52ANWmye3BMqodYY8k9dzsbcdmc7egmP1+G9Ni8Ty1EJtrLZQ2xKpC8pBHumhhb7I1e59Pz68J7gmrnG/exv6fPl5ObzP7p7/nfSOvmc4jcf3/uMy9olp/rJBfi4Guwn+5Zq+7T8=",
|
|
2888
3268
|
"is_unconstrained": true,
|
|
2889
3269
|
"name": "_increase_public_balance"
|
|
2890
3270
|
},
|
|
@@ -2932,7 +3312,7 @@
|
|
|
2932
3312
|
"abi_public",
|
|
2933
3313
|
"abi_view"
|
|
2934
3314
|
],
|
|
2935
|
-
"debug_symbols": "
|
|
3315
|
+
"debug_symbols": "nZbdjuIwDIXfJde9iJ1f8yqjESpQRpWqgjqw0gr13TeBOmlXSpadG3Jwmq/HsZv2IU7d4f6178fz5VvsPh7iMPXD0H/th8uxvfWXMUQfQsYfq8VONcKS2OlGOP0cPL4GJ3YAjSD7GkHCIhBZ8JTiKcURzRHNESNZaBa0CKtY+EU4voVbXICPQBWFWQRJFksEpWTBEeAIRBshK0RgwREVr7FRmEXoGHFRmEUYjhi/iOgZIzl6RhOEC0CMU9HqSzwj89wI3vr9beq6uPOrWoQKXdupG29iN96HoRG/2uH+vOj72o7P8dZOYVY2ohtPYQzAcz90Uc1NXi3LS0FKbZblQVuXEEZtGFBmkI2FeCLIKswE2hCw5sJbNgGSEsHhf+ShfMoDlCzlUWWAdZnhbYlhKgzM24lkEiHA1gRbJqDnciryaT3C1oKrlENJtkBK53KA33aFryCkVoyQJIsIKiNUIii/SkNvAVApB4LjpkDw+mcMVGwjPNcVH5XmVOS4s7SEXFJwb9sICEhFdVS0UWssIOLGUtKWGgsqCON5L6zMNQ3VeRuQCmKtKQHef8BW7f33YVPrTc0IcljMgmouUKXTRqJxxQOrkgoR5Uwk6CKjcm5acKkg4Ms2Kr2JqTWRdOnYrOdhMOeBvmhCV7rbmNTdVmLJxj9qgquauPJLpHZyGsVHJxqd9zO82uf5M/xtj/20+diZI2zq28PQLX/P9/G4mr39vvIMfyxdp8uxO92nLpLyFxOEd/uH8Y2Vn3O82x8=",
|
|
2936
3316
|
"is_unconstrained": true,
|
|
2937
3317
|
"name": "balance_of_public"
|
|
2938
3318
|
},
|
|
@@ -2970,7 +3350,7 @@
|
|
|
2970
3350
|
"abi_public",
|
|
2971
3351
|
"abi_view"
|
|
2972
3352
|
],
|
|
2973
|
-
"debug_symbols": "nVbbauMwEP0XP+dBM6Pb5FdKKW7qFoNxgpssLCX/vqNaYzsBiWxeouNRfHzmKv00H9375eutHz+P383+5ad5n/ph6L/ehuOhPffHUaw/jUk/YGKzp10DQM3epjXOK/p5JWj2Ia3yzLJayKub7c7kVZ4BBHijQC2BFMQMIgqIAhgU+BkghAwQFOgWqYXUYtWS1MyAM3BWQczAkwL9REAFQohGQDQKXAasFs4WMkaBWkBkICTgM0C1YPqPxJfIKEgWiSxZoyBm4EQhJcKkmVCAF0JKWwEUqCUmi0sgWbyAFMwZcALX667RhL+dp65L+d5UgNTFqZ268dzsx8sw7Jo/7XD5/dP3qR1/13M7ya4o6sYPWYXwsx+6hK679W1TfjUy+/
|
|
3353
|
+
"debug_symbols": "nVbbauMwEP0XP+dBM6Pb5FdKKW7qFoNxgpssLCX/vqNaYzsBiWxeouNRfHzmKv00H9375eutHz+P383+5ad5n/ph6L/ehuOhPffHUaw/jUk/YGKzp10DQM3epjXOK/p5JWj2Ia3yzLJayKub7c7kVZ4BBHijQC2BFMQMIgqIAhgU+BkghAwQFOgWqYXUYtWS1MyAM3BWQczAkwL9REAFQohGQDQKXAasFs4WMkaBWkBkICTgM0C1YPqPxJfIKEgWiSxZoyBm4EQhJcKkmVCAF0JKWwEUqCUmi0sgWbyAFMwZcALX667RhL+dp65L+d5UgNTFqZ268dzsx8sw7Jo/7XD5/dP3qR1/13M7ya4o6sYPWYXwsx+6hK679W1TfjUy+/w2G4gLgaMbBigzsE8VMzN4wpWBbxiwzCAlrhoADC8MAR/3IvLiRQglLyoMLH2jDNIYJQZXZvDWqgZvfTEOvsxACwF5W4pCVUEIqsAhlxTEMoNFLSW3TYR7KorBFqupRmGiMmxcsP+RSFwlWFOUUKtHmVZajzJVForobymoTCFzSlPJa1Mh3ImwFT9keqkfZNdygnjb2+BqsbS0tAWbMke1KJWC4sYTe8cQKrGAoO2NEO1zHEgqQ46big6ueMJBS8saWNMK4WEZQgFLXgOXZdSqC1jbHMj4UnVhhcJFDYY3a1YlPQ8TLBnxm1l3R/Bok0UsNRnWatPqrOKARR987dRAWo4Ngy4UT55KQpk5LBwGbJGjMjS93J80mhDLMiqliUtlIhcnf90Ph6sfGEsiqHKQk3NLcXuDRRn1nOAmJ6F4ClJtdjrS4SmXxDWecuF8qj75uftAGs75HIJbhld5ag/9dHNbvyauqW/fhy4/fl7Gw2b3/PekO3rbP03HQ/dxmbrEtLnyyzXxRWoquNdr+to/",
|
|
2974
3354
|
"is_unconstrained": true,
|
|
2975
3355
|
"name": "check_balance"
|
|
2976
3356
|
},
|
|
@@ -3466,6 +3846,12 @@
|
|
|
3466
3846
|
"sign": "unsigned",
|
|
3467
3847
|
"width": 32
|
|
3468
3848
|
}
|
|
3849
|
+
},
|
|
3850
|
+
{
|
|
3851
|
+
"name": "tx_request_salt",
|
|
3852
|
+
"type": {
|
|
3853
|
+
"kind": "field"
|
|
3854
|
+
}
|
|
3469
3855
|
}
|
|
3470
3856
|
],
|
|
3471
3857
|
"kind": "struct",
|
|
@@ -4788,6 +5174,12 @@
|
|
|
4788
5174
|
"kind": "struct",
|
|
4789
5175
|
"path": "aztec::protocol_types::utils::arrays::claimed_length_array::ClaimedLengthArray"
|
|
4790
5176
|
}
|
|
5177
|
+
},
|
|
5178
|
+
{
|
|
5179
|
+
"name": "tx_request_salt",
|
|
5180
|
+
"type": {
|
|
5181
|
+
"kind": "field"
|
|
5182
|
+
}
|
|
4791
5183
|
}
|
|
4792
5184
|
],
|
|
4793
5185
|
"kind": "struct",
|
|
@@ -4796,14 +5188,14 @@
|
|
|
4796
5188
|
"visibility": "databus"
|
|
4797
5189
|
}
|
|
4798
5190
|
},
|
|
4799
|
-
"bytecode": "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",
|
|
5191
|
+
"bytecode": "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Qzm2wzi2wzm2Izi2Izm2ozi2ozm2Yzi2Yzm24zi24zm2Ezi2Ezm2kzi2kzm2b3Jsp3Bsp3Jsp3Fsp3Ns3+LYzuDYzuTYzuLYvs2xfYdj+y7H9j2O7fsc29kc2zkc27kc23kc2w84th9ybOdzbBdwbBdybBdxbD/i2C7m2C7h2C7l2C7j2H7MsV3Osf2EY/spx3YFx5b0KyqfcWxXcWxXc2zXcGzXcmzXcWzXq39RSsfWx1mt4Nhu4Nhu5Nhu4thu5thu4dhu5dhu49hu59ju4Nju5Nju4tju5tju4dju5dju49ju59ge4Nge5Nge4tge5tge4dge5dge49h+zrH9gmN7nGP7Jcf2K47t1xzbExzbbzi233Jsv+PYfs+xjbpRL9YT4ocspCcE6WHGj5w9/YTsyUX6luEpju1pju3PHNtfOLa/cmx/49j+zrH9g2P7J8f2L47t3xxbTg9gm9MD2Ob0ALY5PYBtTg9gm9MD2Ob0ALY5PYBtTg9gm9MD2Ob0ALY5PYBtTg9gm9MD2Ob0ALY5PYBtTg9gm9MD2Ob0ALYLcGw5PYBtTg9gm9MD2Ob0ALY5PYBtTg9gm9MD2Ob0ALY5PYBtTg9gm9MD2Ob0ALY5PYBtTg9g+0rKp7A2pwewzekBbHN6ANucHsA2pwewzekBbHN6ANucHsD29RzbGzi2N3Jsb+LY3syxvYVjy+mla3N66dplObacXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla9fh2HJ66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euncGx5fTStTm9dG1OL12b00vX5vTStTm9dG1OL12b00vX5vTStTm9dG3Ot9xtTi9dm9NL1+b00rU5vXRtTi9dm9NL1+b00rU5vXRtTi9dm9NL1+b00rU5vXRtTi9dm9NL1+b00rU5vXRtTi9dm9NL1+b00rU5vXTtLI4tp5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dpzObacXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p/2Mzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66drrObacXro2p5euzemla3N66dqcXro2p5euvYVjy+mla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla5/k2P7Asf2RY/sTx5bT/9bm9L+1Of1vbU7/W5vT/9bm9L+1Of1vbU7/W5vT/9bm9L+1Of1vbU7/Wxen/62L0//Wxel/6+L0v3Vx+t+6OP1vXZz+ty5O/1sXp/+ti9P/1sXpf+vi9L91cfrfujj9b12c/rcuTv9bF6f/rYvT/9ZVgGPL6X/r4vS/dXH637o4/W9dnP63Lk7/Wxen/62L0//Wxel/6+L0v3Vx+t+6OP1vXZz+ty5O/1vXlRxbTv9bF6f/rYvT/9bF6X/r4vS/dXH637o4/W9dnP63Lk7/Wxen/62L0//Wxel/6+L0v3Vx+t+6OP1vXZz+t66yHFtO/1sXp/+ti9P/1sXpf+vi9L91cfrfujj9b12c/rcuTv9bF6f/rYvT/9bF6X/r4vS/dXH637o4/W9dnP63Lk7/Wxen/62L0//Wxel/6+L0v3Vx+t+6OP1vXZz+ty5O/1sXp/+ti9P/1sXpf+vi9L91cfrfujj9b111OLac/rcuTv9bF6f/rYvT/9bF6X/r4vS/dXH637o4/W9dnP63Lk7/Wxen/62L0//Wxel/6+L0v3Vx+t+6OP1vXZz+ty5O/1sXp/+ti9P/1sXpf+vi9L91cfrfujj9b12c/rcuTv9bF6f/rYvT/9YVdf/brCz132y8Fpoa6pFbo1mrNhmdq7Zu0X5o3D5X5etvuPGmm28pXabsrbfdfsedd919z7333f/Agw+VK/9whYqVKlepWq36IzVq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",
|
|
4800
5192
|
"custom_attributes": [
|
|
4801
5193
|
"abi_private"
|
|
4802
5194
|
],
|
|
4803
|
-
"debug_symbols": "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",
|
|
5195
|
+
"debug_symbols": "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",
|
|
4804
5196
|
"is_unconstrained": false,
|
|
4805
5197
|
"name": "claim",
|
|
4806
|
-
"verification_key": "
|
|
5198
|
+
"verification_key": "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"
|
|
4807
5199
|
},
|
|
4808
5200
|
{
|
|
4809
5201
|
"abi": {
|
|
@@ -5297,6 +5689,12 @@
|
|
|
5297
5689
|
"sign": "unsigned",
|
|
5298
5690
|
"width": 32
|
|
5299
5691
|
}
|
|
5692
|
+
},
|
|
5693
|
+
{
|
|
5694
|
+
"name": "tx_request_salt",
|
|
5695
|
+
"type": {
|
|
5696
|
+
"kind": "field"
|
|
5697
|
+
}
|
|
5300
5698
|
}
|
|
5301
5699
|
],
|
|
5302
5700
|
"kind": "struct",
|
|
@@ -6619,6 +7017,12 @@
|
|
|
6619
7017
|
"kind": "struct",
|
|
6620
7018
|
"path": "aztec::protocol_types::utils::arrays::claimed_length_array::ClaimedLengthArray"
|
|
6621
7019
|
}
|
|
7020
|
+
},
|
|
7021
|
+
{
|
|
7022
|
+
"name": "tx_request_salt",
|
|
7023
|
+
"type": {
|
|
7024
|
+
"kind": "field"
|
|
7025
|
+
}
|
|
6622
7026
|
}
|
|
6623
7027
|
],
|
|
6624
7028
|
"kind": "struct",
|
|
@@ -6627,14 +7031,14 @@
|
|
|
6627
7031
|
"visibility": "databus"
|
|
6628
7032
|
}
|
|
6629
7033
|
},
|
|
6630
|
-
"bytecode": "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",
|
|
7034
|
+
"bytecode": "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9i2ObWeObReObVeObTeObXeObQ+ObU+ObS+ObW+ObR+ObV+ObT+ObX+O7QCO7UCO7SCO7WCObQbH1suxzeTYDuHYDuXYDuPYDufYjuDYjuTYjuLYjubYjuHYjuXYjuPYjufYTuDYTuTYTuLYvs2xncyxncKxncqxncaxfYdjO51jO4NjO5Nj+y7H9j2O7fsc2w84th9ybGdxbGdzbOdwbOdybD/i2H7MsZ3HsZ3PsV3AsV3Isf2EY7uIY7uYY7uEY7uUY/spx3YZx/Yzju1yju0Kji3pV1Q+59iu4tiu5tiu4diu5diu49iuV/+ilI6tj7NawbHdwLHdyLHdxLHdzLHdwrHdyrHdxrHdzrHdwbHdybHdxbHdzbHdw7Hdy7Hdx7Hdz7E9wLE9yLE9xLE9zLE9wrE9yrH9gmP7Jcf2GMf2OMf2K47t1xzbExzbkxzbbzi233Jsv+PYfs+xjbpRL9YT4odMpCcE6WHGj5w9/YTsyUX6luFpju0Zju3PHNtfOLa/cmx/49j+zrH9g2P7J8f2L47t3xxbTg9gm9MD2Ob0ALY5PYBtTg9gm9MD2Ob0ALY5PYBtTg9gm9MD2Ob0ALY5PYBtTg9gm9MD2Ob0ALY5PYBtTg9gm9MD2Ob0ALbzcWw5PYBtTg9gm9MD2Ob0ALY5PYBtTg9gm9MD2Ob0ALY5PYBtTg9gm9MD2Ob0ALY5PYBtTg9g+2rKp7A2pwewzekBbHN6ANucHsA2pwewzekBbHN6ANucHsD2jRzbmzi2N3Nsb+HY3sqxvY1jy+mla3N66dqlObacXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla9fk2HJ66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5eunc6x5fTStTm9dG1OL12b00vX5vTStTm9dG1OL12b00vX5vTStTm9dG3Ot9xtTi9dm9NL1+b00rU5vXRtTi9dm9NL1+b00rU5vXRtTi9dm9NL1+b00rU5vXRtTi9dm9NL1+b00rU5vXRtTi9dm9NL1+b00rU5vXTtTI4tp5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dpzOLacXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p/2Mzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66drrObacXro2p5euzemla3N66dqcXro2p5euvYVjy+mla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla3N66dqcXro2p5euzemla5/i2P7Asf2RY/sTx5bT/9bm9L+1Of1vbU7/W5vT/9bm9L+1Of1vbU7/W5vT/9bm9L+1Of1vbU7/Wxen/62L0//Wxel/6+L0v3Vx+t+6OP1vXZz+ty5O/1sXp/+ti9P/1sXpf+vi9L91cfrfujj9b12c/rcuTv9bF6f/rYvT/9aVj2PL6X/r4vS/dXH637o4/W9dnP63Lk7/Wxen/62L0//Wxel/6+L0v3Vx+t+6OP1vXZz+ty5O/1vX1RxbTv9bF6f/rYvT/9bF6X/r4vS/dXH637o4/W9dnP63Lk7/Wxen/62L0//Wxel/6+L0v3Vx+t+6OP1vXZz+t67SHFtO/1sXp/+ti9P/1sXpf+vi9L91cfrfujj9b12c/rcuTv9bF6f/rYvT/9bF6X/r4vS/dXH637o4/W9dnP63Lk7/Wxen/62L0//Wxel/6+L0v3Vx+t+6OP1vXZz+ty5O/1sXp/+ti9P/1sXpf+vi9L91cfrfujj9b101Obac/rcuTv9bF6f/rYvT/9bF6X/r4vS/dXH637o4/W9dnP63Lk7/Wxen/62L0//Wxel/6+L0v3Vx+t+6OP1vXZz+ty5O/1sXp/+ti9P/1sXpf+vi9L91cfrfujj9b12c/rcuTv9bF6f/rYvT/9YVdf/bzEz132y8Hpoa6pFbtWnL1umdKrVq3m5I3D5XhRtvuvmWW28rWar07Xfcedfd99x73/0PPPjQw4+UefSxsuXKV6hYqXKVx6tWq17jiZq1atd5su5TTz/zbL3nnq/foGGjxk2avtDsxeYvvdyiZavWbV5Jb9uufYdXO3Z67fU33nyrs6+Lr6uvm6+7r4evp6+Xr7evj6+vr5+vv2+Ab6BvkG+wL8Pn9WX6hviG+ob5hvtG+Eb6RvlG+8b4xvrG+cb7Jvgm+ib53vZN9k3xTfVN873jm+6b4Zvpe9f3nu993we+D32zfLN9c3xzfR/5PvbN8833LfAt9H3iW+Rb7FviW+r71LfM95lvuW+Fb6Xvc98q32rfGt9a3zrfep/PJ3wbfBt9m3ybfVt8W33bfNt9O3w7fbt8u317fHt9+3z7fQd8B32HfId9R3xHfV/4vvQd8x33feX72nfCd9L3je9b33e+732nfD/4fvT95DvtO+P72feL71ffb77ffX/4/vT95fvb94+w4oRlCcsWlktY8cLKJSy3sBKElSisJGElCytFWKnCyi0sj7DShJVHWHmFlU9Y+YVVQFiXCOtSYV0mrILCKiSsy4V1hbAKC+tKYV0lrCLCKiqsq4V1jbCuFdZ1wrpeWDcIq5iwigurhLBuFNZNwrpZWLcI61Zh3SasksIqJazSwrpdWHcI605h3SWsu4V1j7DuFdZ9wrpfWA8I60FhPSSsh4X1iLDKCOtRYT0mrLLCKies8sKqIKyKwqokrMrCqiKsx4VVVVjVhFVdWDWE9YSwagqrlrBqC6uOsJ4UVl1hPSWsp4X1jLCeFVY9YT0nrOeFVV9YDYTVUFiNhNVYWE2E1VRYLwirmbBeFFZzYb0krJeF1UJYLYXVSlithdVGWK8IK11YbYXVTljthdVBWK8Kq6OwOgnrNWG9Lqw3hPWmsN4SVmdhdRFWV2F1E1Z3YfUQVk9h9RJWb2H1EVZfYfUTVn9hDRDWQGENEtZgYWUIyyusTGENEdZQYQ0T1nBhjRDWSGGNEtZoYY0R1lhhjRPWeGFNENZEYU0S1tvCmiysKcKaKqxpwnpHWNOFNUNYM4X1rrDeE9b7wvpAWB8Ka5awZgtrjrDmCusjYX0srHnCmi+sBcJaKKxPhLVIWIuFtURYS4X1qbCWCeszYS0X1gphrRTW58JaJazVwlojrLXCWies9cLyCUsIa4OwNgprk7A2C2uLsLYKa5uwtgtrh7B2CmuXsHYLa4+w9gprn7D2C+uAsA4K65CwDgvriLCOCusLYX0prGPCOi6sr4T1tbBOCOuksL4R1rfC+k5Y3wvrlLB+ENaPwvpJWKeFdUZYPwvrF2H9KqzfhPW7sP4Q1p/C+ktYfwvrH2HHCdsSti1sl7DjhZ1L2G5hJwg7UdhJwk4WdoqwU4WdW9geYacJO4+w8wo7n7DzC7uAsC8R9qXCvkzYBYVdSNiXC/sKYRcW9pXCvkrYRYRdVNhXC/saYV8r7OuEfb2wbxB2MWEXF3YJYd8o7JuEfbOwbxH2rcK+TdglhV1K2KWFfbuw7xD2ncK+S9h3C/seYd8r7PuEfb+wHxD2g8J+SNgPC/sRYZcR9qPCfkzYZYVdTtjlhV1B2BWFXUnYlYVdRdiPC7uqsKsJu7qwawj7CWHXFHYtYdcWdh1hPynsusJ+SthPC/sZYT8r7HrCfk7Yzwu7vrAbCLuhsBsJu7Gwmwi7qbBfEHYzYb8o7ObCfknYLwu7hbBbCruVsFsLu42wXxF2urDbCrudsNsLu4OwXxV2R2F3EvZrwn5d2G8I+01hvyXszsLuIuyuwu4m7O7C7iHsnsLuJezewu4j7L7C7ifs/sIeIOyBwh4k7MHCzhC2V9iZwh4i7KHCHibs4cIeIeyRwh4l7NHCHiPsscIeJ+zxwp4g7InCniTst4U9WdhThD1V2NOE/Y6wpwt7hrBnCvtdYb8n7PeF/YGwPxT2LGHPFvYcYc8V9kfC/ljY84Q9X9gLhL1Q2J8Ie5GwFwt7ibCXCvtTYS8T9mfCXi7sFcJeKezPhb1K2KuFvUbYa4W9Ttjrhe0TthD2BmFvFPYmYW8W9hZhbxX2NmFvF/YOYe8U9i5h7xb2HmHvFfY+Ye8X9gFhHxT2IWEfFvYRYR8V9hfC/lLYx4R9XNhfCftrYZ8Q9klhfyPsb4X9nbC/F/YpYf8g7B+F/ZOwTwv7jLB/FvYvwv5V2L8J+3dh/yHsP4X9l7D/FvY/whUnXP7vRQuXS7jihSuXcLmFK0G4EoUrSbiShStFuFKFK7dweYQrTbjyCFde4conXPmFq4BwXSJclwrXZcJVULgKCdflwnWFcBUWriuF6yrhKiJcRYXrauG6RriuFa7rhOt64bpBuIoJV3HhKiE/95ef0cvP0+Vn3/JzavmZsvz8V35WKz9XlZ+Bys8r5WeL8nNA+Zmd/HxNfhYmP7eSnzHJz4PkZzfycxb5mYj8/EJ+1iA/F5DP8OXzdvlsXD7Hls+c5fNh+SxXPneVz0jl80z57FE+J5TP9OTzN/msTD7Xks+g5PMi+WxHPoeRz0zk8w35LEI+N5Dv8eX7cfneWb7Ple9J5ftH+V5Pvi+T76Hk+x353kS+j5Cv+eXrc/laWr7ula9R5etJ+dpPvk6Tr6nka5uZNZu2a5/eqmzDdg33xd0YZ9mu+FzuhMSk5JTU3J60PHnz5S9wyaWXFSx0+RWFr7yqSNGrr7n2uutvKFa8REbGvriSmV2nlGncPL1g5sZNCSdPr1/VLCPj/I8uz/mjBzI37l1xU80d5dxFAj96MOePHsr5I1nvQv3QFeqH8SF+6Pomc+PIbwpMTR2T+5ngD38M9cNfQ/3w7xA/jI8P9cPkUD/ME+qHl4b64f0hFh//QKgfhgiccFuhfhgqdO5QoUtYHeqHa0L9cG2IHyYNDPXDQaF+ODjED1Nqhfph7VA/rBPih7kLhfrh5aF+eEWIH6Y9GOI40h4L9cNKoX5YPdQP64T64bOhftgw1A+bhfqhjOe77w1u8maXNV0v/DDP05kbn12U/PvwGmvGBX9YP+cFFHleDPXDl0P9sKXjh2MydxdvePadVf3GrVu2adiueaMWTeu3Tm/YWP6fDk3T2zZv3ar+q+kN27Rpmr4vLk/XqY+1btW23ZCu08o2T2/auJ3d9Z1Krdo1bdY0fXKd20ur33Bl//dWVP++S7ns/z4uuvnLdZ3yWMMWLbwpF3ym12zaQm66Q9ModxKX08EVrcN7/rU0kcX5sdZtOl3YUjnnmhzm51buueiVlzOw8im12rVu480Ms9JsZ/TY1PLNm7ZQP6C7Kvs/LAv+w7hp5zjX9d3yrdObNm/Wyh+pYTKvX2vXtHH9ls3bNq5/LsUfu5Dh1c8m+JPn8tt/Nd4/9x6/TJMm6U3btr2w9DA/L5vZdVqt5i3btGh6bolZ/9v55WTOa9S+eYsm9Vu2bVa/UYvWjV+u/2LTFv5rZNX4L1+jsRd5jcaeT8YXcqZSruicyud0cJu5RuWda3KYy5U7Nl4+OAjM+nade7KJKgQH4UUVg4PwokrBQXhR5eAgvKhKcBBe9HhwEF5UNTgIL6oWHIQXVQ8OwotqBAfhRU8EB+FFNYOD8KJawUF4Ue3gILyoTnAQXvRkcBBeVDc4CC96KjgIL3o6OAgveiY4CC96NjgIL6oXHIQXPRcchBc9HxyEF9UPDsKLGgQH4UUNg4PwokbBQXhR4+AgvKhJcBBe1DQ4CC96ITgIL2oWHIQXvRgchBc1Dw7Ci14KDsKLXg4OwotaBAfhRS2Dg/CiVsFBeFHr4CC8qE1wEF70SnAQXpQeHIQXtQ0OwovaBQfhRe2Dg/CiDsFBeNGrwUF4UcfgILyoU3AQXvRacBBe9HpwEF70RnAQXvRmcBBe9FZwEF7UOTgIL/J1cYwiyLo6RhFk3RyjCLLujlEEWQ/HKIKsp2MUQdbLMYog6+0YRZD1cYwiyPo6RhFk/Rwj5+vL7Lr+jlEW3cW+7br4V7plu06u2rpDpvN17fm1Wjm9E6J9U/juo81bNfR/yNmuepthF4wnyzc+Z7d/YSbHDO9XatXk7E8v8k2AlW3y4BQXps+5Z/t8NM7/V5fzYLL8L/HOJWf5X7K/L5DvaF7KHmPbOXW2/83lyKls/1O8I43OObcPt0lXzk3awU3mONj46GI74KLfouUJG2hX2EDHhw10rguBvtinEAMuOjZ5cj7HcDnNsj/HiM49x3OQstH9+xzzl4vu3z9y4alIqJudkP1mu4KHleXsEoOCLD9PCh77lMrtW7bxpned8njrhk0uCNxBh6kyzOlNc/5Td+i1JWZfW2LwPoT8B0nZ/0GS4h8kT39cPs2p/WLDViGnSeg6zb+lSi9cWHJyq0A0L/55RbZSkRChiidG5503+iqeGL6KJxiq4ok5C1xChAKXFO0lDjNtUs5pk5z7znYMyc7/7VxGy1digcwNJXOHmzk558zJ4RLygiIla0qGmjApmJbBf9Y5bNjDGGYpcTkNE+WLt/Pb75PzBYcTmOdEI6OIf3ywlIUL3QeBRZd7pX3DFm2z//uIsUj2DThPF2HdGnYGdVhCew8O7Hho+ESv1b5RhGCHCxS6Z1eIdSX5hlzYc6nACodnP7jEYODDSXKFyP9ozjZXEHNaZ5tLFf+xjrPNUTSSDdWqlJxHmOScJcw/S424NcUVTvVNchxh2IiXbd4hq21KMOI54pES7VuLHA6pjndTpaL4ROKCQW7n2zGdz9M80e0hMadDWnQOIWCUR++1cqj77855KR08PH/j3g13/m69suX2fXDeWlg3h3+bVbV9i+y2qtucL2dCJij/Ud5poe5HvsglLq9v7oX7cUdY5zDxSchSoUJ4zwuE/rOw1qFA5pggXIDQsp43xLry+T5RoyxfmD3nzVIjQngvueB9d/jjjfSuNFyS5vxH+ZzLOv8GwXElcr6eWJH9mridJeWC6Pxjm1DzZH1BHsVaE4BKnz/iqSY4V5Ez8vl9a9Snmj/MqbojZ3J+3/pAdHaEtY6YyWFfzxZAMzl/iHUV8G1U7zlcdcsfOZPdvi3qTHbrZHKIO+92Lit7JufNkubnjmFX9kzOGyKTd+VkziXRMado2GMLE1SPc6pQB7bvQlDvC59JtV5sEfameyJdz7zQ9QxxAPmddlqpmj9y0S3gOwIU3Yh1I+2i60a+kHf7mH7dyKeqG18HcvG0Xt3IR6ob3+oTML+KgKf+KwTMDxHwZ4SAP/8L68bvWnUjb6S6kdcA1rPc+outG6GwXkBYcepczRvhMdhjF102QtWz/MKKV68rQf0qMlTdSBBWwoW3Fvmi+AQnHjiO/GjlSAi97RTgONRvGEKVjrzC8qhrR16d2hGi4OR1rit77cjnHAZOokD24pEvZ/Hwq3JUj/yGqkdedfXIHzquBdXlIyFn+XBHKh9uZxw0X3YkAK+Q813MNc0nrKv0XyI7HgDkCfUSWVhXO/I13Ed5idk/bIqP9pOHwBwP5qTXhQ+W8CLh1rktCc6o5Hhynw+oOyFW4ghScoSnOwkRnu64g093wn+6nBj4gCn75zEXPrMJHshdEbonBr7Z33VK7fSG/s82L/z7QEQNTXTF4qabHt53Yh99olzxV4wq+mGDx+kTfZFYo5z98YAi9Imq3D/qtW7Lj9VWTxTmI1VXmA91nY/Xsv8bO8eHmhLh1bJ/UH9hJegniRfqBfbJrCv4D7LMnBzmY+aU4NIC8KqcLSqJQY9sHzSnBCWhPwbOvrpkxefGKdn/QYriH6SG/KA52fE5dbYzSRVW+XDpFfXXagIRqx7mlF3K31T45r/7mwpd77m431Sw7rnAJfuivwhzJPa7CrHfVYj9rkLsdxViv6sQ+12F2O8qxH5XIfa7CrHfVTj3P/J/VyGELNSvKoSQDXCMIsgGOkYRZIMcowiywY5RBFmGYxRB5nWMIsgyHaMIMucogmyoYxRBNswxiiAb7hhFkI1wjCLIRjpGEWSjHKMIstGOUQTZGMcogmysYxRBNs4xiiAb7xhFkE1wjCLIJjpGEWSTHKMIsrcdowiyyY5RBNkUxyiCbKpjFEE2zTGKIHvHMYogm+4YRZDNcIwiyGY6RhFk7zpGEWTvOUYRZO87RhFkHzhGEWQfOkYRZLMcowiy2Y5RBNkcxyiCbK5jFEH2kWMUQfaxYxRBNs8xiiCb7xhFkC1wjCLIFjpGEWSfOEYRZIscowiyxY5RBNkSxyiCbKljFEH2qWMUQbbMMYog+8wxiiBb7hhFkK1wjCLIVjpGEWSfO0YRZKscowiy1Y5RBNkaxyiCbK1jFEG2zjGKIFvvGEWQ+RyjCDLhGEWQbXCMIsg2OkYRZJscowiyzY5RBNkWxyiCbKtjFEG2zTGKINvuGEWQ7XCMIsh2OkYRZLscowiy3Y5RBNkexyiCbK9jFEG2zzGKINvvGEWQHXCMIsgOOkYRZIccowiyw45RBNkRxyiC7KhjFEH2hWMUQfalYxRBdswxiiA77hhFkH3lGEWQfe0YRZCdcIwiyE46RhFk3zhGEWTfOkYRZN85RhFk3ztGEWSnHKMIsh8cowiyHx2jCLKfHKMIstOOUQTZGccoguxnxyiC7BfHKILsV8coguw3xyiC7HfHKILsD8coguxPxyiC7C/HKILsb8coguwfxyi8zP89QscwktByDiMJbecwktDlHEYSxjuHkYS5nMNIQrdzGEmY4BxGEiY6h5GESc5hJGGycxhJmOIcRhKmOoeRhLmdw0hCj3MYSZjmHEYS5nEOIwnzOoeRhPmcw0jC/M5hJGEB5zCS8BLnMJLwUucwkvAy5zCSsKBzGElYyDmMJLzcOYwkvMI5jCQs7BxGEl7pHEYSXuUcRhIWcQ4jCYs6h5GEVzuHkYTXOIeRhNc6h5GE1zmHkYTXO4eRhDc4hwFhiO5FwirmHGZR/vf7Fx0i9i86HOtfdP57Tm6tDkb+xArXwsifSgH3vP+VLkZW8X9pFyN/uC+yj1GovcX6GDn+85/uY3T2Fzz+D3cykq9fY72MFJP/3+tl5H+p9u9vZuR/iWq4nZH/ZV0gBNcBDY0i9Jj4L3Q0EhIPAdSsM93SSFg3Xdh0yX9VUyNh3XZh2+LCGksr2xqF0OQKdReiOWJ2YyPh+JL6uv9jnY38vw4WPMf/SmujQ7HWRnH/htZGwqpgurfR2V8FOm++5n+1uZH/t3MCV2ST6e5Gwqp5IULP/av6GwnrSTXYdBscCevpC+Zb/20djoRVH2jw4Fedf7gTaqZ/cY8jYTVRn6xukyNhNbsQoPR/VZsjYb2s3rZunyNhtVIn9H+r0ZGw2gGdjvyqf13LEmF1vBDXHf9/9ToS1ltAAf5vNDsSVjf9ApJPWUB6XkjIjH9VvyNh9dUnoqrhkbAG/FeImB8jYiZExMx/YwEZrlVA/k80PRqrztf/StOjiep16Tc9mnwhHT/4lzU9egc4Du2mRzPV5eO/1/RoFtT0aNa/senRR+ry8X+16dEn+q+X1U2Pljjyld/0aHes6dH5iIaAe4VY1yONiWJdj3J8/Gqs69GJ/8GuR8f+j3c9OmK869FJVdejT5s1bVe/Ran67VrXb1G6fsumLRs1TW/7YvM29V9t3q6V3MC+uBL/5T/U/PJF/qHmly/6ezMuWtOjx5xrcpjngMUFfbgvL5UN+9WlwN97vyRrKpR32oehYnwoKob/pD/KsFa46LBeF/ZlTXzYLzTlUn5/7KqL/jJS+YuOzfU5v84UYg85XzVd/LcIrzf6LUJ3tLVC75Vilr95f925v3nfvl2L+rK4PV6qduvHS1e9UNjqnqtrOf7avSO4Myo2bdimTHp6w07Ot73XZf9791PPSbxZf3zdkLDOdtj/xRX2f4kfkm3WSP8tqm89BgP5H/5y2Q3/p79adk2ArLuvb9W6XfMXOv2/9s6fp3EYDONJGpWj3HjohhsO3Z10y32LVlcmqEBitdxgqKWQFicp5VuUTjDAgliQkBAbfBY+DHbTxIljhwQXEKhbpcZ/Yj/v+/xS2ylwCIIB2gVe6Lp4DyMC+gQ6LgID0h8dn7+zvbY07bWl/SeWpna+LWGvEm+Q2WvkACvaO8X1R8XIO4CVriyb89ainDcgQxCprhmJbiPW3Hh8os5LQgpLFPzXZ+EIsAfQCDlhgPsecKDTQ7GCj+hDDHtHJnWN91VxW1PFbW0N2tqeX0LFGQbQ1WhzDmCsgk5Tm+3s6hxSV3OIPScOqRdsf3zJaYb6s9vrvxe4uq18HPg/K/1LWyXt189kb4MdPz81dvyQQ1zRo5ylAOh77iU+Ctah3+vQLw/gPhqPJ3I4ttUAW5soQLmmMJ21IXQxTYKUj8Kuix3qOFFSjN1mQUwLYpLfUxVi+s1VDn0fkWCHya4zlVw8NC+Cpn8z7CdoSGvFXQb6Pegj4AeQBAI5XSy0/OZazp4XbfIPmXXC5xT/9cMp/o/4jLCVKLTDBLrN9FlO8pluxsq/i9CLXsh+TSZwF48e6frgldZP2YZYvq4ZIEtVEVcuLiPlxfGNZYVlykNS7E/F41GNkri0zFu/iQpMs9TmIHmlZ+161m4LD3N3ZalK2WwreY7JCi7fDru52m0lcdlVAUoAaIN3TY5uUrBaVoPVlyXtCYtjNDczk1seMdhjsXgmNraqqfZv80mlBu9PUrFoXJENlmhCpcfZEqZEi+Kk1HK7FsySrSujwbhMhYHJ+yBMXvKejdXJQ3rypkMMDkOaV5EXnIrdq3iAyRLLr8x5Ghu8YsV4WEXZQTmKZjo7WCUul2UHUxHSljgZyRJs4wmxt2UD7jQLAA==",
|
|
6631
7035
|
"custom_attributes": [
|
|
6632
7036
|
"abi_private"
|
|
6633
7037
|
],
|
|
6634
|
-
"debug_symbols": "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",
|
|
7038
|
+
"debug_symbols": "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",
|
|
6635
7039
|
"is_unconstrained": false,
|
|
6636
7040
|
"name": "claim_and_end_setup",
|
|
6637
|
-
"verification_key": "
|
|
7041
|
+
"verification_key": "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"
|
|
6638
7042
|
},
|
|
6639
7043
|
{
|
|
6640
7044
|
"abi": {
|
|
@@ -6688,51 +7092,54 @@
|
|
|
6688
7092
|
"custom_attributes": [
|
|
6689
7093
|
"abi_public"
|
|
6690
7094
|
],
|
|
6691
|
-
"debug_symbols": "
|
|
7095
|
+
"debug_symbols": "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",
|
|
6692
7096
|
"is_unconstrained": true,
|
|
6693
7097
|
"name": "public_dispatch"
|
|
6694
7098
|
}
|
|
6695
7099
|
],
|
|
6696
7100
|
"name": "FeeJuice",
|
|
6697
|
-
"noir_version": "1.0.0-beta.
|
|
7101
|
+
"noir_version": "1.0.0-beta.25+75061fab15986eedee4e7d9104ff87dd9fa4ca10",
|
|
6698
7102
|
"outputs": {
|
|
6699
7103
|
"globals": {
|
|
6700
7104
|
"storage": [
|
|
6701
7105
|
{
|
|
6702
|
-
"
|
|
6703
|
-
|
|
6704
|
-
|
|
6705
|
-
|
|
6706
|
-
"
|
|
6707
|
-
"value":
|
|
6708
|
-
|
|
6709
|
-
|
|
6710
|
-
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
"
|
|
6714
|
-
|
|
6715
|
-
|
|
6716
|
-
|
|
6717
|
-
"
|
|
6718
|
-
|
|
6719
|
-
|
|
6720
|
-
|
|
6721
|
-
"
|
|
6722
|
-
"
|
|
6723
|
-
|
|
7106
|
+
"name": "STORAGE_LAYOUT_FeeJuice",
|
|
7107
|
+
"value": {
|
|
7108
|
+
"fields": [
|
|
7109
|
+
{
|
|
7110
|
+
"name": "contract_name",
|
|
7111
|
+
"value": {
|
|
7112
|
+
"kind": "string",
|
|
7113
|
+
"value": "FeeJuice"
|
|
7114
|
+
}
|
|
7115
|
+
},
|
|
7116
|
+
{
|
|
7117
|
+
"name": "fields",
|
|
7118
|
+
"value": {
|
|
7119
|
+
"fields": [
|
|
7120
|
+
{
|
|
7121
|
+
"name": "balances",
|
|
7122
|
+
"value": {
|
|
7123
|
+
"fields": [
|
|
7124
|
+
{
|
|
7125
|
+
"name": "slot",
|
|
7126
|
+
"value": {
|
|
7127
|
+
"kind": "integer",
|
|
7128
|
+
"sign": false,
|
|
7129
|
+
"value": "0000000000000000000000000000000000000000000000000000000000000001"
|
|
7130
|
+
}
|
|
6724
7131
|
}
|
|
6725
|
-
|
|
6726
|
-
|
|
6727
|
-
|
|
7132
|
+
],
|
|
7133
|
+
"kind": "struct"
|
|
7134
|
+
}
|
|
6728
7135
|
}
|
|
6729
|
-
|
|
6730
|
-
|
|
6731
|
-
|
|
7136
|
+
],
|
|
7137
|
+
"kind": "struct"
|
|
7138
|
+
}
|
|
6732
7139
|
}
|
|
6733
|
-
|
|
6734
|
-
|
|
6735
|
-
|
|
7140
|
+
],
|
|
7141
|
+
"kind": "struct"
|
|
7142
|
+
}
|
|
6736
7143
|
}
|
|
6737
7144
|
]
|
|
6738
7145
|
},
|
|
@@ -6941,5 +7348,5 @@
|
|
|
6941
7348
|
}
|
|
6942
7349
|
},
|
|
6943
7350
|
"transpiled": true,
|
|
6944
|
-
"aztec_version": "0.0.1-commit.
|
|
7351
|
+
"aztec_version": "0.0.1-commit.321f6a9"
|
|
6945
7352
|
}
|