1pub mod prelude {
2 pub use crate::compression::{
3 alt_bn128_compression_size::*, consts::*, target_arch::*, AltBn128CompressionError,
4 };
5}
6
7use thiserror::Error;
8
9mod consts {
10 pub const ALT_BN128_G1_COMPRESS: u64 = 0;
11 pub const ALT_BN128_G1_DECOMPRESS: u64 = 1;
12 pub const ALT_BN128_G2_COMPRESS: u64 = 2;
13 pub const ALT_BN128_G2_DECOMPRESS: u64 = 3;
14}
15
16mod alt_bn128_compression_size {
17 pub const G1: usize = 64;
18 pub const G2: usize = 128;
19 pub const G1_COMPRESSED: usize = 32;
20 pub const G2_COMPRESSED: usize = 64;
21}
22
23#[derive(Debug, Error, Clone, PartialEq, Eq)]
26pub enum AltBn128CompressionError {
27 #[error("Unexpected error")]
28 UnexpectedError,
29 #[error("Failed to decompress g1")]
30 G1DecompressionFailed,
31 #[error("Failed to decompress g2")]
32 G2DecompressionFailed,
33 #[error("Failed to compress affine g1")]
34 G1CompressionFailed,
35 #[error("Failed to compress affine g2")]
36 G2CompressionFailed,
37 #[error("Invalid input size")]
38 InvalidInputSize,
39}
40
41impl From<u64> for AltBn128CompressionError {
42 fn from(v: u64) -> AltBn128CompressionError {
43 match v {
44 1 => AltBn128CompressionError::G1DecompressionFailed,
45 2 => AltBn128CompressionError::G2DecompressionFailed,
46 3 => AltBn128CompressionError::G1CompressionFailed,
47 4 => AltBn128CompressionError::G2CompressionFailed,
48 5 => AltBn128CompressionError::InvalidInputSize,
49 _ => AltBn128CompressionError::UnexpectedError,
50 }
51 }
52}
53
54impl From<AltBn128CompressionError> for u64 {
55 fn from(v: AltBn128CompressionError) -> u64 {
56 match v {
58 AltBn128CompressionError::G1DecompressionFailed => 1,
59 AltBn128CompressionError::G2DecompressionFailed => 2,
60 AltBn128CompressionError::G1CompressionFailed => 3,
61 AltBn128CompressionError::G2CompressionFailed => 4,
62 AltBn128CompressionError::InvalidInputSize => 5,
63 AltBn128CompressionError::UnexpectedError => 6,
64 }
65 }
66}
67
68#[cfg(not(target_os = "solana"))]
69mod target_arch {
70
71 use {
72 super::*,
73 crate::compression::alt_bn128_compression_size,
74 ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Compress, Validate},
75 };
76
77 type G1 = ark_bn254::g1::G1Affine;
78 type G2 = ark_bn254::g2::G2Affine;
79
80 pub fn alt_bn128_g1_decompress(
81 g1_bytes: &[u8],
82 ) -> Result<[u8; alt_bn128_compression_size::G1], AltBn128CompressionError> {
83 let g1_bytes: [u8; alt_bn128_compression_size::G1_COMPRESSED] = g1_bytes
84 .try_into()
85 .map_err(|_| AltBn128CompressionError::InvalidInputSize)?;
86 if g1_bytes == [0u8; alt_bn128_compression_size::G1_COMPRESSED] {
87 return Ok([0u8; alt_bn128_compression_size::G1]);
88 }
89 let decompressed_g1 = G1::deserialize_with_mode(
90 convert_endianness::<32, 32>(&g1_bytes).as_slice(),
91 Compress::Yes,
92 Validate::No,
93 )
94 .map_err(|_| AltBn128CompressionError::G1DecompressionFailed)?;
95 let mut decompressed_g1_bytes = [0u8; alt_bn128_compression_size::G1];
96 decompressed_g1
97 .x
98 .serialize_with_mode(&mut decompressed_g1_bytes[..32], Compress::No)
99 .map_err(|_| AltBn128CompressionError::G1DecompressionFailed)?;
100 decompressed_g1
101 .y
102 .serialize_with_mode(&mut decompressed_g1_bytes[32..], Compress::No)
103 .map_err(|_| AltBn128CompressionError::G1DecompressionFailed)?;
104 Ok(convert_endianness::<32, 64>(&decompressed_g1_bytes))
105 }
106
107 pub fn alt_bn128_g1_compress(
108 g1_bytes: &[u8],
109 ) -> Result<[u8; alt_bn128_compression_size::G1_COMPRESSED], AltBn128CompressionError> {
110 let g1_bytes: [u8; alt_bn128_compression_size::G1] = g1_bytes
111 .try_into()
112 .map_err(|_| AltBn128CompressionError::InvalidInputSize)?;
113 if g1_bytes == [0u8; alt_bn128_compression_size::G1] {
114 return Ok([0u8; alt_bn128_compression_size::G1_COMPRESSED]);
115 }
116 let g1 = G1::deserialize_with_mode(
117 convert_endianness::<32, 64>(&g1_bytes).as_slice(),
118 Compress::No,
119 Validate::No,
120 )
121 .map_err(|_| AltBn128CompressionError::G1CompressionFailed)?;
122 let mut g1_bytes = [0u8; alt_bn128_compression_size::G1_COMPRESSED];
123 G1::serialize_compressed(&g1, g1_bytes.as_mut_slice())
124 .map_err(|_| AltBn128CompressionError::G1CompressionFailed)?;
125 Ok(convert_endianness::<32, 32>(&g1_bytes))
126 }
127
128 pub fn alt_bn128_g2_decompress(
129 g2_bytes: &[u8],
130 ) -> Result<[u8; alt_bn128_compression_size::G2], AltBn128CompressionError> {
131 let g2_bytes: [u8; alt_bn128_compression_size::G2_COMPRESSED] = g2_bytes
132 .try_into()
133 .map_err(|_| AltBn128CompressionError::InvalidInputSize)?;
134 if g2_bytes == [0u8; alt_bn128_compression_size::G2_COMPRESSED] {
135 return Ok([0u8; alt_bn128_compression_size::G2]);
136 }
137 let decompressed_g2 = G2::deserialize_with_mode(
138 convert_endianness::<64, 64>(&g2_bytes).as_slice(),
139 Compress::Yes,
140 Validate::No,
141 )
142 .map_err(|_| AltBn128CompressionError::G2DecompressionFailed)?;
143 let mut decompressed_g2_bytes = [0u8; alt_bn128_compression_size::G2];
144 decompressed_g2
145 .x
146 .serialize_with_mode(&mut decompressed_g2_bytes[..64], Compress::No)
147 .map_err(|_| AltBn128CompressionError::G2DecompressionFailed)?;
148 decompressed_g2
149 .y
150 .serialize_with_mode(&mut decompressed_g2_bytes[64..128], Compress::No)
151 .map_err(|_| AltBn128CompressionError::G2DecompressionFailed)?;
152 Ok(convert_endianness::<64, 128>(&decompressed_g2_bytes))
153 }
154
155 pub fn alt_bn128_g2_compress(
156 g2_bytes: &[u8],
157 ) -> Result<[u8; alt_bn128_compression_size::G2_COMPRESSED], AltBn128CompressionError> {
158 let g2_bytes: [u8; alt_bn128_compression_size::G2] = g2_bytes
159 .try_into()
160 .map_err(|_| AltBn128CompressionError::InvalidInputSize)?;
161 if g2_bytes == [0u8; alt_bn128_compression_size::G2] {
162 return Ok([0u8; alt_bn128_compression_size::G2_COMPRESSED]);
163 }
164 let g2 = G2::deserialize_with_mode(
165 convert_endianness::<64, 128>(&g2_bytes).as_slice(),
166 Compress::No,
167 Validate::No,
168 )
169 .map_err(|_| AltBn128CompressionError::G2CompressionFailed)?;
170 let mut g2_bytes = [0u8; alt_bn128_compression_size::G2_COMPRESSED];
171 G2::serialize_compressed(&g2, g2_bytes.as_mut_slice())
172 .map_err(|_| AltBn128CompressionError::G2CompressionFailed)?;
173 Ok(convert_endianness::<64, 64>(&g2_bytes))
174 }
175
176 pub fn convert_endianness<const CHUNK_SIZE: usize, const ARRAY_SIZE: usize>(
177 bytes: &[u8; ARRAY_SIZE],
178 ) -> [u8; ARRAY_SIZE] {
179 let reversed: [_; ARRAY_SIZE] = bytes
180 .chunks_exact(CHUNK_SIZE)
181 .flat_map(|chunk| chunk.iter().rev().copied())
182 .enumerate()
183 .fold([0u8; ARRAY_SIZE], |mut acc, (i, v)| {
184 acc[i] = v;
185 acc
186 });
187 reversed
188 }
189}
190
191#[cfg(target_os = "solana")]
192mod target_arch {
193 use {
194 super::*,
195 alt_bn128_compression_size::{G1, G1_COMPRESSED, G2, G2_COMPRESSED},
196 prelude::*,
197 solana_program::syscalls,
198 };
199
200 pub fn alt_bn128_g1_compress(
201 input: &[u8],
202 ) -> Result<[u8; G1_COMPRESSED], AltBn128CompressionError> {
203 let mut result_buffer = [0; G1_COMPRESSED];
204 let result = unsafe {
205 syscalls::sol_alt_bn128_compression(
206 ALT_BN128_G1_COMPRESS,
207 input as *const _ as *const u8,
208 input.len() as u64,
209 &mut result_buffer as *mut _ as *mut u8,
210 )
211 };
212
213 match result {
214 0 => Ok(result_buffer),
215 _ => Err(AltBn128CompressionError::UnexpectedError),
216 }
217 }
218
219 pub fn alt_bn128_g1_decompress(input: &[u8]) -> Result<[u8; G1], AltBn128CompressionError> {
220 let mut result_buffer = [0; G1];
221 let result = unsafe {
222 syscalls::sol_alt_bn128_compression(
223 ALT_BN128_G1_DECOMPRESS,
224 input as *const _ as *const u8,
225 input.len() as u64,
226 &mut result_buffer as *mut _ as *mut u8,
227 )
228 };
229
230 match result {
231 0 => Ok(result_buffer),
232 _ => Err(AltBn128CompressionError::UnexpectedError),
233 }
234 }
235
236 pub fn alt_bn128_g2_compress(
237 input: &[u8],
238 ) -> Result<[u8; G2_COMPRESSED], AltBn128CompressionError> {
239 let mut result_buffer = [0; G2_COMPRESSED];
240 let result = unsafe {
241 syscalls::sol_alt_bn128_compression(
242 ALT_BN128_G2_COMPRESS,
243 input as *const _ as *const u8,
244 input.len() as u64,
245 &mut result_buffer as *mut _ as *mut u8,
246 )
247 };
248
249 match result {
250 0 => Ok(result_buffer),
251 _ => Err(AltBn128CompressionError::UnexpectedError),
252 }
253 }
254
255 pub fn alt_bn128_g2_decompress(
256 input: &[u8; G2_COMPRESSED],
257 ) -> Result<[u8; G2], AltBn128CompressionError> {
258 let mut result_buffer = [0; G2];
259 let result = unsafe {
260 syscalls::sol_alt_bn128_compression(
261 ALT_BN128_G2_DECOMPRESS,
262 input as *const _ as *const u8,
263 input.len() as u64,
264 &mut result_buffer as *mut _ as *mut u8,
265 )
266 };
267
268 match result {
269 0 => Ok(result_buffer),
270 _ => Err(AltBn128CompressionError::UnexpectedError),
271 }
272 }
273}
274
275#[cfg(test)]
276mod tests {
277 use {
278 super::*,
279 crate::compression::target_arch::convert_endianness,
280 ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Compress, Validate},
281 std::ops::Neg,
282 target_arch::{
283 alt_bn128_g1_compress, alt_bn128_g1_decompress, alt_bn128_g2_compress,
284 alt_bn128_g2_decompress,
285 },
286 };
287 type G1 = ark_bn254::g1::G1Affine;
288 type G2 = ark_bn254::g2::G2Affine;
289
290 #[test]
291 fn alt_bn128_g1_compression() {
292 let g1_be = [
293 45, 206, 255, 166, 152, 55, 128, 138, 79, 217, 145, 164, 25, 74, 120, 234, 234, 217,
294 68, 149, 162, 44, 133, 120, 184, 205, 12, 44, 175, 98, 168, 172, 20, 24, 216, 15, 209,
295 175, 106, 75, 147, 236, 90, 101, 123, 219, 245, 151, 209, 202, 218, 104, 148, 8, 32,
296 254, 243, 191, 218, 122, 42, 81, 193, 84,
297 ];
298 let g1_le = convert_endianness::<32, 64>(&g1_be);
299 let g1: G1 =
300 G1::deserialize_with_mode(g1_le.as_slice(), Compress::No, Validate::No).unwrap();
301
302 let g1_neg = g1.neg();
303 let mut g1_neg_be = [0u8; 64];
304 g1_neg
305 .x
306 .serialize_with_mode(&mut g1_neg_be[..32], Compress::No)
307 .unwrap();
308 g1_neg
309 .y
310 .serialize_with_mode(&mut g1_neg_be[32..64], Compress::No)
311 .unwrap();
312 let g1_neg_be: [u8; 64] = convert_endianness::<32, 64>(&g1_neg_be);
313
314 let points = [(g1, g1_be), (g1_neg, g1_neg_be)];
315
316 for (point, g1_be) in &points {
317 let mut compressed_ref = [0u8; 32];
318 G1::serialize_with_mode(point, compressed_ref.as_mut_slice(), Compress::Yes).unwrap();
319 let compressed_ref: [u8; 32] = convert_endianness::<32, 32>(&compressed_ref);
320
321 let decompressed = alt_bn128_g1_decompress(compressed_ref.as_slice()).unwrap();
322
323 assert_eq!(
324 alt_bn128_g1_compress(&decompressed).unwrap(),
325 compressed_ref
326 );
327 assert_eq!(decompressed, *g1_be);
328 }
329 }
330
331 #[test]
332 fn alt_bn128_g2_compression() {
333 let g2_be = [
334 40, 57, 233, 205, 180, 46, 35, 111, 215, 5, 23, 93, 12, 71, 118, 225, 7, 46, 247, 147,
335 47, 130, 106, 189, 184, 80, 146, 103, 141, 52, 242, 25, 0, 203, 124, 176, 110, 34, 151,
336 212, 66, 180, 238, 151, 236, 189, 133, 209, 17, 137, 205, 183, 168, 196, 92, 159, 75,
337 174, 81, 168, 18, 86, 176, 56, 16, 26, 210, 20, 18, 81, 122, 142, 104, 62, 251, 169,
338 98, 141, 21, 253, 50, 130, 182, 15, 33, 109, 228, 31, 79, 183, 88, 147, 174, 108, 4,
339 22, 14, 129, 168, 6, 80, 246, 254, 100, 218, 131, 94, 49, 247, 211, 3, 245, 22, 200,
340 177, 91, 60, 144, 147, 174, 90, 17, 19, 189, 62, 147, 152, 18,
341 ];
342 let g2_le = convert_endianness::<64, 128>(&g2_be);
343 let g2: G2 =
344 G2::deserialize_with_mode(g2_le.as_slice(), Compress::No, Validate::No).unwrap();
345
346 let g2_neg = g2.neg();
347 let mut g2_neg_be = [0u8; 128];
348 g2_neg
349 .x
350 .serialize_with_mode(&mut g2_neg_be[..64], Compress::No)
351 .unwrap();
352 g2_neg
353 .y
354 .serialize_with_mode(&mut g2_neg_be[64..128], Compress::No)
355 .unwrap();
356 let g2_neg_be: [u8; 128] = convert_endianness::<64, 128>(&g2_neg_be);
357
358 let points = [(g2, g2_be), (g2_neg, g2_neg_be)];
359
360 for (point, g2_be) in &points {
361 let mut compressed_ref = [0u8; 64];
362 G2::serialize_with_mode(point, compressed_ref.as_mut_slice(), Compress::Yes).unwrap();
363 let compressed_ref: [u8; 64] = convert_endianness::<64, 64>(&compressed_ref);
364
365 let decompressed = alt_bn128_g2_decompress(compressed_ref.as_slice()).unwrap();
366
367 assert_eq!(
368 alt_bn128_g2_compress(&decompressed).unwrap(),
369 compressed_ref
370 );
371 assert_eq!(decompressed, *g2_be);
372 }
373 }
374
375 #[test]
376 fn alt_bn128_compression_g1_point_of_infitity() {
377 let g1_bytes = vec![0u8; 64];
378 let g1_compressed = alt_bn128_g1_compress(&g1_bytes).unwrap();
379 let g1_decompressed = alt_bn128_g1_decompress(&g1_compressed).unwrap();
380 assert_eq!(g1_bytes, g1_decompressed);
381 }
382
383 #[test]
384 fn alt_bn128_compression_g2_point_of_infitity() {
385 let g1_bytes = vec![0u8; 128];
386 let g1_compressed = alt_bn128_g2_compress(&g1_bytes).unwrap();
387 let g1_decompressed = alt_bn128_g2_decompress(&g1_compressed).unwrap();
388 assert_eq!(g1_bytes, g1_decompressed);
389 }
390 #[test]
391 fn alt_bn128_compression_pairing_test_input() {
392 use serde_derive::Deserialize;
393
394 let test_data = r#"[
395 {
396 "Input": "1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f593034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf704bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a416782bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c2032c61a830e3c17286de9462bf242fca2883585b93870a73853face6a6bf411198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
397 "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
398 "Name": "jeff1",
399 "Gas": 113000,
400 "NoBenchmark": false
401 },{
402 "Input": "2eca0c7238bf16e83e7a1e6c5d49540685ff51380f309842a98561558019fc0203d3260361bb8451de5ff5ecd17f010ff22f5c31cdf184e9020b06fa5997db841213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f06967a1237ebfeca9aaae0d6d0bab8e28c198c5a339ef8a2407e31cdac516db922160fa257a5fd5b280642ff47b65eca77e626cb685c84fa6d3b6882a283ddd1198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
403 "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
404 "Name": "jeff2",
405 "Gas": 113000,
406 "NoBenchmark": false
407 },{
408 "Input": "0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd216da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba2e89718ad33c8bed92e210e81d1853435399a271913a6520736a4729cf0d51eb01a9e2ffa2e92599b68e44de5bcf354fa2642bd4f26b259daa6f7ce3ed57aeb314a9a87b789a58af499b314e13c3d65bede56c07ea2d418d6874857b70763713178fb49a2d6cd347dc58973ff49613a20757d0fcc22079f9abd10c3baee245901b9e027bd5cfc2cb5db82d4dc9677ac795ec500ecd47deee3b5da006d6d049b811d7511c78158de484232fc68daf8a45cf217d1c2fae693ff5871e8752d73b21198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
409 "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
410 "Name": "jeff3",
411 "Gas": 113000,
412 "NoBenchmark": false
413 },{
414 "Input": "2f2ea0b3da1e8ef11914acf8b2e1b32d99df51f5f4f206fc6b947eae860eddb6068134ddb33dc888ef446b648d72338684d678d2eb2371c61a50734d78da4b7225f83c8b6ab9de74e7da488ef02645c5a16a6652c3c71a15dc37fe3a5dcb7cb122acdedd6308e3bb230d226d16a105295f523a8a02bfc5e8bd2da135ac4c245d065bbad92e7c4e31bf3757f1fe7362a63fbfee50e7dc68da116e67d600d9bf6806d302580dc0661002994e7cd3a7f224e7ddc27802777486bf80f40e4ca3cfdb186bac5188a98c45e6016873d107f5cd131f3a3e339d0375e58bd6219347b008122ae2b09e539e152ec5364e7e2204b03d11d3caa038bfc7cd499f8176aacbee1f39e4e4afc4bc74790a4a028aff2c3d2538731fb755edefd8cb48d6ea589b5e283f150794b6736f670d6a1033f9b46c6f5204f50813eb85c8dc4b59db1c5d39140d97ee4d2b36d99bc49974d18ecca3e7ad51011956051b464d9e27d46cc25e0764bb98575bd466d32db7b15f582b2d5c452b36aa394b789366e5e3ca5aabd415794ab061441e51d01e94640b7e3084a07e02c78cf3103c542bc5b298669f211b88da1679b0b64a63b7e0e7bfe52aae524f73a55be7fe70c7e9bfc94b4cf0da1213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f",
415 "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
416 "Name": "jeff4",
417 "Gas": 147000,
418 "NoBenchmark": false
419 },{
420 "Input": "20a754d2071d4d53903e3b31a7e98ad6882d58aec240ef981fdf0a9d22c5926a29c853fcea789887315916bbeb89ca37edb355b4f980c9a12a94f30deeed30211213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f1abb4a25eb9379ae96c84fff9f0540abcfc0a0d11aeda02d4f37e4baf74cb0c11073b3ff2cdbb38755f8691ea59e9606696b3ff278acfc098fa8226470d03869217cee0a9ad79a4493b5253e2e4e3a39fc2df38419f230d341f60cb064a0ac290a3d76f140db8418ba512272381446eb73958670f00cf46f1d9e64cba057b53c26f64a8ec70387a13e41430ed3ee4a7db2059cc5fc13c067194bcc0cb49a98552fd72bd9edb657346127da132e5b82ab908f5816c826acb499e22f2412d1a2d70f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd2198a1f162a73261f112401aa2db79c7dab1533c9935c77290a6ce3b191f2318d198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
421 "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
422 "Name": "jeff5",
423 "Gas": 147000,
424 "NoBenchmark": false
425 },{
426 "Input": "1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f593034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf704bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a416782bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c103188585e2364128fe25c70558f1560f4f9350baf3959e603cc91486e110936198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
427 "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
428 "Name": "jeff6",
429 "Gas": 113000,
430 "NoBenchmark": false
431 },{
432 "Input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
433 "Expected": "0000000000000000000000000000000000000000000000000000000000000000",
434 "Name": "one_point",
435 "Gas": 79000,
436 "NoBenchmark": false
437 },{
438 "Input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d",
439 "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
440 "Name": "two_point_match_2",
441 "Gas": 113000,
442 "NoBenchmark": false
443 },{
444 "Input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
445 "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
446 "Name": "two_point_match_3",
447 "Gas": 113000,
448 "NoBenchmark": false
449 },{
450 "Input": "105456a333e6d636854f987ea7bb713dfd0ae8371a72aea313ae0c32c0bf10160cf031d41b41557f3e7e3ba0c51bebe5da8e6ecd855ec50fc87efcdeac168bcc0476be093a6d2b4bbf907172049874af11e1b6267606e00804d3ff0037ec57fd3010c68cb50161b7d1d96bb71edfec9880171954e56871abf3d93cc94d745fa114c059d74e5b6c4ec14ae5864ebe23a71781d86c29fb8fb6cce94f70d3de7a2101b33461f39d9e887dbb100f170a2345dde3c07e256d1dfa2b657ba5cd030427000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000021a2c3013d2ea92e13c800cde68ef56a294b883f6ac35d25f587c09b1b3c635f7290158a80cd3d66530f74dc94c94adb88f5cdb481acca997b6e60071f08a115f2f997f3dbd66a7afe07fe7862ce239edba9e05c5afff7f8a1259c9733b2dfbb929d1691530ca701b4a106054688728c9972c8512e9789e9567aae23e302ccd75",
451 "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
452 "Name": "two_point_match_4",
453 "Gas": 113000,
454 "NoBenchmark": false
455 },{
456 "Input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d",
457 "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
458 "Name": "ten_point_match_1",
459 "Gas": 385000,
460 "NoBenchmark": false
461 },{
462 "Input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
463 "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
464 "Name": "ten_point_match_2",
465 "Gas": 385000,
466 "NoBenchmark": false
467 },{
468 "Input": "105456a333e6d636854f987ea7bb713dfd0ae8371a72aea313ae0c32c0bf10160cf031d41b41557f3e7e3ba0c51bebe5da8e6ecd855ec50fc87efcdeac168bcc0476be093a6d2b4bbf907172049874af11e1b6267606e00804d3ff0037ec57fd3010c68cb50161b7d1d96bb71edfec9880171954e56871abf3d93cc94d745fa114c059d74e5b6c4ec14ae5864ebe23a71781d86c29fb8fb6cce94f70d3de7a2101b33461f39d9e887dbb100f170a2345dde3c07e256d1dfa2b657ba5cd030427000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000021a2c3013d2ea92e13c800cde68ef56a294b883f6ac35d25f587c09b1b3c635f7290158a80cd3d66530f74dc94c94adb88f5cdb481acca997b6e60071f08a115f2f997f3dbd66a7afe07fe7862ce239edba9e05c5afff7f8a1259c9733b2dfbb929d1691530ca701b4a106054688728c9972c8512e9789e9567aae23e302ccd75",
469 "Expected": "0000000000000000000000000000000000000000000000000000000000000001",
470 "Name": "ten_point_match_3",
471 "Gas": 113000,
472 "NoBenchmark": false
473 }
474 ]"#;
475
476 #[derive(Deserialize)]
477 #[serde(rename_all = "PascalCase")]
478 struct TestCase {
479 input: String,
480 }
481
482 let test_cases: Vec<TestCase> = serde_json::from_str(test_data).unwrap();
483
484 test_cases.iter().for_each(|test| {
485 let input = array_bytes::hex2bytes_unchecked(&test.input);
486 let g1 = input[0..64].to_vec();
487 let g1_compressed = alt_bn128_g1_compress(&g1).unwrap();
488 assert_eq!(g1, alt_bn128_g1_decompress(&g1_compressed).unwrap());
489 let g2 = input[64..192].to_vec();
490 let g2_compressed = alt_bn128_g2_compress(&g2).unwrap();
491 assert_eq!(g2, alt_bn128_g2_decompress(&g2_compressed).unwrap());
492 });
493 }
494}