use bumpalo::collections::Vec as BumpVec;
use once_cell::sync::Lazy;
use crate::{arena::Arena, constant::Integer};
pub static SCALAR_PERIOD: Lazy<Integer> = Lazy::new(|| {
let bytes: [u8; 32] = [
0x73, 0xed, 0xa7, 0x53, 0x29, 0x9d, 0x7d, 0x48, 0x33, 0x39, 0xd8, 0x08, 0x09, 0xa1, 0xd8,
0x05, 0x53, 0xbd, 0xa4, 0x02, 0xff, 0xfe, 0x5b, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
0x00, 0x01,
];
Integer::from_bytes_be(num_bigint::Sign::Plus, &bytes)
});
pub const BLST_P1_COMPRESSED_SIZE: usize = 48;
pub const BLST_P2_COMPRESSED_SIZE: usize = 96;
pub const INTEGER_TO_BYTE_STRING_MAXIMUM_OUTPUT_LENGTH: i64 = 8192;
#[derive(Debug, thiserror::Error)]
#[error("BLS error: {0:?}")]
pub struct BlsError(blst::BLST_ERROR);
pub trait Compressable {
fn compress<'a>(&self, arena: &'a Arena) -> &'a [u8];
fn uncompress<'a>(arena: &'a Arena, bytes: &[u8]) -> Result<&'a Self, BlsError>
where
Self: std::marker::Sized;
}
impl Compressable for blst::blst_p1 {
fn compress<'a>(&self, arena: &'a Arena) -> &'a [u8] {
let mut out = [0u8; BLST_P1_COMPRESSED_SIZE];
unsafe {
blst::blst_p1_compress(&mut out as *mut _, self);
};
arena.alloc(BumpVec::from_iter_in(out, arena.as_bump()))
}
fn uncompress<'a>(arena: &'a Arena, bytes: &[u8]) -> Result<&'a Self, BlsError> {
if bytes.len() != BLST_P1_COMPRESSED_SIZE {
return Err(BlsError(blst::BLST_ERROR::BLST_BAD_ENCODING));
}
let mut affine = blst::blst_p1_affine::default();
let out = arena.alloc(blst::blst_p1::default());
unsafe {
let err = blst::blst_p1_uncompress(&mut affine as *mut _, bytes.as_ptr());
if err != blst::BLST_ERROR::BLST_SUCCESS {
return Err(BlsError(err));
}
blst::blst_p1_from_affine(out as *mut _, &affine);
let in_group = blst::blst_p1_in_g1(out);
if !in_group {
return Err(BlsError(blst::BLST_ERROR::BLST_POINT_NOT_IN_GROUP));
}
};
Ok(out)
}
}
impl Compressable for blst::blst_p2 {
fn compress<'a>(&self, arena: &'a Arena) -> &'a [u8] {
let mut out = [0; BLST_P2_COMPRESSED_SIZE];
unsafe {
blst::blst_p2_compress(&mut out as *mut _, self);
};
arena.alloc(BumpVec::from_iter_in(out, arena.as_bump()))
}
fn uncompress<'a>(arena: &'a Arena, bytes: &[u8]) -> Result<&'a Self, BlsError> {
if bytes.len() != BLST_P2_COMPRESSED_SIZE {
return Err(BlsError(blst::BLST_ERROR::BLST_BAD_ENCODING));
}
let mut affine = blst::blst_p2_affine::default();
let out = arena.alloc(blst::blst_p2::default());
unsafe {
let err = blst::blst_p2_uncompress(&mut affine as *mut _, bytes.as_ptr());
if err != blst::BLST_ERROR::BLST_SUCCESS {
return Err(BlsError(err));
}
blst::blst_p2_from_affine(out as *mut _, &affine);
let in_group = blst::blst_p2_in_g2(out);
if !in_group {
return Err(BlsError(blst::BLST_ERROR::BLST_POINT_NOT_IN_GROUP));
}
};
Ok(out)
}
}