use std::io::ErrorKind;
use crate::{
syscall_bls12381_add, syscall_bls12381_decompress, syscall_bls12381_double,
utils::{AffinePoint, WeierstrassAffinePoint, WeierstrassPoint},
};
pub const N: usize = 12;
#[derive(Copy, Clone)]
#[repr(align(8))]
pub struct Bls12381Point(pub WeierstrassPoint<N>);
impl WeierstrassAffinePoint<N> for Bls12381Point {
fn infinity() -> Self {
Self(WeierstrassPoint::Infinity)
}
fn is_infinity(&self) -> bool {
matches!(self.0, WeierstrassPoint::Infinity)
}
}
impl AffinePoint<N> for Bls12381Point {
const GENERATOR: [u64; N] = [
18103045581585958587,
7806400890582735599,
11623291730934869080,
14080658508445169925,
2780237799254240271,
1725392847304644500,
912580534683953121,
15005087156090211044,
61670280795567085,
18227722000993880822,
11573741888802228964,
627113611842199793,
];
#[allow(deprecated)]
const GENERATOR_T: Self = Self(WeierstrassPoint::Affine(Self::GENERATOR));
fn new(limbs: [u64; N]) -> Self {
Self(WeierstrassPoint::Affine(limbs))
}
fn identity() -> Self {
Self::infinity()
}
fn is_identity(&self) -> bool {
self.is_infinity()
}
fn limbs_ref(&self) -> &[u64; N] {
match &self.0 {
WeierstrassPoint::Infinity => panic!("Infinity point has no limbs"),
WeierstrassPoint::Affine(limbs) => limbs,
}
}
fn limbs_mut(&mut self) -> &mut [u64; N] {
match &mut self.0 {
WeierstrassPoint::Infinity => panic!("Infinity point has no limbs"),
WeierstrassPoint::Affine(limbs) => limbs,
}
}
fn add_assign(&mut self, other: &Self) {
let a = self.limbs_mut();
let b = other.limbs_ref();
unsafe {
syscall_bls12381_add(a, b);
}
}
fn complete_add_assign(&mut self, other: &Self) {
self.weierstrass_add_assign(other);
}
fn double(&mut self) {
let a = self.limbs_mut();
unsafe {
syscall_bls12381_double(a);
}
}
}
pub fn decompress_pubkey(compressed_key: &[u64; 6]) -> Result<[u64; 12], ErrorKind> {
let mut decompressed_key = [0u64; 12];
decompressed_key[..6].copy_from_slice(compressed_key);
let mut decompressed_key = decompressed_key.map(u64::to_ne_bytes);
const SIGN_OFFSET: u32 = 3;
const SIGN_MASK: u8 = 1u8 << (u8::BITS - SIGN_OFFSET);
let sign_bit = (decompressed_key[0][0] & SIGN_MASK) != 0;
decompressed_key[0][0] <<= SIGN_OFFSET;
decompressed_key[0][0] >>= SIGN_OFFSET;
let mut decompressed_key = decompressed_key.map(u64::from_ne_bytes);
unsafe {
syscall_bls12381_decompress(&mut decompressed_key, sign_bit);
}
Ok(decompressed_key)
}