use std::{
borrow::Borrow,
ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
};
use clear_on_drop::clear::Clear;
use curve25519_dalek::{
ristretto::{CompressedRistretto, RistrettoPoint},
scalar::Scalar,
traits::{Identity, IsIdentity},
};
use rand_core::{CryptoRng, RngCore};
use subtle::{Choice, ConstantTimeEq};
use crate::{
authenticated_scalar::AuthenticatedScalar,
beaver::SharedValueSource,
error::{MpcError, MpcNetworkError},
macros,
mpc_ristretto::{MpcCompressedRistretto, MpcRistrettoPoint},
mpc_scalar::MpcScalar,
network::MpcNetwork,
BeaverSource, SharedNetwork, Visibility, Visible,
};
#[derive(Debug)]
pub struct AuthenticatedRistretto<N: MpcNetwork + Send, S: SharedValueSource<Scalar>> {
value: MpcRistrettoPoint<N, S>,
mac_share: Option<MpcRistrettoPoint<N, S>>,
key_share: MpcScalar<N, S>,
visibility: Visibility,
}
impl<N: MpcNetwork + Send, S: SharedValueSource<Scalar>> Clone for AuthenticatedRistretto<N, S> {
fn clone(&self) -> Self {
Self {
value: self.value.clone(),
mac_share: self.mac_share.clone(),
key_share: self.key_share.clone(),
visibility: self.visibility,
}
}
}
#[allow(unused_doc_comments, dead_code)]
impl<N: MpcNetwork + Send, S: SharedValueSource<Scalar>> AuthenticatedRistretto<N, S> {
#[inline]
pub fn is_public(&self) -> bool {
self.visibility == Visibility::Public
}
#[inline]
pub(crate) fn is_shared(&self) -> bool {
self.visibility == Visibility::Shared
}
#[inline]
pub fn value(&self) -> &MpcRistrettoPoint<N, S> {
&self.value
}
#[inline]
fn mac(&self) -> Option<MpcRistrettoPoint<N, S>> {
self.mac_share.clone()
}
#[inline]
fn key_share(&self) -> MpcScalar<N, S> {
self.key_share.clone()
}
#[inline]
fn network(&self) -> SharedNetwork<N> {
self.value().network()
}
#[inline]
fn beaver_source(&self) -> BeaverSource<S> {
self.value().beaver_source()
}
#[inline]
pub fn to_ristretto(&self) -> RistrettoPoint {
self.value().value()
}
#[inline]
pub(crate) fn recompute_mac(&mut self) {
self.mac_share = Some(&self.key_share * &self.value)
}
macros::impl_authenticated!(
MpcRistrettoPoint<N, S>, from_public_u64, from_private_u64, from_u64_with_visibility, u64
);
macros::impl_authenticated!(
MpcRistrettoPoint<N, S>, from_public_scalar, from_private_scalar, from_scalar_with_visibility, Scalar
);
macros::impl_authenticated!(
MpcRistrettoPoint<N, S>,
from_public_ristretto_point,
from_private_ristretto_point,
from_ristretto_point_with_visibility,
RistrettoPoint
);
pub fn from_private_mpc_ristretto(
x: MpcRistrettoPoint<N, S>,
key_share: MpcScalar<N, S>,
) -> Self {
Self::from_mpc_ristretto_with_visibility(x, Visibility::Private, key_share)
}
pub fn from_public_mpc_ristretto(
x: MpcRistrettoPoint<N, S>,
key_share: MpcScalar<N, S>,
) -> Self {
Self::from_mpc_ristretto_with_visibility(x, Visibility::Public, key_share)
}
fn from_mpc_ristretto(
x: MpcRistrettoPoint<N, S>,
key_share: MpcScalar<N, S>,
_: SharedNetwork<N>,
_: BeaverSource<S>,
) -> Self {
Self::from_public_mpc_ristretto(x, key_share)
}
pub(crate) fn from_mpc_ristretto_with_visibility(
x: MpcRistrettoPoint<N, S>,
visibility: Visibility,
key_share: MpcScalar<N, S>,
) -> Self {
Self {
value: x,
visibility,
key_share,
mac_share: None, }
}
pub fn random<R: RngCore + CryptoRng>(
rng: &mut R,
key_share: MpcScalar<N, S>,
network: SharedNetwork<N>,
beaver_source: BeaverSource<S>,
) -> Self {
Self {
value: MpcRistrettoPoint::random(rng, network, beaver_source),
visibility: Visibility::Private,
mac_share: None, key_share,
}
}
macros::impl_authenticated!(MpcRistrettoPoint<N, S>, identity);
macros::impl_authenticated!(MpcRistrettoPoint<N, S>, default);
pub fn compress(&self) -> AuthenticatedCompressedRistretto<N, S> {
AuthenticatedCompressedRistretto {
value: self.value().compress(),
visibility: self.visibility,
mac_share: self.mac().map(|val| val.compress()),
key_share: self.key_share(),
}
}
pub fn batch_compress(
points: &[AuthenticatedRistretto<N, S>],
) -> Vec<AuthenticatedCompressedRistretto<N, S>> {
points.iter().map(|point| point.compress()).collect()
}
}
impl<N: MpcNetwork + Send, S: SharedValueSource<Scalar>> AuthenticatedRistretto<N, S> {
pub fn share_secret(
&self,
party_id: u64,
) -> Result<AuthenticatedRistretto<N, S>, MpcNetworkError> {
let my_share = self.value().share_secret(party_id)?;
let my_mac_share = &self.key_share() * &my_share;
Ok(Self {
value: my_share,
visibility: Visibility::Shared,
mac_share: Some(my_mac_share),
key_share: self.key_share(),
})
}
pub fn batch_share_secrets(
party_id: u64,
secrets: &[AuthenticatedRistretto<N, S>],
) -> Result<Vec<AuthenticatedRistretto<N, S>>, MpcNetworkError> {
assert!(
!secrets.is_empty(),
"Cannot batch share secrets of empty vector"
);
let key_share = secrets[0].key_share();
let my_shares = MpcRistrettoPoint::batch_share_secrets(
party_id,
&secrets
.iter()
.map(|secret| secret.value().clone())
.collect::<Vec<MpcRistrettoPoint<_, _>>>(),
)?;
#[allow(clippy::needless_collect)]
let my_mac_shares: Vec<MpcRistrettoPoint<N, S>> = my_shares
.iter()
.map(|share| &key_share.clone() * share)
.collect();
Ok(my_shares
.into_iter()
.zip(my_mac_shares.into_iter())
.map(|(value, mac)| AuthenticatedRistretto {
value,
visibility: Visibility::Shared,
key_share: key_share.clone(),
mac_share: Some(mac),
})
.collect())
}
pub fn open(&self) -> Result<AuthenticatedRistretto<N, S>, MpcNetworkError> {
Ok(Self {
value: self.value().open()?,
visibility: Visibility::Public,
mac_share: None, key_share: self.key_share(),
})
}
pub fn batch_open(
values: &[AuthenticatedRistretto<N, S>],
) -> Result<Vec<AuthenticatedRistretto<N, S>>, MpcNetworkError> {
assert!(!values.is_empty(), "Cannot batch open an empty vector");
let key_share = values[0].key_share();
let opened_values = MpcRistrettoPoint::batch_open(
&values
.iter()
.map(|shared_value| shared_value.value().clone())
.collect::<Vec<MpcRistrettoPoint<_, _>>>(),
)?;
Ok(opened_values
.into_iter()
.map(|value| {
AuthenticatedRistretto {
value,
visibility: Visibility::Public,
key_share: key_share.clone(),
mac_share: None, }
})
.collect())
}
pub fn open_and_authenticate(&self) -> Result<AuthenticatedRistretto<N, S>, MpcError> {
if !self.is_shared() {
return Ok(self.clone());
}
let opened_value = self.value().open().map_err(MpcError::NetworkError)?;
let mac_check_share = &self.key_share * &opened_value - self.mac().unwrap();
if mac_check_share
.commit_and_open()?
.value()
.ne(&RistrettoPoint::identity())
{
return Err(MpcError::AuthenticationError);
}
Ok(Self {
value: opened_value,
visibility: Visibility::Public,
key_share: self.key_share(),
mac_share: None, })
}
pub fn batch_open_and_authenticate(
values: &[AuthenticatedRistretto<N, S>],
) -> Result<Vec<AuthenticatedRistretto<N, S>>, MpcError> {
assert!(
!values.is_empty(),
"Cannot batch open and authenticate an empty vector"
);
let key_share = values[0].key_share();
let opened_values = MpcRistrettoPoint::batch_open(
&values
.iter()
.map(|shared_value| shared_value.value().clone())
.collect::<Vec<MpcRistrettoPoint<_, _>>>(),
)
.map_err(MpcError::NetworkError)?;
let mac_check_shares = opened_values
.iter()
.zip(values.iter())
.map(|(opened_value, original_value)| {
if original_value.is_public() {
MpcRistrettoPoint::identity(
original_value.network(),
original_value.beaver_source(),
)
} else {
&key_share * opened_value - &original_value.mac().unwrap()
}
})
.collect::<Vec<MpcRistrettoPoint<_, _>>>();
MpcRistrettoPoint::batch_commit_and_open(&mac_check_shares)?
.iter()
.try_for_each(|commit_result| {
if commit_result.value().ne(&RistrettoPoint::identity()) {
return Err(MpcError::AuthenticationError);
}
Ok(())
})?;
Ok(opened_values
.into_iter()
.map(|value| AuthenticatedRistretto {
value,
visibility: Visibility::Public,
key_share: key_share.clone(),
mac_share: None, })
.collect::<Vec<AuthenticatedRistretto<_, _>>>())
}
}
impl<N: MpcNetwork + Send, S: SharedValueSource<Scalar>> Visible for AuthenticatedRistretto<N, S> {
fn visibility(&self) -> Visibility {
self.visibility
}
}
impl<N: MpcNetwork + Send, S: SharedValueSource<Scalar>> PartialEq
for AuthenticatedRistretto<N, S>
{
fn eq(&self, other: &Self) -> bool {
self.value().eq(other.value())
}
}
impl<N: MpcNetwork + Send, S: SharedValueSource<Scalar>> Eq for AuthenticatedRistretto<N, S> {}
impl<N: MpcNetwork + Send, S: SharedValueSource<Scalar>> ConstantTimeEq
for AuthenticatedRistretto<N, S>
{
fn ct_eq(&self, other: &Self) -> subtle::Choice {
self.value().ct_eq(other.value())
}
}
impl<N: MpcNetwork + Send, S: SharedValueSource<Scalar>> Clear for AuthenticatedRistretto<N, S> {
#[allow(clippy::needless_borrow)]
fn clear(&mut self) {
(&mut self.value).clear();
(&mut self.mac_share).clear();
(&mut self.key_share).clear();
}
}
impl<'a, N: MpcNetwork + Send, S: SharedValueSource<Scalar>> Mul<&'a AuthenticatedScalar<N, S>>
for &'a AuthenticatedRistretto<N, S>
{
type Output = AuthenticatedRistretto<N, S>;
fn mul(self, rhs: &'a AuthenticatedScalar<N, S>) -> Self::Output {
let value = self.value() * rhs.value();
let mac = {
if self.is_public() && rhs.is_public() {
None
} else if self.is_shared() && rhs.is_shared() {
Some(&value * self.key_share())
} else if rhs.is_public() {
Some(self.mac().unwrap() * rhs.value())
}
else {
Some(rhs.mac().unwrap() * self.value())
}
};
Self::Output {
value,
visibility: Visibility::min_visibility_two(self, rhs),
mac_share: mac,
key_share: self.key_share(),
}
}
}
impl<'a, N: MpcNetwork + Send, S: SharedValueSource<Scalar>> Mul<&'a AuthenticatedRistretto<N, S>>
for &'a AuthenticatedScalar<N, S>
{
type Output = AuthenticatedRistretto<N, S>;
fn mul(self, rhs: &'a AuthenticatedRistretto<N, S>) -> Self::Output {
rhs * self
}
}
macros::impl_operator_variants!(AuthenticatedRistretto<N, S>, Mul, mul, *, AuthenticatedScalar<N, S>);
macros::impl_operator_variants!(AuthenticatedScalar<N, S>, Mul, mul, *, AuthenticatedRistretto<N, S>, Output=AuthenticatedRistretto<N, S>);
macros::impl_wrapper_type!(
AuthenticatedRistretto<N, S>,
MpcScalar<N, S>,
AuthenticatedScalar::from_mpc_scalar,
Mul,
mul,
*,
authenticated=true
);
macros::impl_wrapper_type!(AuthenticatedRistretto<N, S>, Scalar, AuthenticatedScalar::from_public_scalar, Mul, mul, *, authenticated=true);
macros::impl_arithmetic_assign!(AuthenticatedRistretto<N, S>, MulAssign, mul_assign, *, AuthenticatedScalar<N, S>);
macros::impl_arithmetic_assign!(AuthenticatedRistretto<N, S>, MulAssign, mul_assign, *, MpcScalar<N, S>);
macros::impl_arithmetic_assign!(AuthenticatedRistretto<N, S>, MulAssign, mul_assign, *, Scalar);
macros::impl_wrapper_type!(
AuthenticatedScalar<N, S>,
RistrettoPoint,
AuthenticatedRistretto::from_public_ristretto_point,
Mul,
mul,
*,
Output=AuthenticatedRistretto<N, S>,
authenticated=true
);
macros::impl_wrapper_type!(
AuthenticatedScalar<N, S>,
MpcRistrettoPoint<N, S>,
AuthenticatedRistretto::from_mpc_ristretto,
Mul,
mul,
*,
Output=AuthenticatedRistretto<N, S>,
authenticated=true
);
impl<'a, N: MpcNetwork + Send, S: SharedValueSource<Scalar>> Add<&'a AuthenticatedRistretto<N, S>>
for &'a AuthenticatedRistretto<N, S>
{
type Output = AuthenticatedRistretto<N, S>;
fn add(self, rhs: &'a AuthenticatedRistretto<N, S>) -> Self::Output {
if self.is_public() && rhs.is_shared() {
return rhs + self;
}
let mac_share = {
if self.is_public() && rhs.is_public() {
None
} else if rhs.is_public() {
Some(self.mac().unwrap() + &self.key_share() * rhs.value())
} else {
Some(self.mac().unwrap() + rhs.mac().unwrap())
}
};
Self::Output {
value: self.value() + rhs.value(),
visibility: Visibility::min_visibility_two(self, rhs),
mac_share,
key_share: self.key_share(),
}
}
}
macros::impl_operator_variants!(AuthenticatedRistretto<N, S>, Add, add, +, AuthenticatedRistretto<N, S>);
macros::impl_wrapper_type!(
AuthenticatedRistretto<N, S>,
MpcRistrettoPoint<N, S>,
AuthenticatedRistretto::from_mpc_ristretto,
Add,
add,
+,
authenticated=true
);
macros::impl_wrapper_type!(
AuthenticatedRistretto<N, S>,
RistrettoPoint,
AuthenticatedRistretto::from_public_ristretto_point,
Add,
add,
+,
authenticated=true
);
macros::impl_arithmetic_assign!(AuthenticatedRistretto<N, S>, AddAssign, add_assign, +, AuthenticatedRistretto<N, S>);
macros::impl_arithmetic_assign!(AuthenticatedRistretto<N, S>, AddAssign, add_assign, +, MpcRistrettoPoint<N, S>);
macros::impl_arithmetic_assign!(AuthenticatedRistretto<N, S>, AddAssign, add_assign, +, RistrettoPoint);
impl<'a, N: MpcNetwork + Send, S: SharedValueSource<Scalar>> Sub<&'a AuthenticatedRistretto<N, S>>
for &'a AuthenticatedRistretto<N, S>
{
type Output = AuthenticatedRistretto<N, S>;
#[allow(clippy::suspicious_arithmetic_impl)]
fn sub(self, rhs: &'a AuthenticatedRistretto<N, S>) -> Self::Output {
self + rhs.neg()
}
}
macros::impl_operator_variants!(AuthenticatedRistretto<N, S>, Sub, sub, -, AuthenticatedRistretto<N, S>);
macros::impl_wrapper_type!(
AuthenticatedRistretto<N, S>,
MpcRistrettoPoint<N, S>,
AuthenticatedRistretto::from_mpc_ristretto,
Sub,
sub,
-,
authenticated=true
);
macros::impl_wrapper_type!(
AuthenticatedRistretto<N, S>,
RistrettoPoint,
AuthenticatedRistretto::from_public_ristretto_point,
Sub,
sub,
-,
authenticated=true
);
macros::impl_arithmetic_assign!(AuthenticatedRistretto<N, S>, SubAssign, sub_assign, -, AuthenticatedRistretto<N, S>);
macros::impl_arithmetic_assign!(AuthenticatedRistretto<N, S>, SubAssign, sub_assign, -, MpcRistrettoPoint<N, S>);
macros::impl_arithmetic_assign!(AuthenticatedRistretto<N, S>, SubAssign, sub_assign, -, RistrettoPoint);
impl<'a, N: MpcNetwork + Send, S: SharedValueSource<Scalar>> Neg
for &'a AuthenticatedRistretto<N, S>
{
type Output = AuthenticatedRistretto<N, S>;
fn neg(self) -> Self::Output {
Self::Output {
value: self.value().neg(),
visibility: self.visibility(),
mac_share: self.mac().map(|value| value.neg()),
key_share: self.key_share(),
}
}
}
impl<N: MpcNetwork + Send, S: SharedValueSource<Scalar>> Neg for AuthenticatedRistretto<N, S> {
type Output = AuthenticatedRistretto<N, S>;
fn neg(self) -> Self::Output {
(&self).neg()
}
}
impl<N: MpcNetwork + Send, S: SharedValueSource<Scalar>> AuthenticatedRistretto<N, S> {
pub fn multiscalar_mul<I, J>(scalars: I, points: J) -> Self
where
I: IntoIterator,
I::Item: std::borrow::Borrow<AuthenticatedScalar<N, S>>,
J: IntoIterator,
J::Item: std::borrow::Borrow<Self>,
{
let mut peekable = points.into_iter().peekable();
let (key_share, network, beaver_source) = {
let first_elem: &AuthenticatedRistretto<N, S> = peekable.peek().unwrap().borrow();
(
first_elem.key_share(),
first_elem.network(),
first_elem.beaver_source(),
)
};
scalars.into_iter().zip(peekable).fold(
AuthenticatedRistretto::identity(key_share, network, beaver_source),
|acc, pair| acc + pair.0.borrow() * pair.1.borrow(),
)
}
}
#[derive(Debug)]
pub struct AuthenticatedCompressedRistretto<N: MpcNetwork + Send, S: SharedValueSource<Scalar>> {
value: MpcCompressedRistretto<N, S>,
visibility: Visibility,
mac_share: Option<MpcCompressedRistretto<N, S>>,
key_share: MpcScalar<N, S>,
}
impl<N: MpcNetwork + Send, S: SharedValueSource<Scalar>> Clone
for AuthenticatedCompressedRistretto<N, S>
{
fn clone(&self) -> Self {
Self {
value: self.value.clone(),
visibility: self.visibility,
mac_share: self.mac_share.clone(),
key_share: self.key_share.clone(),
}
}
}
impl<N: MpcNetwork + Send, S: SharedValueSource<Scalar>> AuthenticatedCompressedRistretto<N, S> {
pub fn value(&self) -> CompressedRistretto {
self.value.value()
}
pub fn from_public_bytes(
buf: &[u8; 32],
key_share: MpcScalar<N, S>,
network: SharedNetwork<N>,
beaver_source: BeaverSource<S>,
) -> Self {
Self::from_bytes_with_visibility(buf, Visibility::Public, key_share, network, beaver_source)
}
pub fn from_private_bytes(
buf: &[u8; 32],
key_share: MpcScalar<N, S>,
network: SharedNetwork<N>,
beaver_source: BeaverSource<S>,
) -> Self {
Self::from_bytes_with_visibility(
buf,
Visibility::Private,
key_share,
network,
beaver_source,
)
}
pub(crate) fn from_bytes_with_visibility(
buf: &[u8; 32],
visibility: Visibility,
key_share: MpcScalar<N, S>,
network: SharedNetwork<N>,
beaver_source: BeaverSource<S>,
) -> Self {
Self {
value: MpcCompressedRistretto::from_bytes_with_visibility(
buf,
visibility,
network,
beaver_source,
),
visibility,
key_share,
mac_share: None, }
}
pub fn from_public_compressed_ristretto(
value: CompressedRistretto,
key_share: MpcScalar<N, S>,
network: SharedNetwork<N>,
beaver_source: BeaverSource<S>,
) -> Self {
Self::from_compressed_ristretto_with_visibility(
value,
Visibility::Public,
key_share,
network,
beaver_source,
)
}
pub fn from_private_compressed_ristretto(
value: CompressedRistretto,
key_share: MpcScalar<N, S>,
network: SharedNetwork<N>,
beaver_source: BeaverSource<S>,
) -> Self {
Self::from_compressed_ristretto_with_visibility(
value,
Visibility::Private,
key_share,
network,
beaver_source,
)
}
pub(crate) fn from_compressed_ristretto_with_visibility(
value: CompressedRistretto,
visibility: Visibility,
key_share: MpcScalar<N, S>,
network: SharedNetwork<N>,
beaver_source: BeaverSource<S>,
) -> Self {
Self {
value: MpcCompressedRistretto::from_compressed_ristretto_with_visibility(
value,
visibility,
network,
beaver_source,
),
visibility,
key_share,
mac_share: None, }
}
pub fn decompress(&self) -> Option<AuthenticatedRistretto<N, S>> {
let new_mac = match &self.mac_share {
None => None,
Some(val) => Some(val.decompress()?),
};
Some(AuthenticatedRistretto {
value: self.value.decompress()?,
visibility: self.visibility,
mac_share: new_mac,
key_share: self.key_share.clone(),
})
}
pub fn batch_decompress(
points: &[AuthenticatedCompressedRistretto<N, S>],
) -> Option<Vec<AuthenticatedRistretto<N, S>>> {
points.iter().map(|point| point.decompress()).collect()
}
pub fn as_bytes(&self) -> &[u8; 32] {
self.value.as_bytes()
}
pub fn identity(
key_share: MpcScalar<N, S>,
network: SharedNetwork<N>,
beaver_source: BeaverSource<S>,
) -> AuthenticatedCompressedRistretto<N, S> {
AuthenticatedCompressedRistretto {
value: MpcCompressedRistretto::identity(network, beaver_source),
visibility: Visibility::Public,
mac_share: None,
key_share,
}
}
}
impl<N: MpcNetwork + Send, S: SharedValueSource<Scalar>> AuthenticatedCompressedRistretto<N, S> {
pub fn open(&self) -> Result<Self, MpcError> {
Ok(self
.decompress()
.ok_or_else(|| MpcError::ArithmeticError("error decompressing point".to_string()))?
.open()
.map_err(MpcError::NetworkError)?
.compress())
}
pub fn batch_open(points: &[Self]) -> Result<Vec<Self>, MpcError> {
let decompressed = Self::batch_decompress(points)
.ok_or_else(|| MpcError::ArithmeticError("error decompressing points".to_string()))?;
let opened =
AuthenticatedRistretto::batch_open(&decompressed).map_err(MpcError::NetworkError)?;
Ok(AuthenticatedRistretto::batch_compress(&opened))
}
pub fn open_and_authenticate(&self) -> Result<Self, MpcError> {
Ok(self
.decompress()
.ok_or_else(|| MpcError::ArithmeticError("error decompressing point".to_string()))?
.open_and_authenticate()?
.compress())
}
pub fn batch_open_and_authenticate(points: &[Self]) -> Result<Vec<Self>, MpcError> {
let decompressed = Self::batch_decompress(points)
.ok_or_else(|| MpcError::ArithmeticError("error decompressing points".to_string()))?;
let opened = AuthenticatedRistretto::batch_open_and_authenticate(&decompressed)?;
Ok(AuthenticatedRistretto::batch_compress(&opened))
}
}
impl<N: MpcNetwork + Send, S: SharedValueSource<Scalar>> IsIdentity
for AuthenticatedCompressedRistretto<N, S>
{
fn is_identity(&self) -> bool {
self.value.is_identity()
}
}
impl<N: MpcNetwork + Send, S: SharedValueSource<Scalar>> ConstantTimeEq
for AuthenticatedCompressedRistretto<N, S>
{
fn ct_eq(&self, other: &Self) -> Choice {
self.value.ct_eq(&other.value)
}
}
impl<N: MpcNetwork + Send, S: SharedValueSource<Scalar>> Clear
for AuthenticatedCompressedRistretto<N, S>
{
#[allow(clippy::needless_borrow)]
fn clear(&mut self) {
(&mut self.value).clear();
}
}
#[cfg(test)]
mod authenticated_ristretto_tests {
use std::{cell::RefCell, rc::Rc};
use clear_on_drop::clear::Clear;
use curve25519_dalek::{ristretto::RistrettoPoint, scalar::Scalar, traits::Identity};
use crate::{
beaver::DummySharedScalarSource, mpc_ristretto::MpcRistrettoPoint, mpc_scalar::MpcScalar,
network::dummy_network::DummyMpcNetwork,
};
use super::AuthenticatedRistretto;
#[test]
fn test_clear() {
let network = Rc::new(RefCell::new(DummyMpcNetwork::new()));
let beaver_source = Rc::new(RefCell::new(DummySharedScalarSource::new()));
let key_share = MpcScalar::from_public_u64(2, network.clone(), beaver_source.clone());
let mut value = AuthenticatedRistretto::from_public_u64(
3,
key_share,
network.clone(),
beaver_source.clone(),
);
value.mac_share = Some(MpcRistrettoPoint::from_public_u64(
5,
network,
beaver_source,
));
#[allow(clippy::needless_borrow)]
(&mut value).clear();
assert_eq!(value.to_ristretto(), RistrettoPoint::identity());
assert_eq!(value.mac(), None);
assert_eq!(value.key_share().to_scalar(), Scalar::zero())
}
}