use bls12_381::{pairing, G1Affine, G2Affine, G2Projective, Scalar};
use crate::keys::{PrivateKey, PublicKey};
use crate::traits::ThresholdSignature;
use crate::utils::lambda_coeff;
const G2_POINT_BYTES_LENGTH: usize = 96;
#[derive(Debug, Eq, PartialEq)]
pub enum VerificationResult {
Valid,
Invalid,
}
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub struct Signature(pub(crate) G2Affine, Option<Scalar>);
impl Signature {
pub(crate) fn new(private_key: &PrivateKey, message_element: &G2Affine) -> Signature {
Signature((message_element * &private_key.0).into(), private_key.1)
}
pub(crate) fn verify(
&self,
public_key: &PublicKey,
message_element: &G2Affine,
) -> VerificationResult {
let c_1 = pairing(&public_key.0, &message_element);
let c_2 = pairing(&G1Affine::generator(), &self.0);
VerificationResult::from(c_1 == c_2)
}
pub fn to_bytes(&self, buff: &mut [u8]) {
buff[0..96].copy_from_slice(&self.0.to_compressed()[..]);
if let Some(fragment_index) = self.1 {
buff[96..128].copy_from_slice(&fragment_index.to_bytes()[..]);
}
}
pub fn from_bytes(bytes: &[u8]) -> Signature {
let mut point_bytes = [0u8; 96];
let fragment_index: Option<Scalar>;
if bytes.len() == G2_POINT_BYTES_LENGTH {
point_bytes.copy_from_slice(&bytes);
fragment_index = None
} else {
let mut index_bytes = [0u8; 32];
point_bytes.copy_from_slice(&bytes[0..G2_POINT_BYTES_LENGTH]);
index_bytes.copy_from_slice(&bytes[G2_POINT_BYTES_LENGTH..128]);
fragment_index = Some(Scalar::from_bytes(&index_bytes).unwrap());
}
Signature(
G2Affine::from_compressed(&point_bytes).unwrap(),
fragment_index,
)
}
}
impl ThresholdSignature for Signature {
fn assemble(fragments: &[Signature]) -> Signature {
let mut fragment_indices = [Scalar::zero(); 256];
for i in 0..fragments.len() {
fragment_indices[i] = fragments[i].1.unwrap();
}
let mut result = G2Projective::identity();
for fragment in fragments.iter() {
result +=
fragment.0 * lambda_coeff(&fragment.1.unwrap(), &fragment_indices[..fragments.len()]);
}
Signature(result.into(), None)
}
fn is_fragment(&self) -> bool {
match self.1 {
Some(_) => true,
None => false,
}
}
}
impl From<bool> for VerificationResult {
fn from(result: bool) -> Self {
if result {
VerificationResult::Valid
} else {
VerificationResult::Invalid
}
}
}