1use bumpalo::collections::Vec as BumpVec;
2use once_cell::sync::Lazy;
3
4use crate::{arena::Arena, constant::Integer};
5
6pub static SCALAR_PERIOD: Lazy<Integer> = Lazy::new(|| {
7 let bytes: [u8; 32] = [
8 0x73, 0xed, 0xa7, 0x53, 0x29, 0x9d, 0x7d, 0x48, 0x33, 0x39, 0xd8, 0x08, 0x09, 0xa1, 0xd8,
9 0x05, 0x53, 0xbd, 0xa4, 0x02, 0xff, 0xfe, 0x5b, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
10 0x00, 0x01,
11 ];
12
13 Integer::from_bytes_be(num_bigint::Sign::Plus, &bytes)
14});
15
16pub const BLST_P1_COMPRESSED_SIZE: usize = 48;
17
18pub const BLST_P2_COMPRESSED_SIZE: usize = 96;
19
20pub const INTEGER_TO_BYTE_STRING_MAXIMUM_OUTPUT_LENGTH: i64 = 8192;
21
22#[derive(Debug, thiserror::Error)]
23#[error("BLS error: {0:?}")]
24pub struct BlsError(blst::BLST_ERROR);
25
26pub trait Compressable {
27 fn compress<'a>(&self, arena: &'a Arena) -> &'a [u8];
28
29 fn uncompress<'a>(arena: &'a Arena, bytes: &[u8]) -> Result<&'a Self, BlsError>
30 where
31 Self: std::marker::Sized;
32}
33
34impl Compressable for blst::blst_p1 {
35 fn compress<'a>(&self, arena: &'a Arena) -> &'a [u8] {
36 let mut out = [0u8; BLST_P1_COMPRESSED_SIZE];
37
38 unsafe {
39 blst::blst_p1_compress(&mut out as *mut _, self);
40 };
41
42 arena.alloc(BumpVec::from_iter_in(out, arena.as_bump()))
43 }
44
45 fn uncompress<'a>(arena: &'a Arena, bytes: &[u8]) -> Result<&'a Self, BlsError> {
46 if bytes.len() != BLST_P1_COMPRESSED_SIZE {
47 return Err(BlsError(blst::BLST_ERROR::BLST_BAD_ENCODING));
48 }
49
50 let mut affine = blst::blst_p1_affine::default();
51
52 let out = arena.alloc(blst::blst_p1::default());
53
54 unsafe {
55 let err = blst::blst_p1_uncompress(&mut affine as *mut _, bytes.as_ptr());
56
57 if err != blst::BLST_ERROR::BLST_SUCCESS {
58 return Err(BlsError(err));
59 }
60
61 blst::blst_p1_from_affine(out as *mut _, &affine);
62
63 let in_group = blst::blst_p1_in_g1(out);
64
65 if !in_group {
66 return Err(BlsError(blst::BLST_ERROR::BLST_POINT_NOT_IN_GROUP));
67 }
68 };
69
70 Ok(out)
71 }
72}
73
74impl Compressable for blst::blst_p2 {
75 fn compress<'a>(&self, arena: &'a Arena) -> &'a [u8] {
76 let mut out = [0; BLST_P2_COMPRESSED_SIZE];
77
78 unsafe {
79 blst::blst_p2_compress(&mut out as *mut _, self);
80 };
81
82 arena.alloc(BumpVec::from_iter_in(out, arena.as_bump()))
83 }
84
85 fn uncompress<'a>(arena: &'a Arena, bytes: &[u8]) -> Result<&'a Self, BlsError> {
86 if bytes.len() != BLST_P2_COMPRESSED_SIZE {
87 return Err(BlsError(blst::BLST_ERROR::BLST_BAD_ENCODING));
88 }
89
90 let mut affine = blst::blst_p2_affine::default();
91
92 let out = arena.alloc(blst::blst_p2::default());
93
94 unsafe {
95 let err = blst::blst_p2_uncompress(&mut affine as *mut _, bytes.as_ptr());
96
97 if err != blst::BLST_ERROR::BLST_SUCCESS {
98 return Err(BlsError(err));
99 }
100
101 blst::blst_p2_from_affine(out as *mut _, &affine);
102
103 let in_group = blst::blst_p2_in_g2(out);
104
105 if !in_group {
106 return Err(BlsError(blst::BLST_ERROR::BLST_POINT_NOT_IN_GROUP));
107 }
108 };
109
110 Ok(out)
111 }
112}