Skip to content

Commit 5bdb82c

Browse files
committed
add alt_bn128 syscalls
1 parent fcbe528 commit 5bdb82c

File tree

5 files changed

+418
-0
lines changed

5 files changed

+418
-0
lines changed
Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
//! Compression/decompression of points on the BN254 curve.
2+
3+
use super::{ALT_BN128_G1_SIZE, ALT_BN128_G2_SIZE};
4+
use crate::program_error::ProgramError;
5+
6+
#[cfg(target_os = "solana")]
7+
use crate::syscalls::sol_alt_bn128_compression;
8+
9+
// compression sizes
10+
pub const ALT_BN128_G1_COMPRESSED_SIZE: usize = ALT_BN128_G1_SIZE / 2; // 32
11+
pub const ALT_BN128_G2_COMPRESSED_SIZE: usize = ALT_BN128_G2_SIZE / 2; // 64
12+
13+
// compression operations
14+
const ALT_BN128_G1_COMPRESS: u64 = 0;
15+
const ALT_BN128_G1_DECOMPRESS: u64 = 1;
16+
const ALT_BN128_G2_COMPRESS: u64 = 2;
17+
const ALT_BN128_G2_DECOMPRESS: u64 = 3;
18+
19+
/// Compress a G1 point on the BN254 curve.
20+
///
21+
/// # Arguments
22+
///
23+
/// * `input` - A G1 point in big-endian (EIP-197) encoding.
24+
///
25+
/// # Returns
26+
///
27+
/// A `Result` containing the compressed G1 point in big-endian (EIP-197) encoding,
28+
/// or an error if the input is not a valid G1 point.
29+
///
30+
/// Note: This function does **not** check if the input has the correct length.
31+
/// It will return an error if the length is invalid, incurring the cost of the syscall.
32+
#[inline(always)]
33+
pub fn alt_bn128_g1_compress(
34+
input: &[u8],
35+
) -> Result<[u8; ALT_BN128_G1_COMPRESSED_SIZE], ProgramError> {
36+
alt_bn128_compression(input, ALT_BN128_G1_COMPRESS)
37+
}
38+
39+
/// Compress a G1 point on the BN254 curve.
40+
///
41+
/// # Arguments
42+
///
43+
/// * `input` - A G1 point in big-endian (EIP-197) encoding.
44+
///
45+
/// # Returns
46+
///
47+
/// A `Result` containing the compressed G1 point in big-endian (EIP-197) encoding,
48+
/// or an error if the input is not a valid G1 point.
49+
///
50+
/// Note: This function checks if the input has the correct length,
51+
/// returning an error without incurring the cost of the syscall.
52+
pub fn checked_alt_bn128_g1_compress(
53+
input: &[u8],
54+
) -> Result<[u8; ALT_BN128_G1_COMPRESSED_SIZE], ProgramError> {
55+
if input.len() != ALT_BN128_G1_SIZE {
56+
return Err(ProgramError::InvalidArgument);
57+
}
58+
alt_bn128_compression(input, ALT_BN128_G1_COMPRESS)
59+
}
60+
61+
/// Decompress a G1 point on the BN254 curve.
62+
///
63+
/// # Arguments
64+
///
65+
/// * `input` - A compressed G1 point in big-endian (EIP-197) encoding.
66+
///
67+
/// # Returns
68+
///
69+
/// A `Result` containing the decompressed G1 point in big-endian (EIP-197) encoding,
70+
/// or an error if the input is not a valid compressed G1 point.
71+
///
72+
/// Note: This function does **not** check if the input has the correct length.
73+
/// It will return an error if the length is invalid, incurring the cost of the syscall.
74+
#[inline(always)]
75+
pub fn alt_bn128_g1_decompress(input: &[u8]) -> Result<[u8; ALT_BN128_G1_SIZE], ProgramError> {
76+
alt_bn128_compression(input, ALT_BN128_G1_DECOMPRESS)
77+
}
78+
79+
/// Decompress a G1 point on the BN254 curve.
80+
///
81+
/// # Arguments
82+
///
83+
/// * `input` - A compressed G1 point in big-endian (EIP-197) encoding.
84+
///
85+
/// # Returns
86+
///
87+
/// A `Result` containing the decompressed G1 point in big-endian (EIP-197) encoding,
88+
/// or an error if the input is not a valid compressed G1 point.
89+
///
90+
/// Note: This function checks if the input has the correct length,
91+
/// returning an error without incurring the cost of the syscall.
92+
pub fn checked_alt_bn128_g1_decompress(
93+
input: &[u8],
94+
) -> Result<[u8; ALT_BN128_G1_SIZE], ProgramError> {
95+
if input.len() != ALT_BN128_G1_COMPRESSED_SIZE {
96+
return Err(ProgramError::InvalidArgument);
97+
}
98+
alt_bn128_compression(input, ALT_BN128_G1_DECOMPRESS)
99+
}
100+
101+
/// Compress a G2 point on the BN254 curve.
102+
///
103+
/// # Arguments
104+
///
105+
/// * `input` - A G2 point in big-endian (EIP-197) encoding.
106+
///
107+
/// # Returns
108+
///
109+
/// A `Result` containing the compressed G2 point in big-endian (EIP-197) encoding,
110+
/// or an error if the input is not a valid G2 point.
111+
///
112+
/// Note: This function does **not** check if the input has the correct length.
113+
/// It will return an error if the length is invalid, incurring the cost of the syscall.
114+
#[inline(always)]
115+
pub fn alt_bn128_g2_compress(
116+
input: &[u8],
117+
) -> Result<[u8; ALT_BN128_G2_COMPRESSED_SIZE], ProgramError> {
118+
alt_bn128_compression(input, ALT_BN128_G2_COMPRESS)
119+
}
120+
121+
/// Compress a G2 point on the BN254 curve.
122+
///
123+
/// # Arguments
124+
///
125+
/// * `input` - A G2 point in big-endian (EIP-197) encoding.
126+
///
127+
/// # Returns
128+
///
129+
/// A `Result` containing the compressed G2 point in big-endian (EIP-197) encoding,
130+
/// or an error if the input is not a valid G2 point.
131+
///
132+
/// Note: This function checks if the input has the correct length,
133+
/// returning an error without incurring the cost of the syscall.
134+
pub fn checked_alt_bn128_g2_compress(
135+
input: &[u8],
136+
) -> Result<[u8; ALT_BN128_G2_COMPRESSED_SIZE], ProgramError> {
137+
if input.len() != ALT_BN128_G2_SIZE {
138+
return Err(ProgramError::InvalidArgument);
139+
}
140+
alt_bn128_compression(input, ALT_BN128_G2_COMPRESS)
141+
}
142+
143+
/// Decompress a G2 point on the BN254 curve.
144+
///
145+
/// # Arguments
146+
///
147+
/// * `input` - A compressed G2 point in big-endian (EIP-197) encoding.
148+
///
149+
/// # Returns
150+
///
151+
/// A `Result` containing the decompressed G2 point in big-endian (EIP-197) encoding,
152+
/// or an error if the input is not a valid compressed G2 point.
153+
///
154+
/// Note: This function does **not** check if the input has the correct length.
155+
/// It will return an error if the length is invalid, incurring the cost of the syscall.
156+
#[inline(always)]
157+
pub fn alt_bn128_g2_decompress(input: &[u8]) -> Result<[u8; ALT_BN128_G2_SIZE], ProgramError> {
158+
alt_bn128_compression(input, ALT_BN128_G2_DECOMPRESS)
159+
}
160+
161+
/// Decompress a G2 point on the BN254 curve.
162+
///
163+
/// # Arguments
164+
///
165+
/// * `input` - A compressed G2 point in big-endian (EIP-197) encoding.
166+
///
167+
/// # Returns
168+
///
169+
/// A `Result` containing the decompressed G2 point in big-endian (EIP-197) encoding,
170+
/// or an error if the input is not a valid compressed G2 point.
171+
///
172+
/// Note: This function checks if the input has the correct length,
173+
/// returning an error without incurring the cost of the syscall.
174+
pub fn checked_alt_bn128_g2_decompress(
175+
input: &[u8],
176+
) -> Result<[u8; ALT_BN128_G2_SIZE], ProgramError> {
177+
if input.len() != ALT_BN128_G2_COMPRESSED_SIZE {
178+
return Err(ProgramError::InvalidArgument);
179+
}
180+
alt_bn128_compression(input, ALT_BN128_G2_DECOMPRESS)
181+
}
182+
183+
#[inline]
184+
fn alt_bn128_compression<const OUTPUT_DATA_LEN: usize>(
185+
input: &[u8],
186+
op: u64,
187+
) -> Result<[u8; OUTPUT_DATA_LEN], ProgramError> {
188+
// Call via a system call to perform the calculation
189+
#[cfg(target_os = "solana")]
190+
{
191+
let mut bytes = core::mem::MaybeUninit::<[u8; OUTPUT_DATA_LEN]>::uninit();
192+
193+
let result = unsafe {
194+
sol_alt_bn128_compression(
195+
op,
196+
input as *const _ as *const u8,
197+
input.len() as u64,
198+
bytes.as_mut_ptr() as *mut u8,
199+
)
200+
};
201+
202+
match result {
203+
// SAFETY: The syscall has initialized the bytes.
204+
crate::SUCCESS => Ok(unsafe { bytes.assume_init() }),
205+
_ => Err(ProgramError::InvalidArgument),
206+
}
207+
}
208+
209+
#[cfg(not(target_os = "solana"))]
210+
{
211+
core::hint::black_box((input, op));
212+
panic!("alt_bn128_compression is only available on target `solana`")
213+
}
214+
}

0 commit comments

Comments
 (0)