#[cfg(zisk_guest)]
use crate::alloc_extern::vec::Vec;
use crate::{
syscalls::{
syscall_bls12_381_curve_add, syscall_bls12_381_curve_dbl, SyscallBls12_381CurveAddParams,
SyscallPoint384,
},
zisklib::{eq, fcall_msb_pos_256, is_one, is_two, is_zero, lt},
};
use super::{
constants::{E_B, G1_IDENTITY, GAMMA, P, X2DIV3_BIN_BE},
fp::{
add_fp_bls12_381, mul_fp_bls12_381, neg_fp_bls12_381, sqrt_fp_bls12_381,
square_fp_bls12_381,
},
fr::{reduce_fr_bls12_381, scalar_bytes_be_to_u64_le_bls12_381},
};
#[allow(dead_code)]
pub(crate) const G1_ADD_SUCCESS: u8 = 0;
#[allow(dead_code)]
pub(crate) const G1_ADD_SUCCESS_INFINITY: u8 = 1;
const G1_ADD_ERR_NOT_IN_FIELD: u8 = 2;
const G1_ADD_ERR_NOT_ON_CURVE: u8 = 3;
#[allow(dead_code)]
pub(crate) const G1_MSM_SUCCESS: u8 = 0;
#[allow(dead_code)]
pub(crate) const G1_MSM_SUCCESS_INFINITY: u8 = 1;
const G1_MSM_ERR_NOT_IN_FIELD: u8 = 2;
const G1_MSM_ERR_NOT_ON_CURVE: u8 = 3;
const G1_MSM_ERR_NOT_IN_SUBGROUP: u8 = 4;
pub fn decompress_bls12_381(
input: &[u8; 48],
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> Result<([u64; 12], bool), &'static str> {
let flags = input[0];
if (flags & 0x80) == 0 {
return Err("Expected compressed point");
}
if (flags & 0x40) != 0 {
if (flags & 0x3f) != 0 {
return Err("Invalid infinity encoding");
}
for input in input.iter().skip(1) {
if *input != 0 {
return Err("Invalid infinity encoding");
}
}
return Ok((G1_IDENTITY, true));
}
let y_sign = (flags & 0x20) != 0;
let mut x = [0u64; 6];
let mut bytes = [0u8; 48];
bytes.copy_from_slice(input);
bytes[0] &= 0x1f;
for i in 0..6 {
for j in 0..8 {
x[5 - i] |= (bytes[i * 8 + j] as u64) << (8 * (7 - j));
}
}
if !lt(&x, &P) {
return Err("x coordinate >= field modulus");
}
let x_sq = square_fp_bls12_381(
&x,
#[cfg(feature = "hints")]
hints,
);
let x_cb = mul_fp_bls12_381(
&x_sq,
&x,
#[cfg(feature = "hints")]
hints,
);
let y_sq = add_fp_bls12_381(
&x_cb,
&E_B,
#[cfg(feature = "hints")]
hints,
);
let (y, has_sqrt) = sqrt_fp_bls12_381(
&y_sq,
#[cfg(feature = "hints")]
hints,
);
if !has_sqrt {
return Err("No square root exists - point not on curve");
}
let y_neg = neg_fp_bls12_381(
&y,
#[cfg(feature = "hints")]
hints,
);
let y_is_larger = lt(&y_neg, &y);
let final_y = if y_is_larger == y_sign { y } else { y_neg };
let mut result = [0u64; 12];
result[0..6].copy_from_slice(&x);
result[6..12].copy_from_slice(&final_y);
Ok((result, false))
}
pub fn is_on_curve_bls12_381(
p: &[u64; 12],
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> bool {
let x: [u64; 6] = p[0..6].try_into().unwrap();
let y: [u64; 6] = p[6..12].try_into().unwrap();
let lhs = square_fp_bls12_381(
&y,
#[cfg(feature = "hints")]
hints,
);
let mut rhs = square_fp_bls12_381(
&x,
#[cfg(feature = "hints")]
hints,
);
rhs = mul_fp_bls12_381(
&rhs,
&x,
#[cfg(feature = "hints")]
hints,
);
rhs = add_fp_bls12_381(
&rhs,
&E_B,
#[cfg(feature = "hints")]
hints,
);
eq(&lhs, &rhs) || eq(p, &G1_IDENTITY)
}
pub fn is_on_subgroup_bls12_381(
p: &[u64; 12],
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> bool {
let sigma1 = sigma_endomorphism_bls12_381(
p,
#[cfg(feature = "hints")]
hints,
);
let rhs = sigma_endomorphism_bls12_381(
&sigma1,
#[cfg(feature = "hints")]
hints,
);
let mut lhs = dbl_complete_bls12_381(
&sigma1,
#[cfg(feature = "hints")]
hints,
);
lhs = sub_complete_bls12_381(
&lhs,
p,
#[cfg(feature = "hints")]
hints,
);
lhs = sub_complete_bls12_381(
&lhs,
&rhs,
#[cfg(feature = "hints")]
hints,
);
lhs = scalar_mul_by_x2div3_complete_bls12_381(
&lhs,
#[cfg(feature = "hints")]
hints,
);
eq(&lhs, &rhs)
}
pub fn sigma_endomorphism_bls12_381(
p: &[u64; 12],
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> [u64; 12] {
let mut x: [u64; 6] = p[0..6].try_into().unwrap();
let y: [u64; 6] = p[6..12].try_into().unwrap();
x = mul_fp_bls12_381(
&x,
&GAMMA,
#[cfg(feature = "hints")]
hints,
);
let mut result = [0u64; 12];
result[0..6].copy_from_slice(&x);
result[6..12].copy_from_slice(&y);
result
}
pub fn add_complete_bls12_381(
p1: &[u64; 12],
p2: &[u64; 12],
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> [u64; 12] {
if eq(p1, &G1_IDENTITY) {
return *p2;
} else if eq(p2, &G1_IDENTITY) {
return *p1;
}
add_bls12_381(
p1,
p2,
#[cfg(feature = "hints")]
hints,
)
}
pub(crate) fn add_bls12_381(
p1: &[u64; 12],
p2: &[u64; 12],
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> [u64; 12] {
let x1: [u64; 6] = p1[0..6].try_into().unwrap();
let y1: [u64; 6] = p1[6..12].try_into().unwrap();
let x2: [u64; 6] = p2[0..6].try_into().unwrap();
let y2: [u64; 6] = p2[6..12].try_into().unwrap();
if eq(&x1, &x2) {
if eq(&y1, &y2) {
return dbl_bls12_381(
p1,
#[cfg(feature = "hints")]
hints,
);
} else {
return G1_IDENTITY;
}
}
let mut p1 = SyscallPoint384 { x: x1, y: y1 };
let p2 = SyscallPoint384 { x: x2, y: y2 };
let mut params = SyscallBls12_381CurveAddParams { p1: &mut p1, p2: &p2 };
syscall_bls12_381_curve_add(
&mut params,
#[cfg(feature = "hints")]
hints,
);
let mut result = [0u64; 12];
result[0..6].copy_from_slice(&p1.x);
result[6..12].copy_from_slice(&p1.y);
result
}
pub fn add_complete_safe_bls12_381(
p1: &[u64; 12],
p2: &[u64; 12],
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> Result<[u64; 12], u8> {
let p1_is_inf = *p1 == G1_IDENTITY;
let p2_is_inf = *p2 == G1_IDENTITY;
if p1_is_inf && p2_is_inf {
return Ok(G1_IDENTITY);
}
if p1_is_inf {
let x2: [u64; 6] = p2[0..6].try_into().unwrap();
let y2: [u64; 6] = p2[6..12].try_into().unwrap();
if !lt(&x2, &P) || !lt(&y2, &P) {
return Err(G1_ADD_ERR_NOT_IN_FIELD);
}
if !is_on_curve_bls12_381(
p2,
#[cfg(feature = "hints")]
hints,
) {
return Err(G1_ADD_ERR_NOT_ON_CURVE);
}
return Ok(*p2);
}
if p2_is_inf {
let x1: [u64; 6] = p1[0..6].try_into().unwrap();
let y1: [u64; 6] = p1[6..12].try_into().unwrap();
if !lt(&x1, &P) || !lt(&y1, &P) {
return Err(G1_ADD_ERR_NOT_IN_FIELD);
}
if !is_on_curve_bls12_381(
p1,
#[cfg(feature = "hints")]
hints,
) {
return Err(G1_ADD_ERR_NOT_ON_CURVE);
}
return Ok(*p1);
}
let x1: [u64; 6] = p1[0..6].try_into().unwrap();
let y1: [u64; 6] = p1[6..12].try_into().unwrap();
if !lt(&x1, &P) || !lt(&y1, &P) {
return Err(G1_ADD_ERR_NOT_IN_FIELD);
}
if !is_on_curve_bls12_381(
p1,
#[cfg(feature = "hints")]
hints,
) {
return Err(G1_ADD_ERR_NOT_ON_CURVE);
}
let x2: [u64; 6] = p2[0..6].try_into().unwrap();
let y2: [u64; 6] = p2[6..12].try_into().unwrap();
if !lt(&x2, &P) || !lt(&y2, &P) {
return Err(G1_ADD_ERR_NOT_IN_FIELD);
}
if !is_on_curve_bls12_381(
p2,
#[cfg(feature = "hints")]
hints,
) {
return Err(G1_ADD_ERR_NOT_ON_CURVE);
}
Ok(add_bls12_381(
p1,
p2,
#[cfg(feature = "hints")]
hints,
))
}
pub fn neg_bls12_381(p: &[u64; 12], #[cfg(feature = "hints")] hints: &mut Vec<u64>) -> [u64; 12] {
let x: [u64; 6] = p[0..6].try_into().unwrap();
let y: [u64; 6] = p[6..12].try_into().unwrap();
let y_neg = neg_fp_bls12_381(
&y,
#[cfg(feature = "hints")]
hints,
);
let mut result = [0u64; 12];
result[0..6].copy_from_slice(&x);
result[6..12].copy_from_slice(&y_neg);
result
}
pub fn dbl_complete_bls12_381(
p: &[u64; 12],
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> [u64; 12] {
if eq(p, &G1_IDENTITY) {
return G1_IDENTITY;
}
dbl_bls12_381(
p,
#[cfg(feature = "hints")]
hints,
)
}
pub(crate) fn dbl_bls12_381(
p: &[u64; 12],
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> [u64; 12] {
let mut p = SyscallPoint384 { x: p[0..6].try_into().unwrap(), y: p[6..12].try_into().unwrap() };
syscall_bls12_381_curve_dbl(
&mut p,
#[cfg(feature = "hints")]
hints,
);
let mut result = [0u64; 12];
result[0..6].copy_from_slice(&p.x);
result[6..12].copy_from_slice(&p.y);
result
}
pub fn sub_complete_bls12_381(
p1: &[u64; 12],
p2: &[u64; 12],
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> [u64; 12] {
if eq(p1, &G1_IDENTITY) {
return neg_bls12_381(
p2,
#[cfg(feature = "hints")]
hints,
);
} else if eq(p2, &G1_IDENTITY) {
return *p1;
}
sub_bls12_381(
p1,
p2,
#[cfg(feature = "hints")]
hints,
)
}
pub fn sub_bls12_381(
p1: &[u64; 12],
p2: &[u64; 12],
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> [u64; 12] {
let x2: [u64; 6] = p2[0..6].try_into().unwrap();
let y2: [u64; 6] = p2[6..12].try_into().unwrap();
let y2_neg = neg_fp_bls12_381(
&y2,
#[cfg(feature = "hints")]
hints,
);
let mut p2_neg = [0u64; 12];
p2_neg[0..6].copy_from_slice(&x2);
p2_neg[6..12].copy_from_slice(&y2_neg);
add_bls12_381(
p1,
&p2_neg,
#[cfg(feature = "hints")]
hints,
)
}
pub fn scalar_mul_complete_bls12_381(
p: &[u64; 12],
k: &[u64; 4],
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> [u64; 12] {
if eq(p, &G1_IDENTITY) {
return G1_IDENTITY;
}
let k = reduce_fr_bls12_381(
k,
#[cfg(feature = "hints")]
hints,
);
if is_zero(&k) {
return G1_IDENTITY;
} else if is_one(&k) {
return *p;
} else if is_two(&k) {
return dbl_bls12_381(
p,
#[cfg(feature = "hints")]
hints,
);
}
let (max_limb, max_bit) = fcall_msb_pos_256(
&k,
#[cfg(feature = "hints")]
hints,
);
assert!(max_limb < 4 && max_bit < 64, "msb_pos hint out of range");
let max_limb = max_limb as usize;
let max_bit = max_bit as usize;
assert_eq!((k[max_limb] >> max_bit) & 1, 1, "The most significant bit of the scalar must be 1");
let mut k_rec = [0u64; 4];
k_rec[max_limb] |= 1 << max_bit;
let mut limb = max_limb;
let mut bit = if max_bit == 0 {
limb -= 1;
63
} else {
max_bit - 1
};
let mut q: [u64; 12] = *p;
for i in (0..=limb).rev() {
for j in (0..=bit).rev() {
q = dbl_complete_bls12_381(
&q,
#[cfg(feature = "hints")]
hints,
);
if ((k[i] >> j) & 1) == 1 {
q = add_complete_bls12_381(
&q,
p,
#[cfg(feature = "hints")]
hints,
);
k_rec[i] |= 1 << j;
}
}
bit = 63;
}
assert!(eq(&k, &k_rec), "Reconstructed scalar does not match input scalar");
q
}
pub fn scalar_mul_bls12_381(
p: &[u64; 12],
k: &[u64; 4],
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> [u64; 12] {
let k = reduce_fr_bls12_381(
k,
#[cfg(feature = "hints")]
hints,
);
if is_zero(&k) {
return G1_IDENTITY;
} else if is_one(&k) {
return *p;
} else if is_two(&k) {
return dbl_bls12_381(
p,
#[cfg(feature = "hints")]
hints,
);
}
let (max_limb, max_bit) = fcall_msb_pos_256(
&k,
#[cfg(feature = "hints")]
hints,
);
assert!(max_limb < 4 && max_bit < 64, "msb_pos hint out of range");
let max_limb = max_limb as usize;
let max_bit = max_bit as usize;
assert_eq!((k[max_limb] >> max_bit) & 1, 1, "The most significant bit of the scalar must be 1");
let x1: [u64; 6] = p[0..6].try_into().unwrap();
let y1: [u64; 6] = p[6..12].try_into().unwrap();
let mut q = SyscallPoint384 { x: x1, y: y1 };
let mut k_rec = [0u64; 4];
k_rec[max_limb] |= 1 << max_bit;
let mut limb = max_limb;
let mut bit = if max_bit == 0 {
limb -= 1;
63
} else {
max_bit - 1
};
let p = SyscallPoint384 { x: x1, y: y1 };
for i in (0..=limb).rev() {
for j in (0..=bit).rev() {
syscall_bls12_381_curve_dbl(
&mut q,
#[cfg(feature = "hints")]
hints,
);
if ((k[i] >> j) & 1) == 1 {
let mut params = SyscallBls12_381CurveAddParams { p1: &mut q, p2: &p };
syscall_bls12_381_curve_add(
&mut params,
#[cfg(feature = "hints")]
hints,
);
k_rec[i] |= 1 << j;
}
}
bit = 63;
}
assert!(eq(&k, &k_rec), "Reconstructed scalar does not match input scalar");
let mut result = [0u64; 12];
result[0..6].copy_from_slice(&q.x);
result[6..12].copy_from_slice(&q.y);
result
}
pub fn scalar_mul_by_x2div3_complete_bls12_381(
p: &[u64; 12],
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> [u64; 12] {
if eq(p, &G1_IDENTITY) {
return G1_IDENTITY;
}
let mut r = *p;
for &bit in X2DIV3_BIN_BE.iter().skip(1) {
r = dbl_complete_bls12_381(
&r,
#[cfg(feature = "hints")]
hints,
);
if bit == 1 {
r = add_complete_bls12_381(
&r,
p,
#[cfg(feature = "hints")]
hints,
);
}
}
r
}
pub fn msm_complete_safe_bls12_381(
points: &[[u64; 12]],
scalars: &[[u64; 4]],
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> Result<[u64; 12], u8> {
assert_eq!(points.len(), scalars.len(), "Points and scalars must have the same length");
let mut acc = G1_IDENTITY;
let mut acc_is_inf = true;
for (point, scalar) in points.iter().zip(scalars.iter()) {
if *point == G1_IDENTITY {
continue;
}
let x: [u64; 6] = point[0..6].try_into().unwrap();
let y: [u64; 6] = point[6..12].try_into().unwrap();
if !lt(&x, &P) || !lt(&y, &P) {
return Err(G1_MSM_ERR_NOT_IN_FIELD);
}
if !is_on_curve_bls12_381(
point,
#[cfg(feature = "hints")]
hints,
) {
return Err(G1_MSM_ERR_NOT_ON_CURVE);
}
if !is_on_subgroup_bls12_381(
point,
#[cfg(feature = "hints")]
hints,
) {
return Err(G1_MSM_ERR_NOT_IN_SUBGROUP);
}
let scalar = reduce_fr_bls12_381(
scalar,
#[cfg(feature = "hints")]
hints,
);
if is_zero(&scalar) {
continue;
}
let product = scalar_mul_bls12_381(
point,
&scalar,
#[cfg(feature = "hints")]
hints,
);
if product == G1_IDENTITY {
continue;
}
if acc_is_inf {
acc = product;
acc_is_inf = false;
} else {
acc = add_bls12_381(
&acc,
&product,
#[cfg(feature = "hints")]
hints,
);
acc_is_inf = acc == G1_IDENTITY;
}
}
Ok(acc)
}
#[cfg_attr(not(feature = "hints"), no_mangle)]
#[cfg_attr(feature = "hints", export_name = "hints_decompress_bls12_381_c")]
pub unsafe extern "C" fn decompress_bls12_381_c(
input_ptr: *const u8,
result_ptr: *mut u64,
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> u8 {
let input = &*(input_ptr as *const [u8; 48]);
match decompress_bls12_381(
input,
#[cfg(feature = "hints")]
hints,
) {
Ok((p, is_infinity)) => {
let result = &mut *(result_ptr as *mut [u64; 12]);
*result = p;
if is_infinity {
1
} else {
0
}
}
Err(_) => 2,
}
}
#[cfg_attr(not(feature = "hints"), no_mangle)]
#[cfg_attr(feature = "hints", export_name = "hints_is_on_curve_bls12_381_c")]
pub unsafe extern "C" fn is_on_curve_bls12_381_c(
p_ptr: *const u64,
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> u8 {
let p = &*(p_ptr as *const [u64; 12]);
is_on_curve_bls12_381(
p,
#[cfg(feature = "hints")]
hints,
) as u8
}
#[cfg_attr(not(feature = "hints"), no_mangle)]
#[cfg_attr(feature = "hints", export_name = "hints_is_on_subgroup_bls12_381_c")]
pub unsafe extern "C" fn is_on_subgroup_bls12_381_c(
p_ptr: *const u64,
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> u8 {
let p = &*(p_ptr as *const [u64; 12]);
is_on_subgroup_bls12_381(
p,
#[cfg(feature = "hints")]
hints,
) as u8
}
#[cfg_attr(not(feature = "hints"), no_mangle)]
#[cfg_attr(feature = "hints", export_name = "hints_add_bls12_381_c")]
pub unsafe extern "C" fn add_bls12_381_c(
p1_ptr: *const u64,
p2_ptr: *const u64,
result_ptr: *mut u64,
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> u8 {
let p1 = &*(p1_ptr as *const [u64; 12]);
let p2 = &*(p2_ptr as *const [u64; 12]);
let result = &mut *(result_ptr as *mut [u64; 12]);
*result = add_bls12_381(
p1,
p2,
#[cfg(feature = "hints")]
hints,
);
if eq(result, &G1_IDENTITY) {
1
} else {
0
}
}
#[allow(dead_code)]
#[inline]
pub(crate) unsafe fn add_safe_bls12_381_c(
ret: *mut u8,
a: *const u8,
b: *const u8,
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> u8 {
let a_bytes: &[u8; 96] = &*(a as *const [u8; 96]);
let b_bytes: &[u8; 96] = &*(b as *const [u8; 96]);
let ret_bytes: &mut [u8; 96] = &mut *(ret as *mut [u8; 96]);
let a_u64 = g1_bytes_be_to_u64_le_bls12_381(a_bytes);
let b_u64 = g1_bytes_be_to_u64_le_bls12_381(b_bytes);
let result = match add_complete_safe_bls12_381(
&a_u64,
&b_u64,
#[cfg(feature = "hints")]
hints,
) {
Ok(r) => r,
Err(code) => return code,
};
g1_u64_le_to_bytes_be_bls12_381(&result, ret_bytes);
if result == G1_IDENTITY {
G1_ADD_SUCCESS_INFINITY
} else {
G1_ADD_SUCCESS
}
}
#[cfg_attr(not(feature = "hints"), no_mangle)]
#[cfg_attr(feature = "hints", export_name = "hints_scalar_mul_bls12_381_c")]
pub unsafe extern "C" fn scalar_mul_bls12_381_c(
p_ptr: *const u64,
k_ptr: *const u64,
result_ptr: *mut u64,
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> u8 {
let p = &*(p_ptr as *const [u64; 12]);
let k = &*(k_ptr as *const [u64; 4]);
let result = &mut *(result_ptr as *mut [u64; 12]);
*result = scalar_mul_bls12_381(
p,
k,
#[cfg(feature = "hints")]
hints,
);
if eq(result, &G1_IDENTITY) {
1
} else {
0
}
}
#[allow(dead_code)]
#[inline]
pub(crate) unsafe fn msm_safe_bls12_381_c(
ret: *mut u8,
pairs: *const u8,
num_pairs: usize,
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> u8 {
let ret_bytes: &mut [u8; 96] = &mut *(ret as *mut [u8; 96]);
let mut points = Vec::with_capacity(num_pairs);
let mut scalars = Vec::with_capacity(num_pairs);
for i in 0..num_pairs {
let pair_ptr = pairs.add(i * 128);
let point_bytes: &[u8; 96] = &*(pair_ptr as *const [u8; 96]);
let scalar_bytes: &[u8; 32] = &*(pair_ptr.add(96) as *const [u8; 32]);
let point_u64 = g1_bytes_be_to_u64_le_bls12_381(point_bytes);
let scalar_u64 = scalar_bytes_be_to_u64_le_bls12_381(scalar_bytes);
points.push(point_u64);
scalars.push(scalar_u64);
}
let result = match msm_complete_safe_bls12_381(
&points,
&scalars,
#[cfg(feature = "hints")]
hints,
) {
Ok(r) => r,
Err(code) => return code,
};
g1_u64_le_to_bytes_be_bls12_381(&result, ret_bytes);
if result == G1_IDENTITY {
G1_MSM_SUCCESS_INFINITY
} else {
G1_MSM_SUCCESS
}
}
pub fn g1_bytes_be_to_u64_le_bls12_381(bytes: &[u8; 96]) -> [u64; 12] {
let mut result = [0u64; 12];
for i in 0..6 {
for j in 0..8 {
result[5 - i] |= (bytes[i * 8 + j] as u64) << (8 * (7 - j));
}
}
for i in 0..6 {
for j in 0..8 {
result[11 - i] |= (bytes[48 + i * 8 + j] as u64) << (8 * (7 - j));
}
}
result
}
pub fn g1_u64_le_to_bytes_be_bls12_381(limbs: &[u64; 12], bytes: &mut [u8; 96]) {
for i in 0..6 {
let limb = limbs[5 - i];
for j in 0..8 {
bytes[i * 8 + j] = ((limb >> (8 * (7 - j))) & 0xFF) as u8;
}
}
for i in 0..6 {
let limb = limbs[11 - i];
for j in 0..8 {
bytes[48 + i * 8 + j] = ((limb >> (8 * (7 - j))) & 0xFF) as u8;
}
}
}