use crate::amcl::hmac;
use crate::constants::{CurveOrder, GroupG2_SIZE, G2_COMP_BYTE_SIZE, HASH_TYPE};
use crate::errors::{SerzDeserzError, ValueError};
use crate::field_elem::{FieldElement, FieldElementVector};
use crate::group_elem::{GroupElement, GroupElementVector};
use crate::types::{GroupG2, FP, FP2};
use crate::utils::{hash_msg, hash_to_field};
use std::iter;
use std::ops::{Add, AddAssign, Index, IndexMut, Mul, Neg, Sub, SubAssign};
use core::fmt;
use std::hash::{Hash, Hasher};
use std::slice::Iter;
use crate::rayon::iter::IntoParallelRefMutIterator;
use rayon::prelude::*;
use serde::de::{Deserialize, Deserializer, Error as DError, Visitor};
use serde::ser::{Error as SError, Serialize, Serializer};
use zeroize::Zeroize;
#[derive(Clone)]
pub struct G2 {
value: GroupG2,
}
impl fmt::Debug for G2 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "ECP2: [ {} ]", self.value.tostring())
}
}
impl GroupElement for G2 {
fn new() -> Self {
Self {
value: GroupG2::new(),
}
}
fn identity() -> Self {
let mut v = GroupG2::new();
v.inf();
Self { value: v }
}
fn generator() -> Self {
GroupG2::generator().into()
}
fn is_identity(&self) -> bool {
self.value.is_infinity()
}
fn set_to_identity(&mut self) {
self.value.inf()
}
fn from_msg_hash(msg: &[u8]) -> Self {
GroupG2::mapit(&hash_msg(msg)).into()
}
impl_group_elem_byte_conversion_methods!(
GroupG2,
GroupG2_SIZE,
G2_COMP_BYTE_SIZE,
SerzDeserzError::G2BytesIncorrectSize
);
fn add_assign_(&mut self, b: &Self) {
self.value.add(&b.value);
}
fn sub_assign_(&mut self, b: &Self) {
self.value.sub(&b.value);
}
fn plus(&self, b: &Self) -> Self {
let mut sum = self.value.clone();
sum.add(&b.value);
sum.into()
}
fn minus(&self, b: &Self) -> Self {
let mut diff = self.value.clone();
diff.sub(&b.value);
diff.into()
}
fn scalar_mul_const_time(&self, a: &FieldElement) -> Self {
self.value.mul(&a.to_bignum()).into()
}
fn double(&self) -> Self {
let mut d = self.value.clone();
d.dbl();
d.into()
}
fn double_mut(&mut self) {
self.value.dbl();
}
fn to_hex(&self) -> String {
self.value.tostring()
}
fn from_hex(mut string: String) -> Result<Self, SerzDeserzError> {
if &string == "infinity" {
return Ok(Self::new());
}
unbound_bounded_string!(string, '(', ')', SerzDeserzError::CannotParseG2);
let (x, y) = split_string_to_2_tuple!(string, SerzDeserzError::CannotParseG2);
let x_fp2 = parse_hex_as_FP2(x)?;
let y_fp2 = parse_hex_as_FP2(y)?;
Ok(Self {
value: GroupG2::new_fp2s(&x_fp2, &y_fp2),
})
}
fn negation(&self) -> Self {
let mut n = self.to_ecp();
n.neg();
n.into()
}
fn is_extension() -> bool {
return true;
}
fn has_correct_order(&self) -> bool {
return self.value.mul(&CurveOrder).is_infinity();
}
}
pub fn parse_hex_as_FP2(mut string: String) -> Result<FP2, SerzDeserzError> {
unbound_bounded_string!(string, '[', ']', SerzDeserzError::CannotParseFP2);
let (a, b) = split_string_to_2_tuple!(string, SerzDeserzError::CannotParseFP2);
let a_big = FieldElement::parse_hex_as_bignum(a)?;
let b_big = FieldElement::parse_hex_as_bignum(b)?;
Ok(FP2::new_bigs(&a_big, &b_big))
}
impl_group_elem_traits!(G2, GroupG2);
impl_group_elem_serz!(G2, GroupG2, "G2");
impl_group_elem_conversions!(G2, GroupG2, GroupG2_SIZE, G2_COMP_BYTE_SIZE);
impl_group_elem_ops!(G2);
impl_scalar_mul_ops!(G2);
impl_group_element_lookup_table!(G2, G2LookupTable);
impl_optmz_scalar_mul_ops!(G2, GroupG2, G2LookupTable);
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct G2Vector {
elems: Vec<G2>,
}
impl_group_elem_vec_ops!(G2, G2Vector);
impl_group_elem_vec_product_ops!(G2, G2Vector, G2LookupTable);
impl_group_elem_vec_conversions!(G2, G2Vector);
impl G2 {
pub fn binary_scalar_mul(&self, h: &Self, a: &FieldElement, b: &FieldElement) -> Self {
let group_elems = iter::once(self).chain(iter::once(h));
let field_elems = iter::once(a).chain(iter::once(b));
G2Vector::multi_scalar_mul_const_time_without_precomputation(group_elems, field_elems)
.unwrap()
}
pub fn hash_to_curve(dst: &[u8], msg: &[u8]) -> G2 {
let mut u: [FP; 4] = [FP::new(), FP::new(), FP::new(), FP::new()];
hash_to_field(hmac::MC_SHA2, HASH_TYPE, dst, msg, &mut u, 4);
let fp2_1 = FP2::new_fps(&u[0], &u[1]);
let fp2_2 = FP2::new_fps(&u[2], &u[3]);
let mut P = GroupG2::map2point(&fp2_1);
let P1 = GroupG2::map2point(&fp2_2);
P.add(&P1);
P.cfp();
Self { value: P }
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_parse_hex_for_FP2() {
}
#[test]
fn test_parse_bad_hex_for_FP2() {
}
}