use crate::{common::*, curve_arithmetic::*};
use rand::*;
use std::fmt::Formatter;
use std::{
ops::{Deref, Drop},
ptr,
rc::Rc,
sync::atomic,
};
#[repr(transparent)]
#[derive(PartialEq, Eq, Serialize)]
pub struct Secret<T: Field + Serialize> {
secret: T,
}
impl<T: Field + Serialize> Debug for Secret<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.write_str("<Secret>")
}
}
impl<F: Field + Serialize> Secret<F> {
pub fn new(secret: F) -> Self {
Secret { secret }
}
}
impl<F: Field + Serialize> AsRef<F> for Secret<F> {
fn as_ref(&self) -> &F {
&self.secret
}
}
impl<F: Field + Serialize> Deref for Secret<F> {
type Target = F;
fn deref(&self) -> &Self::Target {
&self.secret
}
}
impl<F: Field + Serialize> Drop for Secret<F> {
fn drop(&mut self) {
unsafe { ptr::write_volatile(&mut self.secret, F::zero()) }
atomic::compiler_fence(atomic::Ordering::SeqCst);
}
}
#[derive(Debug, PartialEq, Eq, Serialize, Clone, SerdeBase16Serialize)]
pub struct Value<C: Curve> {
pub value: Rc<Secret<C::Scalar>>,
}
impl<C: Curve> Deref for Value<C> {
type Target = C::Scalar;
fn deref(&self) -> &C::Scalar {
&self.value
}
}
impl<C: Curve> AsRef<C::Scalar> for Value<C> {
fn as_ref(&self) -> &C::Scalar {
&self.value
}
}
impl<C: Curve> From<u64> for Value<C> {
fn from(secret: u64) -> Self {
Self::new(C::scalar_from_u64(secret))
}
}
impl<C: Curve> Value<C> {
pub fn new(secret: C::Scalar) -> Self {
Self {
value: Rc::new(Secret::new(secret)),
}
}
pub fn generate<T: Rng>(csprng: &mut T) -> Value<C> {
Value::new(C::generate_scalar(csprng))
}
pub fn generate_non_zero<T: Rng>(csprng: &mut T) -> Value<C> {
Value::new(C::generate_non_zero_scalar(csprng))
}
#[inline]
pub fn view<T: Curve<Scalar = C::Scalar>>(&self) -> Value<T> {
Value {
value: self.value.clone(),
}
}
}
#[cfg(test)]
mod tests {
use ark_bls12_381::{G1Projective, G2Projective};
use crate::curve_arithmetic::arkworks_instances::ArkGroup;
use super::*;
macro_rules! macro_test_value_to_byte_conversion {
($function_name:ident, $curve_type:path) => {
#[test]
pub fn $function_name() {
let mut csprng = thread_rng();
for _i in 1..20 {
let val = Value::<$curve_type>::generate(&mut csprng);
let res_val2 = serialize_deserialize(&val);
assert!(res_val2.is_ok());
let val2 = res_val2.unwrap();
assert_eq!(val2, val);
}
}
};
}
macro_test_value_to_byte_conversion!(
value_to_byte_conversion_bls12_381_g1_projective,
ArkGroup<G1Projective>
);
macro_test_value_to_byte_conversion!(
value_to_byte_conversion_bls12_381_g2_projective,
ArkGroup<G2Projective>
);
}