mirror of
https://github.com/zama-ai/tfhe-rs.git
synced 2026-01-08 22:28:01 -05:00
refactor(zk): handle compression without canonical serialize
This commit is contained in:
committed by
Nicolas Sarlin
parent
c9be958d1a
commit
835cc6d9b0
@@ -30,3 +30,4 @@ tfhe-versionable = { version = "0.3.0", path = "../utils/tfhe-versionable" }
|
||||
[dev-dependencies]
|
||||
serde_json = "~1.0"
|
||||
itertools = "0.11.0"
|
||||
bincode = "1.3.3"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use tfhe_versionable::VersionsDispatch;
|
||||
|
||||
use crate::curve_api::Curve;
|
||||
use crate::proofs::pke::Proof as PKEv1Proof;
|
||||
use crate::proofs::pke_v2::Proof as PKEv2Proof;
|
||||
use crate::curve_api::{Compressible, Curve};
|
||||
use crate::proofs::pke::{CompressedProof as PKEv1CompressedProof, Proof as PKEv1Proof};
|
||||
use crate::proofs::pke_v2::{CompressedProof as PKEv2CompressedProof, Proof as PKEv2Proof};
|
||||
use crate::proofs::GroupElements;
|
||||
use crate::serialization::{
|
||||
SerializableAffine, SerializableCubicExtField, SerializableFp, SerializableFp2,
|
||||
@@ -34,14 +34,32 @@ pub type SerializableG1AffineVersions = SerializableAffineVersions<SerializableF
|
||||
pub type SerializableG2AffineVersions = SerializableAffineVersions<SerializableFp2>;
|
||||
pub type SerializableFp12Versions = SerializableQuadExtFieldVersions<SerializableFp6>;
|
||||
|
||||
#[derive(VersionsDispatch)]
|
||||
pub enum PKEv1ProofVersions<G: Curve> {
|
||||
V0(PKEv1Proof<G>),
|
||||
}
|
||||
|
||||
#[derive(VersionsDispatch)]
|
||||
pub enum PKEv2ProofVersions<G: Curve> {
|
||||
V0(PKEv2Proof<G>),
|
||||
}
|
||||
|
||||
#[derive(VersionsDispatch)]
|
||||
pub enum PKEv1ProofVersions<G: Curve> {
|
||||
V0(PKEv1Proof<G>),
|
||||
pub enum PKEv1CompressedProofVersions<G: Curve>
|
||||
where
|
||||
G::G1: Compressible,
|
||||
G::G2: Compressible,
|
||||
{
|
||||
V0(PKEv1CompressedProof<G>),
|
||||
}
|
||||
|
||||
#[derive(VersionsDispatch)]
|
||||
pub enum PKEv2CompressedProofVersions<G: Curve>
|
||||
where
|
||||
G::G1: Compressible,
|
||||
G::G2: Compressible,
|
||||
{
|
||||
V0(PKEv2CompressedProof<G>),
|
||||
}
|
||||
|
||||
#[derive(VersionsDispatch)]
|
||||
|
||||
@@ -3,7 +3,6 @@ use ark_ec::short_weierstrass::Affine;
|
||||
use ark_ec::{AdditiveGroup as Group, CurveGroup, VariableBaseMSM};
|
||||
use ark_ff::{BigInt, Field, MontFp, Zero};
|
||||
use ark_poly::univariate::DensePolynomial;
|
||||
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
|
||||
use core::fmt;
|
||||
use core::ops::{Add, AddAssign, Div, Mul, Neg, Sub, SubAssign};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -108,9 +107,7 @@ pub trait CurveGroupOps<Zp>:
|
||||
+ Sync
|
||||
+ core::fmt::Debug
|
||||
+ serde::Serialize
|
||||
+ for<'de> serde::Deserialize<'de>
|
||||
+ CanonicalSerialize
|
||||
+ CanonicalDeserialize;
|
||||
+ for<'de> serde::Deserialize<'de>;
|
||||
|
||||
fn projective(affine: Self::Affine) -> Self;
|
||||
|
||||
@@ -121,6 +118,16 @@ pub trait CurveGroupOps<Zp>:
|
||||
fn normalize(self) -> Self::Affine;
|
||||
}
|
||||
|
||||
/// Mark that an element can be compressed, by storing only the 'x' coordinates of the affine
|
||||
/// representation and getting the 'y' from the curve.
|
||||
pub trait Compressible: Sized {
|
||||
type Compressed;
|
||||
type UncompressError;
|
||||
|
||||
fn compress(&self) -> Self::Compressed;
|
||||
fn uncompress(compressed: Self::Compressed) -> Result<Self, Self::UncompressError>;
|
||||
}
|
||||
|
||||
pub trait PairingGroupOps<Zp, G1, G2>:
|
||||
Copy
|
||||
+ Send
|
||||
@@ -139,8 +146,8 @@ pub trait PairingGroupOps<Zp, G1, G2>:
|
||||
|
||||
pub trait Curve: Clone {
|
||||
type Zp: FieldOps;
|
||||
type G1: CurveGroupOps<Self::Zp> + CanonicalSerialize + CanonicalDeserialize;
|
||||
type G2: CurveGroupOps<Self::Zp> + CanonicalSerialize + CanonicalDeserialize;
|
||||
type G1: CurveGroupOps<Self::Zp>;
|
||||
type G2: CurveGroupOps<Self::Zp>;
|
||||
type Gt: PairingGroupOps<Self::Zp, Self::G1, Self::G2>;
|
||||
}
|
||||
|
||||
|
||||
@@ -41,19 +41,7 @@ mod g1 {
|
||||
|
||||
use super::*;
|
||||
|
||||
#[derive(
|
||||
Copy,
|
||||
Clone,
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
CanonicalSerialize,
|
||||
CanonicalDeserialize,
|
||||
Hash,
|
||||
Versionize,
|
||||
)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Hash, Versionize)]
|
||||
#[serde(try_from = "SerializableG1Affine", into = "SerializableG1Affine")]
|
||||
#[versionize(
|
||||
SerializableG1AffineVersions,
|
||||
@@ -67,7 +55,7 @@ mod g1 {
|
||||
|
||||
impl From<G1Affine> for SerializableAffine<SerializableFp> {
|
||||
fn from(value: G1Affine) -> Self {
|
||||
SerializableAffine::compressed(value.inner)
|
||||
SerializableAffine::uncompressed(value.inner)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,6 +69,19 @@ mod g1 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Compressible for G1Affine {
|
||||
type Compressed = SerializableG1Affine;
|
||||
type UncompressError = InvalidSerializedAffineError;
|
||||
|
||||
fn compress(&self) -> SerializableG1Affine {
|
||||
SerializableAffine::compressed(self.inner)
|
||||
}
|
||||
|
||||
fn uncompress(compressed: Self::Compressed) -> Result<Self, Self::UncompressError> {
|
||||
compressed.try_into()
|
||||
}
|
||||
}
|
||||
|
||||
impl G1Affine {
|
||||
pub fn multi_mul_scalar(bases: &[Self], scalars: &[Zp]) -> G1 {
|
||||
// SAFETY: interpreting a `repr(transparent)` pointer as its contents.
|
||||
@@ -96,18 +97,7 @@ mod g1 {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Copy,
|
||||
Clone,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
Hash,
|
||||
CanonicalSerialize,
|
||||
CanonicalDeserialize,
|
||||
Versionize,
|
||||
)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Hash, Versionize)]
|
||||
#[serde(try_from = "SerializableG1Affine", into = "SerializableG1Affine")]
|
||||
#[versionize(
|
||||
SerializableG1AffineVersions,
|
||||
@@ -121,11 +111,11 @@ mod g1 {
|
||||
|
||||
impl From<G1> for SerializableAffine<SerializableFp> {
|
||||
fn from(value: G1) -> Self {
|
||||
SerializableAffine::compressed(value.inner.into_affine())
|
||||
SerializableAffine::uncompressed(value.inner.into_affine())
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<SerializableAffine<SerializableFp>> for G1 {
|
||||
impl TryFrom<SerializableG1Affine> for G1 {
|
||||
type Error = InvalidSerializedAffineError;
|
||||
|
||||
fn try_from(value: SerializableAffine<SerializableFp>) -> Result<Self, Self::Error> {
|
||||
@@ -135,6 +125,19 @@ mod g1 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Compressible for G1 {
|
||||
type Compressed = SerializableG1Affine;
|
||||
type UncompressError = InvalidSerializedAffineError;
|
||||
|
||||
fn compress(&self) -> SerializableG1Affine {
|
||||
SerializableAffine::compressed(self.inner.into_affine())
|
||||
}
|
||||
|
||||
fn uncompress(compressed: Self::Compressed) -> Result<Self, Self::UncompressError> {
|
||||
compressed.try_into()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for G1 {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("G1")
|
||||
@@ -266,19 +269,7 @@ mod g2 {
|
||||
|
||||
use super::*;
|
||||
|
||||
#[derive(
|
||||
Copy,
|
||||
Clone,
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
CanonicalSerialize,
|
||||
CanonicalDeserialize,
|
||||
Hash,
|
||||
Versionize,
|
||||
)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Hash, Versionize)]
|
||||
#[serde(try_from = "SerializableG2Affine", into = "SerializableG2Affine")]
|
||||
#[versionize(
|
||||
SerializableG2AffineVersions,
|
||||
@@ -292,7 +283,7 @@ mod g2 {
|
||||
|
||||
impl From<G2Affine> for SerializableAffine<SerializableFp2> {
|
||||
fn from(value: G2Affine) -> Self {
|
||||
SerializableAffine::compressed(value.inner)
|
||||
SerializableAffine::uncompressed(value.inner)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -306,6 +297,20 @@ mod g2 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Compressible for G2Affine {
|
||||
type Compressed = SerializableG2Affine;
|
||||
|
||||
type UncompressError = InvalidSerializedAffineError;
|
||||
|
||||
fn compress(&self) -> SerializableAffine<SerializableFp2> {
|
||||
SerializableAffine::compressed(self.inner)
|
||||
}
|
||||
|
||||
fn uncompress(compressed: Self::Compressed) -> Result<Self, Self::UncompressError> {
|
||||
compressed.try_into()
|
||||
}
|
||||
}
|
||||
|
||||
impl G2Affine {
|
||||
pub fn multi_mul_scalar(bases: &[Self], scalars: &[Zp]) -> G2 {
|
||||
// SAFETY: interpreting a `repr(transparent)` pointer as its contents.
|
||||
@@ -321,18 +326,7 @@ mod g2 {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Copy,
|
||||
Clone,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
CanonicalSerialize,
|
||||
CanonicalDeserialize,
|
||||
Hash,
|
||||
Versionize,
|
||||
)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Hash, Versionize)]
|
||||
#[serde(try_from = "SerializableG2Affine", into = "SerializableG2Affine")]
|
||||
#[versionize(
|
||||
SerializableG2AffineVersions,
|
||||
@@ -344,13 +338,13 @@ mod g2 {
|
||||
pub(crate) inner: ark_bls12_381::G2Projective,
|
||||
}
|
||||
|
||||
impl From<G2> for SerializableAffine<SerializableFp2> {
|
||||
impl From<G2> for SerializableG2Affine {
|
||||
fn from(value: G2) -> Self {
|
||||
SerializableAffine::compressed(value.inner.into_affine())
|
||||
SerializableAffine::uncompressed(value.inner.into_affine())
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<SerializableAffine<SerializableFp2>> for G2 {
|
||||
impl TryFrom<SerializableG2Affine> for G2 {
|
||||
type Error = InvalidSerializedAffineError;
|
||||
|
||||
fn try_from(value: SerializableAffine<SerializableFp2>) -> Result<Self, Self::Error> {
|
||||
@@ -360,6 +354,20 @@ mod g2 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Compressible for G2 {
|
||||
type Compressed = SerializableG2Affine;
|
||||
|
||||
type UncompressError = InvalidSerializedAffineError;
|
||||
|
||||
fn compress(&self) -> SerializableAffine<SerializableFp2> {
|
||||
SerializableAffine::compressed(self.inner.into_affine())
|
||||
}
|
||||
|
||||
fn uncompress(compressed: Self::Compressed) -> Result<Self, Self::UncompressError> {
|
||||
compressed.try_into()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for G2 {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
#[allow(dead_code)]
|
||||
@@ -998,6 +1006,26 @@ mod tests {
|
||||
assert_eq!(g_hat_cur, g_hat_cur2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_compressed_serialization() {
|
||||
let rng = &mut StdRng::seed_from_u64(0);
|
||||
let alpha = Zp::rand(rng);
|
||||
let g_cur = G1::GENERATOR.mul_scalar(alpha);
|
||||
let g_hat_cur = G2::GENERATOR.mul_scalar(alpha);
|
||||
|
||||
let g_cur2 = G1::uncompress(
|
||||
serde_json::from_str(&serde_json::to_string(&g_cur.compress()).unwrap()).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(g_cur, g_cur2);
|
||||
|
||||
let g_hat_cur2 = G2::uncompress(
|
||||
serde_json::from_str(&serde_json::to_string(&g_hat_cur.compress()).unwrap()).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(g_hat_cur, g_hat_cur2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hasher_and_eq() {
|
||||
// we need to make sure if the points are the same
|
||||
|
||||
@@ -41,19 +41,7 @@ mod g1 {
|
||||
|
||||
use super::*;
|
||||
|
||||
#[derive(
|
||||
Copy,
|
||||
Clone,
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
CanonicalSerialize,
|
||||
CanonicalDeserialize,
|
||||
Hash,
|
||||
Versionize,
|
||||
)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Hash, Versionize)]
|
||||
#[serde(try_from = "SerializableG1Affine", into = "SerializableG1Affine")]
|
||||
#[versionize(
|
||||
SerializableG1AffineVersions,
|
||||
@@ -67,7 +55,7 @@ mod g1 {
|
||||
|
||||
impl From<G1Affine> for SerializableAffine<SerializableFp> {
|
||||
fn from(value: G1Affine) -> Self {
|
||||
SerializableAffine::compressed(value.inner)
|
||||
SerializableAffine::uncompressed(value.inner)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,6 +69,20 @@ mod g1 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Compressible for G1Affine {
|
||||
type Compressed = SerializableG1Affine;
|
||||
|
||||
type UncompressError = InvalidSerializedAffineError;
|
||||
|
||||
fn compress(&self) -> Self::Compressed {
|
||||
SerializableAffine::compressed(self.inner)
|
||||
}
|
||||
|
||||
fn uncompress(compressed: Self::Compressed) -> Result<Self, Self::UncompressError> {
|
||||
compressed.try_into()
|
||||
}
|
||||
}
|
||||
|
||||
impl G1Affine {
|
||||
#[track_caller]
|
||||
pub fn multi_mul_scalar(bases: &[Self], scalars: &[Zp]) -> G1 {
|
||||
@@ -97,18 +99,7 @@ mod g1 {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Copy,
|
||||
Clone,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
CanonicalSerialize,
|
||||
CanonicalDeserialize,
|
||||
Hash,
|
||||
Versionize,
|
||||
)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Hash, Versionize)]
|
||||
#[serde(try_from = "SerializableG1Affine", into = "SerializableG1Affine")]
|
||||
#[versionize(
|
||||
SerializableG1AffineVersions,
|
||||
@@ -120,22 +111,36 @@ mod g1 {
|
||||
pub(crate) inner: crate::curve_446::g1::G1Projective,
|
||||
}
|
||||
|
||||
impl From<G1> for SerializableAffine<SerializableFp> {
|
||||
impl From<G1> for SerializableG1Affine {
|
||||
fn from(value: G1) -> Self {
|
||||
SerializableAffine::compressed(value.inner.into_affine())
|
||||
SerializableAffine::uncompressed(value.inner.into_affine())
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<SerializableAffine<SerializableFp>> for G1 {
|
||||
impl TryFrom<SerializableG1Affine> for G1 {
|
||||
type Error = InvalidSerializedAffineError;
|
||||
|
||||
fn try_from(value: SerializableAffine<SerializableFp>) -> Result<Self, Self::Error> {
|
||||
fn try_from(value: SerializableG1Affine) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
inner: Affine::try_from(value)?.into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Compressible for G1 {
|
||||
type Compressed = SerializableG1Affine;
|
||||
|
||||
type UncompressError = InvalidSerializedAffineError;
|
||||
|
||||
fn compress(&self) -> Self::Compressed {
|
||||
SerializableAffine::compressed(self.inner.into_affine())
|
||||
}
|
||||
|
||||
fn uncompress(compressed: Self::Compressed) -> Result<Self, Self::UncompressError> {
|
||||
compressed.try_into()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for G1 {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("G1")
|
||||
@@ -268,19 +273,7 @@ mod g2 {
|
||||
use super::*;
|
||||
use crate::serialization::InvalidSerializedAffineError;
|
||||
|
||||
#[derive(
|
||||
Copy,
|
||||
Clone,
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
CanonicalSerialize,
|
||||
CanonicalDeserialize,
|
||||
Hash,
|
||||
Versionize,
|
||||
)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Hash, Versionize)]
|
||||
#[serde(try_from = "SerializableG2Affine", into = "SerializableG2Affine")]
|
||||
#[versionize(
|
||||
SerializableG2AffineVersions,
|
||||
@@ -292,22 +285,36 @@ mod g2 {
|
||||
pub(crate) inner: crate::curve_446::g2::G2Affine,
|
||||
}
|
||||
|
||||
impl From<G2Affine> for SerializableAffine<SerializableFp2> {
|
||||
impl From<G2Affine> for SerializableG2Affine {
|
||||
fn from(value: G2Affine) -> Self {
|
||||
SerializableAffine::compressed(value.inner)
|
||||
SerializableAffine::uncompressed(value.inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<SerializableAffine<SerializableFp2>> for G2Affine {
|
||||
impl TryFrom<SerializableG2Affine> for G2Affine {
|
||||
type Error = InvalidSerializedAffineError;
|
||||
|
||||
fn try_from(value: SerializableAffine<SerializableFp2>) -> Result<Self, Self::Error> {
|
||||
fn try_from(value: SerializableG2Affine) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
inner: value.try_into()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Compressible for G2Affine {
|
||||
type Compressed = SerializableG2Affine;
|
||||
|
||||
type UncompressError = InvalidSerializedAffineError;
|
||||
|
||||
fn compress(&self) -> Self::Compressed {
|
||||
SerializableAffine::compressed(self.inner)
|
||||
}
|
||||
|
||||
fn uncompress(compressed: Self::Compressed) -> Result<Self, Self::UncompressError> {
|
||||
compressed.try_into()
|
||||
}
|
||||
}
|
||||
|
||||
impl G2Affine {
|
||||
#[track_caller]
|
||||
pub fn multi_mul_scalar(bases: &[Self], scalars: &[Zp]) -> G2 {
|
||||
@@ -414,18 +421,7 @@ mod g2 {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Copy,
|
||||
Clone,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
CanonicalSerialize,
|
||||
CanonicalDeserialize,
|
||||
Hash,
|
||||
Versionize,
|
||||
)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Hash, Versionize)]
|
||||
#[serde(try_from = "SerializableG2Affine", into = "SerializableG2Affine")]
|
||||
#[versionize(
|
||||
SerializableG2AffineVersions,
|
||||
@@ -437,22 +433,36 @@ mod g2 {
|
||||
pub(crate) inner: crate::curve_446::g2::G2Projective,
|
||||
}
|
||||
|
||||
impl From<G2> for SerializableAffine<SerializableFp2> {
|
||||
impl From<G2> for SerializableG2Affine {
|
||||
fn from(value: G2) -> Self {
|
||||
SerializableAffine::compressed(value.inner.into_affine())
|
||||
SerializableAffine::uncompressed(value.inner.into_affine())
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<SerializableAffine<SerializableFp2>> for G2 {
|
||||
impl TryFrom<SerializableG2Affine> for G2 {
|
||||
type Error = InvalidSerializedAffineError;
|
||||
|
||||
fn try_from(value: SerializableAffine<SerializableFp2>) -> Result<Self, Self::Error> {
|
||||
fn try_from(value: SerializableG2Affine) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
inner: Affine::try_from(value)?.into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Compressible for G2 {
|
||||
type Compressed = SerializableG2Affine;
|
||||
|
||||
type UncompressError = InvalidSerializedAffineError;
|
||||
|
||||
fn compress(&self) -> Self::Compressed {
|
||||
SerializableAffine::compressed(self.inner.into_affine())
|
||||
}
|
||||
|
||||
fn uncompress(compressed: Self::Compressed) -> Result<Self, Self::UncompressError> {
|
||||
compressed.try_into()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for G2 {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
#[allow(dead_code)]
|
||||
@@ -1322,6 +1332,26 @@ mod tests {
|
||||
assert_eq!(g_hat_cur, g_hat_cur2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_compressed_serialization() {
|
||||
let rng = &mut StdRng::seed_from_u64(0);
|
||||
let alpha = Zp::rand(rng);
|
||||
let g_cur = G1::GENERATOR.mul_scalar(alpha);
|
||||
let g_hat_cur = G2::GENERATOR.mul_scalar(alpha);
|
||||
|
||||
let g_cur2 = G1::uncompress(
|
||||
serde_json::from_str(&serde_json::to_string(&g_cur.compress()).unwrap()).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(g_cur, g_cur2);
|
||||
|
||||
let g_hat_cur2 = G2::uncompress(
|
||||
serde_json::from_str(&serde_json::to_string(&g_hat_cur.compress()).unwrap()).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(g_hat_cur, g_hat_cur2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hasher_and_eq() {
|
||||
// we need to make sure if the points are the same
|
||||
|
||||
@@ -1,48 +1,17 @@
|
||||
use ark_serialize::{
|
||||
CanonicalDeserialize, CanonicalSerialize, Compress, SerializationError, Valid, Validate,
|
||||
};
|
||||
use rand::{Rng, RngCore};
|
||||
use std::ops::{Index, IndexMut};
|
||||
|
||||
use tfhe_versionable::{Unversionize, Versionize, VersionizeOwned};
|
||||
|
||||
use crate::backward_compatibility::GroupElementsVersions;
|
||||
use crate::curve_api::{Curve, CurveGroupOps, FieldOps, PairingGroupOps};
|
||||
|
||||
impl<T: Valid> Valid for OneBased<T> {
|
||||
fn check(&self) -> Result<(), SerializationError> {
|
||||
self.0.check()
|
||||
}
|
||||
}
|
||||
use crate::curve_api::{Compressible, Curve, CurveGroupOps, FieldOps, PairingGroupOps};
|
||||
use crate::serialization::{
|
||||
InvalidSerializedGroupElementsError, SerializableG1Affine, SerializableG2Affine,
|
||||
SerializableGroupElements,
|
||||
};
|
||||
use core::ops::{Index, IndexMut};
|
||||
use rand::{Rng, RngCore};
|
||||
use tfhe_versionable::{Unversionize, Versionize, VersionizeOwned};
|
||||
|
||||
#[derive(Clone, Copy, Debug, serde::Serialize, serde::Deserialize)]
|
||||
#[repr(transparent)]
|
||||
pub(crate) struct OneBased<T: ?Sized>(T);
|
||||
|
||||
impl<T: CanonicalDeserialize> CanonicalDeserialize for OneBased<T> {
|
||||
fn deserialize_with_mode<R: ark_serialize::Read>(
|
||||
reader: R,
|
||||
compress: Compress,
|
||||
validate: Validate,
|
||||
) -> Result<Self, SerializationError> {
|
||||
T::deserialize_with_mode(reader, compress, validate).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: CanonicalSerialize> CanonicalSerialize for OneBased<T> {
|
||||
fn serialize_with_mode<W: ark_serialize::Write>(
|
||||
&self,
|
||||
writer: W,
|
||||
compress: Compress,
|
||||
) -> Result<(), SerializationError> {
|
||||
self.0.serialize_with_mode(writer, compress)
|
||||
}
|
||||
|
||||
fn serialized_size(&self, compress: Compress) -> usize {
|
||||
self.0.serialized_size(compress)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: these impl could be removed by adding support for `repr(transparent)` in tfhe-versionable
|
||||
impl<T: Versionize> Versionize for OneBased<T> {
|
||||
type Versioned<'vers> = T::Versioned<'vers>
|
||||
@@ -110,15 +79,7 @@ impl<T: ?Sized + IndexMut<usize>> IndexMut<usize> for OneBased<T> {
|
||||
|
||||
pub type Affine<Zp, Group> = <Group as CurveGroupOps<Zp>>::Affine;
|
||||
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
serde::Serialize,
|
||||
serde::Deserialize,
|
||||
CanonicalSerialize,
|
||||
CanonicalDeserialize,
|
||||
Versionize,
|
||||
)]
|
||||
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, Versionize)]
|
||||
#[serde(bound(
|
||||
deserialize = "G: Curve, G::G1: serde::Deserialize<'de>, G::G2: serde::Deserialize<'de>",
|
||||
serialize = "G: Curve, G::G1: serde::Serialize, G::G2: serde::Serialize"
|
||||
@@ -177,6 +138,34 @@ impl<G: Curve> GroupElements<G> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<G: Curve> Compressible for GroupElements<G>
|
||||
where
|
||||
GroupElements<G>:
|
||||
TryFrom<SerializableGroupElements, Error = InvalidSerializedGroupElementsError>,
|
||||
<G::G1 as CurveGroupOps<G::Zp>>::Affine: Compressible<Compressed = SerializableG1Affine>,
|
||||
<G::G2 as CurveGroupOps<G::Zp>>::Affine: Compressible<Compressed = SerializableG2Affine>,
|
||||
{
|
||||
type Compressed = SerializableGroupElements;
|
||||
|
||||
type UncompressError = InvalidSerializedGroupElementsError;
|
||||
|
||||
fn compress(&self) -> Self::Compressed {
|
||||
let mut g_list = Vec::new();
|
||||
let mut g_hat_list = Vec::new();
|
||||
for idx in 0..self.message_len {
|
||||
g_list.push(self.g_list[(idx * 2) + 1].compress());
|
||||
g_list.push(self.g_list[(idx * 2) + 2].compress());
|
||||
g_hat_list.push(self.g_hat_list[idx + 1].compress())
|
||||
}
|
||||
|
||||
SerializableGroupElements { g_list, g_hat_list }
|
||||
}
|
||||
|
||||
fn uncompress(compressed: Self::Compressed) -> Result<Self, Self::UncompressError> {
|
||||
Self::try_from(compressed)
|
||||
}
|
||||
}
|
||||
|
||||
pub const HASH_METADATA_LEN_BYTES: usize = 256;
|
||||
|
||||
pub mod binary;
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
// TODO: refactor copy-pasted code in proof/verify
|
||||
|
||||
use crate::backward_compatibility::{PKEv1ProofVersions, SerializablePKEv1PublicParamsVersions};
|
||||
use crate::backward_compatibility::{
|
||||
PKEv1CompressedProofVersions, PKEv1ProofVersions, SerializablePKEv1PublicParamsVersions,
|
||||
};
|
||||
use crate::serialization::{
|
||||
InvalidSerializedPublicParamsError, SerializableGroupElements, SerializablePKEv1PublicParams,
|
||||
try_vec_to_array, InvalidSerializedAffineError, InvalidSerializedPublicParamsError,
|
||||
SerializableGroupElements, SerializablePKEv1PublicParams,
|
||||
};
|
||||
|
||||
use super::*;
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
|
||||
use rayon::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::error::Error;
|
||||
@@ -18,7 +20,7 @@ fn bit_iter(x: u64, nbits: u32) -> impl Iterator<Item = bool> {
|
||||
(0..nbits).map(move |idx| ((x >> idx) & 1) != 0)
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, CanonicalSerialize, CanonicalDeserialize)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[serde(
|
||||
try_from = "SerializablePKEv1PublicParams",
|
||||
into = "SerializablePKEv1PublicParams",
|
||||
@@ -92,6 +94,96 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<G: Curve> Compressible for PublicParams<G>
|
||||
where
|
||||
GroupElements<G>: Compressible<
|
||||
Compressed = SerializableGroupElements,
|
||||
UncompressError = InvalidSerializedGroupElementsError,
|
||||
>,
|
||||
{
|
||||
type Compressed = SerializablePKEv1PublicParams;
|
||||
|
||||
type UncompressError = InvalidSerializedPublicParamsError;
|
||||
|
||||
fn compress(&self) -> Self::Compressed {
|
||||
let PublicParams {
|
||||
g_lists,
|
||||
big_d,
|
||||
n,
|
||||
d,
|
||||
k,
|
||||
b,
|
||||
b_r,
|
||||
q,
|
||||
t,
|
||||
msbs_zero_padding_bit_count,
|
||||
hash,
|
||||
hash_t,
|
||||
hash_agg,
|
||||
hash_lmap,
|
||||
hash_z,
|
||||
hash_w,
|
||||
} = self;
|
||||
SerializablePKEv1PublicParams {
|
||||
g_lists: g_lists.compress(),
|
||||
big_d: *big_d,
|
||||
n: *n,
|
||||
d: *d,
|
||||
k: *k,
|
||||
b: *b,
|
||||
b_r: *b_r,
|
||||
q: *q,
|
||||
t: *t,
|
||||
msbs_zero_padding_bit_count: *msbs_zero_padding_bit_count,
|
||||
hash: hash.to_vec(),
|
||||
hash_t: hash_t.to_vec(),
|
||||
hash_agg: hash_agg.to_vec(),
|
||||
hash_lmap: hash_lmap.to_vec(),
|
||||
hash_z: hash_z.to_vec(),
|
||||
hash_w: hash_w.to_vec(),
|
||||
}
|
||||
}
|
||||
|
||||
fn uncompress(compressed: Self::Compressed) -> Result<Self, Self::UncompressError> {
|
||||
let SerializablePKEv1PublicParams {
|
||||
g_lists,
|
||||
big_d,
|
||||
n,
|
||||
d,
|
||||
k,
|
||||
b,
|
||||
b_r,
|
||||
q,
|
||||
t,
|
||||
msbs_zero_padding_bit_count,
|
||||
hash,
|
||||
hash_t,
|
||||
hash_agg,
|
||||
hash_lmap,
|
||||
hash_z,
|
||||
hash_w,
|
||||
} = compressed;
|
||||
Ok(Self {
|
||||
g_lists: GroupElements::uncompress(g_lists)?,
|
||||
big_d,
|
||||
n,
|
||||
d,
|
||||
k,
|
||||
b,
|
||||
b_r,
|
||||
q,
|
||||
t,
|
||||
msbs_zero_padding_bit_count,
|
||||
hash: try_vec_to_array(hash)?,
|
||||
hash_t: try_vec_to_array(hash_t)?,
|
||||
hash_agg: try_vec_to_array(hash_agg)?,
|
||||
hash_lmap: try_vec_to_array(hash_lmap)?,
|
||||
hash_z: try_vec_to_array(hash_z)?,
|
||||
hash_w: try_vec_to_array(hash_w)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<G: Curve> PublicParams<G> {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn from_vec(
|
||||
@@ -153,6 +245,78 @@ pub struct Proof<G: Curve> {
|
||||
pi_kzg: Option<G::G1>,
|
||||
}
|
||||
|
||||
type CompressedG2<G> = <<G as Curve>::G2 as Compressible>::Compressed;
|
||||
type CompressedG1<G> = <<G as Curve>::G1 as Compressible>::Compressed;
|
||||
|
||||
#[derive(Serialize, Deserialize, Versionize)]
|
||||
#[serde(bound(
|
||||
deserialize = "G: Curve, CompressedG1<G>: serde::Deserialize<'de>, CompressedG2<G>: serde::Deserialize<'de>",
|
||||
serialize = "G: Curve, CompressedG1<G>: serde::Serialize, CompressedG2<G>: serde::Serialize"
|
||||
))]
|
||||
#[versionize(PKEv1CompressedProofVersions)]
|
||||
pub struct CompressedProof<G: Curve>
|
||||
where
|
||||
G::G1: Compressible,
|
||||
G::G2: Compressible,
|
||||
{
|
||||
c_hat: CompressedG2<G>,
|
||||
c_y: CompressedG1<G>,
|
||||
pi: CompressedG1<G>,
|
||||
c_hat_t: Option<CompressedG2<G>>,
|
||||
c_h: Option<CompressedG1<G>>,
|
||||
pi_kzg: Option<CompressedG1<G>>,
|
||||
}
|
||||
|
||||
impl<G: Curve> Compressible for Proof<G>
|
||||
where
|
||||
G::G1: Compressible<UncompressError = InvalidSerializedAffineError>,
|
||||
G::G2: Compressible<UncompressError = InvalidSerializedAffineError>,
|
||||
{
|
||||
type Compressed = CompressedProof<G>;
|
||||
|
||||
type UncompressError = InvalidSerializedAffineError;
|
||||
|
||||
fn compress(&self) -> Self::Compressed {
|
||||
let Proof {
|
||||
c_hat,
|
||||
c_y,
|
||||
pi,
|
||||
c_hat_t,
|
||||
c_h,
|
||||
pi_kzg,
|
||||
} = self;
|
||||
|
||||
CompressedProof {
|
||||
c_hat: c_hat.compress(),
|
||||
c_y: c_y.compress(),
|
||||
pi: pi.compress(),
|
||||
c_hat_t: c_hat_t.map(|val| val.compress()),
|
||||
c_h: c_h.map(|val| val.compress()),
|
||||
pi_kzg: pi_kzg.map(|val| val.compress()),
|
||||
}
|
||||
}
|
||||
|
||||
fn uncompress(compressed: Self::Compressed) -> Result<Self, Self::UncompressError> {
|
||||
let CompressedProof {
|
||||
c_hat,
|
||||
c_y,
|
||||
pi,
|
||||
c_hat_t,
|
||||
c_h,
|
||||
pi_kzg,
|
||||
} = compressed;
|
||||
|
||||
Ok(Proof {
|
||||
c_hat: G::G2::uncompress(c_hat)?,
|
||||
c_y: G::G1::uncompress(c_y)?,
|
||||
pi: G::G1::uncompress(pi)?,
|
||||
c_hat_t: c_hat_t.map(G::G2::uncompress).transpose()?,
|
||||
c_h: c_h.map(G::G1::uncompress).transpose()?,
|
||||
pi_kzg: pi_kzg.map(G::G1::uncompress).transpose()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
||||
pub struct PublicCommit<G: Curve> {
|
||||
a: Vec<i64>,
|
||||
@@ -1097,7 +1261,7 @@ pub fn verify<G: Curve>(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use ark_serialize::{Compress, SerializationError, Validate};
|
||||
use bincode::ErrorKind;
|
||||
use rand::rngs::StdRng;
|
||||
use rand::{Rng, SeedableRng};
|
||||
|
||||
@@ -1234,15 +1398,17 @@ mod tests {
|
||||
|
||||
type Curve = crate::curve_api::Bls12_446;
|
||||
|
||||
let serialize_then_deserialize =
|
||||
|public_param: &PublicParams<Curve>,
|
||||
compress: Compress|
|
||||
-> Result<PublicParams<Curve>, SerializationError> {
|
||||
let mut data = Vec::new();
|
||||
public_param.serialize_with_mode(&mut data, compress)?;
|
||||
|
||||
PublicParams::deserialize_with_mode(data.as_slice(), compress, Validate::No)
|
||||
};
|
||||
let serialize_then_deserialize = |public_param: &PublicParams<Curve>,
|
||||
compress: bool|
|
||||
-> bincode::Result<PublicParams<Curve>> {
|
||||
match compress {
|
||||
true => PublicParams::uncompress(bincode::deserialize(&bincode::serialize(
|
||||
&public_param.clone().compress(),
|
||||
)?)?)
|
||||
.map_err(|e| Box::new(ErrorKind::Custom(format!("Failed to uncompress: {}", e)))),
|
||||
false => bincode::deserialize(&bincode::serialize(&public_param)?),
|
||||
}
|
||||
};
|
||||
|
||||
// To check management of bigger k_max from CRS during test
|
||||
let crs_k = k + 1 + (rng.gen::<usize>() % (d - k));
|
||||
@@ -1250,9 +1416,9 @@ mod tests {
|
||||
let original_public_param =
|
||||
crs_gen::<Curve>(d, crs_k, b_i, q, t, msbs_zero_padding_bit_count, rng);
|
||||
let public_param_that_was_compressed =
|
||||
serialize_then_deserialize(&original_public_param, Compress::No).unwrap();
|
||||
serialize_then_deserialize(&original_public_param, true).unwrap();
|
||||
let public_param_that_was_not_compressed =
|
||||
serialize_then_deserialize(&original_public_param, Compress::Yes).unwrap();
|
||||
serialize_then_deserialize(&original_public_param, false).unwrap();
|
||||
|
||||
for (
|
||||
public_param,
|
||||
@@ -1448,21 +1614,23 @@ mod tests {
|
||||
let div = val.div_euclid(q);
|
||||
let rem = val.rem_euclid(q);
|
||||
let result = div as i64 + (rem > (q / 2)) as i64;
|
||||
let result = result.rem_euclid(t as i64);
|
||||
let result = result.rem_euclid(effective_cleartext_t as i64);
|
||||
m_roundtrip[i] = result;
|
||||
}
|
||||
|
||||
type Curve = crate::curve_api::Bls12_446;
|
||||
|
||||
let serialize_then_deserialize =
|
||||
|public_param: &PublicParams<Curve>,
|
||||
compress: Compress|
|
||||
-> Result<PublicParams<Curve>, SerializationError> {
|
||||
let mut data = Vec::new();
|
||||
public_param.serialize_with_mode(&mut data, compress)?;
|
||||
|
||||
PublicParams::deserialize_with_mode(data.as_slice(), compress, Validate::No)
|
||||
};
|
||||
let serialize_then_deserialize = |public_param: &PublicParams<Curve>,
|
||||
compress: bool|
|
||||
-> bincode::Result<PublicParams<Curve>> {
|
||||
match compress {
|
||||
true => PublicParams::uncompress(bincode::deserialize(&bincode::serialize(
|
||||
&public_param.clone().compress(),
|
||||
)?)?)
|
||||
.map_err(|e| Box::new(ErrorKind::Custom(format!("Failed to uncompress: {}", e)))),
|
||||
false => bincode::deserialize(&bincode::serialize(&public_param)?),
|
||||
}
|
||||
};
|
||||
|
||||
// To check management of bigger k_max from CRS during test
|
||||
let crs_k = k + 1 + (rng.gen::<usize>() % (d - k));
|
||||
@@ -1470,9 +1638,9 @@ mod tests {
|
||||
let original_public_param =
|
||||
crs_gen::<Curve>(d, crs_k, b_i, q, t, msbs_zero_padding_bit_count, rng);
|
||||
let public_param_that_was_compressed =
|
||||
serialize_then_deserialize(&original_public_param, Compress::No).unwrap();
|
||||
serialize_then_deserialize(&original_public_param, true).unwrap();
|
||||
let public_param_that_was_not_compressed =
|
||||
serialize_then_deserialize(&original_public_param, Compress::Yes).unwrap();
|
||||
serialize_then_deserialize(&original_public_param, false).unwrap();
|
||||
|
||||
for public_param in [
|
||||
original_public_param,
|
||||
@@ -1505,4 +1673,156 @@ mod tests {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_proof_compression() {
|
||||
let d = 2048;
|
||||
let k = 320;
|
||||
let big_b = 1048576;
|
||||
let q = 0;
|
||||
let t = 1024;
|
||||
let msbs_zero_padding_bit_count = 1;
|
||||
let effective_cleartext_t = t >> msbs_zero_padding_bit_count;
|
||||
|
||||
let delta = {
|
||||
let q = if q == 0 { 1i128 << 64 } else { q as i128 };
|
||||
(q / t as i128) as u64
|
||||
};
|
||||
|
||||
let rng = &mut StdRng::seed_from_u64(0);
|
||||
|
||||
let polymul_rev = |a: &[i64], b: &[i64]| -> Vec<i64> {
|
||||
assert_eq!(a.len(), b.len());
|
||||
let d = a.len();
|
||||
let mut c = vec![0i64; d];
|
||||
|
||||
for i in 0..d {
|
||||
for j in 0..d {
|
||||
if i + j < d {
|
||||
c[i + j] = c[i + j].wrapping_add(a[i].wrapping_mul(b[d - j - 1]));
|
||||
} else {
|
||||
c[i + j - d] = c[i + j - d].wrapping_sub(a[i].wrapping_mul(b[d - j - 1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c
|
||||
};
|
||||
|
||||
let a = (0..d).map(|_| rng.gen::<i64>()).collect::<Vec<_>>();
|
||||
let s = (0..d)
|
||||
.map(|_| (rng.gen::<u64>() % 2) as i64)
|
||||
.collect::<Vec<_>>();
|
||||
let e = (0..d)
|
||||
.map(|_| (rng.gen::<u64>() % (2 * big_b)) as i64 - big_b as i64)
|
||||
.collect::<Vec<_>>();
|
||||
let e1 = (0..d)
|
||||
.map(|_| (rng.gen::<u64>() % (2 * big_b)) as i64 - big_b as i64)
|
||||
.collect::<Vec<_>>();
|
||||
let e2 = (0..k)
|
||||
.map(|_| (rng.gen::<u64>() % (2 * big_b)) as i64 - big_b as i64)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let r = (0..d)
|
||||
.map(|_| (rng.gen::<u64>() % 2) as i64)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let m = (0..k)
|
||||
.map(|_| (rng.gen::<u64>() % effective_cleartext_t) as i64)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let b = polymul_rev(&a, &s)
|
||||
.into_iter()
|
||||
.zip(e.iter())
|
||||
.map(|(x, e)| x.wrapping_add(*e))
|
||||
.collect::<Vec<_>>();
|
||||
let c1 = polymul_rev(&a, &r)
|
||||
.into_iter()
|
||||
.zip(e1.iter())
|
||||
.map(|(x, e1)| x.wrapping_add(*e1))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let mut c2 = vec![0i64; k];
|
||||
|
||||
for i in 0..k {
|
||||
let mut dot = 0i64;
|
||||
for j in 0..d {
|
||||
let b = if i + j < d {
|
||||
b[d - j - i - 1]
|
||||
} else {
|
||||
b[2 * d - j - i - 1].wrapping_neg()
|
||||
};
|
||||
|
||||
dot = dot.wrapping_add(r[d - j - 1].wrapping_mul(b));
|
||||
}
|
||||
|
||||
c2[i] = dot
|
||||
.wrapping_add(e2[i])
|
||||
.wrapping_add((delta * m[i] as u64) as i64);
|
||||
}
|
||||
|
||||
// One of our usecases uses 320 bits of additional metadata
|
||||
const METADATA_LEN: usize = (320 / u8::BITS) as usize;
|
||||
|
||||
let mut metadata = [0u8; METADATA_LEN];
|
||||
metadata.fill_with(|| rng.gen::<u8>());
|
||||
|
||||
let mut m_roundtrip = vec![0i64; k];
|
||||
for i in 0..k {
|
||||
let mut dot = 0i128;
|
||||
for j in 0..d {
|
||||
let c = if i + j < d {
|
||||
c1[d - j - i - 1]
|
||||
} else {
|
||||
c1[2 * d - j - i - 1].wrapping_neg()
|
||||
};
|
||||
|
||||
dot += s[d - j - 1] as i128 * c as i128;
|
||||
}
|
||||
|
||||
let q = if q == 0 { 1i128 << 64 } else { q as i128 };
|
||||
let val = ((c2[i] as i128).wrapping_sub(dot)) * t as i128;
|
||||
let div = val.div_euclid(q);
|
||||
let rem = val.rem_euclid(q);
|
||||
let result = div as i64 + (rem > (q / 2)) as i64;
|
||||
let result = result.rem_euclid(effective_cleartext_t as i64);
|
||||
m_roundtrip[i] = result;
|
||||
}
|
||||
|
||||
type Curve = crate::curve_api::Bls12_446;
|
||||
|
||||
let crs_k = k + 1 + (rng.gen::<usize>() % (d - k));
|
||||
|
||||
let public_param =
|
||||
crs_gen::<Curve>(d, crs_k, big_b, q, t, msbs_zero_padding_bit_count, rng);
|
||||
|
||||
let (public_commit, private_commit) = commit(
|
||||
a.clone(),
|
||||
b.clone(),
|
||||
c1.clone(),
|
||||
c2.clone(),
|
||||
r.clone(),
|
||||
e1.clone(),
|
||||
m.clone(),
|
||||
e2.clone(),
|
||||
&public_param,
|
||||
rng,
|
||||
);
|
||||
|
||||
for load in [ComputeLoad::Proof, ComputeLoad::Verify] {
|
||||
let proof = prove(
|
||||
(&public_param, &public_commit),
|
||||
&private_commit,
|
||||
&metadata,
|
||||
load,
|
||||
rng,
|
||||
);
|
||||
|
||||
let compressed_proof = bincode::serialize(&proof.clone().compress()).unwrap();
|
||||
let proof =
|
||||
Proof::uncompress(bincode::deserialize(&compressed_proof).unwrap()).unwrap();
|
||||
|
||||
verify(&proof, (&public_param, &public_commit), &metadata).unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,25 +2,26 @@
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use super::*;
|
||||
use crate::backward_compatibility::{PKEv2ProofVersions, SerializablePKEv2PublicParamsVersions};
|
||||
use crate::backward_compatibility::{
|
||||
PKEv2CompressedProofVersions, PKEv2ProofVersions, SerializablePKEv2PublicParamsVersions,
|
||||
};
|
||||
use crate::four_squares::*;
|
||||
use crate::serialization::{
|
||||
InvalidSerializedPublicParamsError, SerializableGroupElements, SerializablePKEv2PublicParams,
|
||||
try_vec_to_array, InvalidSerializedAffineError, InvalidSerializedPublicParamsError,
|
||||
SerializableGroupElements, SerializablePKEv2PublicParams,
|
||||
};
|
||||
use core::marker::PhantomData;
|
||||
use rayon::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::error::Error;
|
||||
use tfhe_versionable::{
|
||||
Unversionize, UnversionizeError, Versionize, VersionizeOwned, VersionsDispatch,
|
||||
};
|
||||
use tfhe_versionable::{UnversionizeError, VersionsDispatch};
|
||||
|
||||
fn bit_iter(x: u64, nbits: u32) -> impl Iterator<Item = bool> {
|
||||
(0..nbits).map(move |idx| ((x >> idx) & 1) != 0)
|
||||
}
|
||||
|
||||
/// The CRS of the zk scheme
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, CanonicalSerialize, CanonicalDeserialize)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[serde(
|
||||
try_from = "SerializablePKEv2PublicParams",
|
||||
into = "SerializablePKEv2PublicParams",
|
||||
@@ -54,8 +55,7 @@ pub struct PublicParams<G: Curve> {
|
||||
pub(crate) hash_chi: [u8; HASH_METADATA_LEN_BYTES],
|
||||
}
|
||||
|
||||
// Manual impl of Versionize because the proc macro has trouble handling conversion from/into types
|
||||
// with generics
|
||||
// Manual impl of Versionize because TryFrom + generics is currently badly handled by the proc macro
|
||||
impl<G: Curve> Versionize for PublicParams<G>
|
||||
where
|
||||
Self: Clone,
|
||||
@@ -101,6 +101,120 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<G: Curve> Compressible for PublicParams<G>
|
||||
where
|
||||
GroupElements<G>: Compressible<
|
||||
Compressed = SerializableGroupElements,
|
||||
UncompressError = InvalidSerializedGroupElementsError,
|
||||
>,
|
||||
{
|
||||
type Compressed = SerializablePKEv2PublicParams;
|
||||
|
||||
type UncompressError = InvalidSerializedPublicParamsError;
|
||||
|
||||
fn compress(&self) -> Self::Compressed {
|
||||
let PublicParams {
|
||||
g_lists,
|
||||
D,
|
||||
n,
|
||||
d,
|
||||
k,
|
||||
B,
|
||||
B_r,
|
||||
B_bound,
|
||||
m_bound,
|
||||
q,
|
||||
t,
|
||||
msbs_zero_padding_bit_count,
|
||||
hash,
|
||||
hash_R,
|
||||
hash_t,
|
||||
hash_w,
|
||||
hash_agg,
|
||||
hash_lmap,
|
||||
hash_phi,
|
||||
hash_xi,
|
||||
hash_z,
|
||||
hash_chi,
|
||||
} = self;
|
||||
SerializablePKEv2PublicParams {
|
||||
g_lists: g_lists.compress(),
|
||||
D: *D,
|
||||
n: *n,
|
||||
d: *d,
|
||||
k: *k,
|
||||
B: *B,
|
||||
B_r: *B_r,
|
||||
B_bound: *B_bound,
|
||||
m_bound: *m_bound,
|
||||
q: *q,
|
||||
t: *t,
|
||||
msbs_zero_padding_bit_count: *msbs_zero_padding_bit_count,
|
||||
hash: hash.to_vec(),
|
||||
hash_R: hash_R.to_vec(),
|
||||
hash_t: hash_t.to_vec(),
|
||||
hash_w: hash_w.to_vec(),
|
||||
hash_agg: hash_agg.to_vec(),
|
||||
hash_lmap: hash_lmap.to_vec(),
|
||||
hash_phi: hash_phi.to_vec(),
|
||||
hash_xi: hash_xi.to_vec(),
|
||||
hash_z: hash_z.to_vec(),
|
||||
hash_chi: hash_chi.to_vec(),
|
||||
}
|
||||
}
|
||||
|
||||
fn uncompress(compressed: Self::Compressed) -> Result<Self, Self::UncompressError> {
|
||||
let SerializablePKEv2PublicParams {
|
||||
g_lists,
|
||||
D,
|
||||
n,
|
||||
d,
|
||||
k,
|
||||
B,
|
||||
B_r,
|
||||
B_bound,
|
||||
m_bound,
|
||||
q,
|
||||
t,
|
||||
msbs_zero_padding_bit_count,
|
||||
hash,
|
||||
hash_R,
|
||||
hash_t,
|
||||
hash_w,
|
||||
hash_agg,
|
||||
hash_lmap,
|
||||
hash_phi,
|
||||
hash_xi,
|
||||
hash_z,
|
||||
hash_chi,
|
||||
} = compressed;
|
||||
Ok(Self {
|
||||
g_lists: GroupElements::uncompress(g_lists)?,
|
||||
D,
|
||||
n,
|
||||
d,
|
||||
k,
|
||||
B,
|
||||
B_r,
|
||||
B_bound,
|
||||
m_bound,
|
||||
q,
|
||||
t,
|
||||
msbs_zero_padding_bit_count,
|
||||
hash: try_vec_to_array(hash)?,
|
||||
hash_R: try_vec_to_array(hash_R)?,
|
||||
hash_t: try_vec_to_array(hash_t)?,
|
||||
hash_w: try_vec_to_array(hash_w)?,
|
||||
hash_agg: try_vec_to_array(hash_agg)?,
|
||||
hash_lmap: try_vec_to_array(hash_lmap)?,
|
||||
hash_phi: try_vec_to_array(hash_phi)?,
|
||||
hash_xi: try_vec_to_array(hash_xi)?,
|
||||
hash_z: try_vec_to_array(hash_z)?,
|
||||
hash_chi: try_vec_to_array(hash_chi)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<G: Curve> PublicParams<G> {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn from_vec(
|
||||
@@ -182,6 +296,114 @@ pub struct Proof<G: Curve> {
|
||||
C_hat_w: Option<G::G2>,
|
||||
}
|
||||
|
||||
type CompressedG2<G> = <<G as Curve>::G2 as Compressible>::Compressed;
|
||||
type CompressedG1<G> = <<G as Curve>::G1 as Compressible>::Compressed;
|
||||
|
||||
#[derive(Serialize, Deserialize, Versionize)]
|
||||
#[serde(bound(
|
||||
deserialize = "G: Curve, CompressedG1<G>: serde::Deserialize<'de>, CompressedG2<G>: serde::Deserialize<'de>",
|
||||
serialize = "G: Curve, CompressedG1<G>: serde::Serialize, CompressedG2<G>: serde::Serialize"
|
||||
))]
|
||||
#[versionize(PKEv2CompressedProofVersions)]
|
||||
pub struct CompressedProof<G: Curve>
|
||||
where
|
||||
G::G1: Compressible,
|
||||
G::G2: Compressible,
|
||||
{
|
||||
C_hat_e: CompressedG2<G>,
|
||||
C_e: CompressedG1<G>,
|
||||
C_r_tilde: CompressedG1<G>,
|
||||
C_R: CompressedG1<G>,
|
||||
C_hat_bin: CompressedG2<G>,
|
||||
C_y: CompressedG1<G>,
|
||||
C_h1: CompressedG1<G>,
|
||||
C_h2: CompressedG1<G>,
|
||||
C_hat_t: CompressedG2<G>,
|
||||
pi: CompressedG1<G>,
|
||||
pi_kzg: CompressedG1<G>,
|
||||
|
||||
C_hat_h3: Option<CompressedG2<G>>,
|
||||
C_hat_w: Option<CompressedG2<G>>,
|
||||
}
|
||||
|
||||
impl<G: Curve> Compressible for Proof<G>
|
||||
where
|
||||
G::G1: Compressible<UncompressError = InvalidSerializedAffineError>,
|
||||
G::G2: Compressible<UncompressError = InvalidSerializedAffineError>,
|
||||
{
|
||||
type Compressed = CompressedProof<G>;
|
||||
|
||||
type UncompressError = InvalidSerializedAffineError;
|
||||
|
||||
fn compress(&self) -> Self::Compressed {
|
||||
let Proof {
|
||||
C_hat_e,
|
||||
C_e,
|
||||
C_r_tilde,
|
||||
C_R,
|
||||
C_hat_bin,
|
||||
C_y,
|
||||
C_h1,
|
||||
C_h2,
|
||||
C_hat_t,
|
||||
pi,
|
||||
pi_kzg,
|
||||
C_hat_h3,
|
||||
C_hat_w,
|
||||
} = self;
|
||||
|
||||
CompressedProof {
|
||||
C_hat_e: C_hat_e.compress(),
|
||||
C_e: C_e.compress(),
|
||||
C_r_tilde: C_r_tilde.compress(),
|
||||
C_R: C_R.compress(),
|
||||
C_hat_bin: C_hat_bin.compress(),
|
||||
C_y: C_y.compress(),
|
||||
C_h1: C_h1.compress(),
|
||||
C_h2: C_h2.compress(),
|
||||
C_hat_t: C_hat_t.compress(),
|
||||
pi: pi.compress(),
|
||||
pi_kzg: pi_kzg.compress(),
|
||||
C_hat_h3: C_hat_h3.map(|val| val.compress()),
|
||||
C_hat_w: C_hat_w.map(|val| val.compress()),
|
||||
}
|
||||
}
|
||||
|
||||
fn uncompress(compressed: Self::Compressed) -> Result<Self, Self::UncompressError> {
|
||||
let CompressedProof {
|
||||
C_hat_e,
|
||||
C_e,
|
||||
C_r_tilde,
|
||||
C_R,
|
||||
C_hat_bin,
|
||||
C_y,
|
||||
C_h1,
|
||||
C_h2,
|
||||
C_hat_t,
|
||||
pi,
|
||||
pi_kzg,
|
||||
C_hat_h3,
|
||||
C_hat_w,
|
||||
} = compressed;
|
||||
|
||||
Ok(Proof {
|
||||
C_hat_e: G::G2::uncompress(C_hat_e)?,
|
||||
C_e: G::G1::uncompress(C_e)?,
|
||||
C_r_tilde: G::G1::uncompress(C_r_tilde)?,
|
||||
C_R: G::G1::uncompress(C_R)?,
|
||||
C_hat_bin: G::G2::uncompress(C_hat_bin)?,
|
||||
C_y: G::G1::uncompress(C_y)?,
|
||||
C_h1: G::G1::uncompress(C_h1)?,
|
||||
C_h2: G::G1::uncompress(C_h2)?,
|
||||
C_hat_t: G::G2::uncompress(C_hat_t)?,
|
||||
pi: G::G1::uncompress(pi)?,
|
||||
pi_kzg: G::G1::uncompress(pi_kzg)?,
|
||||
C_hat_h3: C_hat_h3.map(G::G2::uncompress).transpose()?,
|
||||
C_hat_w: C_hat_w.map(G::G2::uncompress).transpose()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// This is the public part of the commitment. `a` and `b` are the mask and body of the public key,
|
||||
/// `c1` and `c2` are the mask and body of the ciphertext.
|
||||
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
||||
@@ -2136,7 +2358,7 @@ pub fn verify<G: Curve>(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use ark_serialize::{Compress, SerializationError, Validate};
|
||||
use bincode::ErrorKind;
|
||||
use rand::rngs::StdRng;
|
||||
use rand::{Rng, SeedableRng};
|
||||
|
||||
@@ -2273,15 +2495,17 @@ mod tests {
|
||||
|
||||
type Curve = crate::curve_api::Bls12_446;
|
||||
|
||||
let serialize_then_deserialize =
|
||||
|public_param: &PublicParams<Curve>,
|
||||
compress: Compress|
|
||||
-> Result<PublicParams<Curve>, SerializationError> {
|
||||
let mut data = Vec::new();
|
||||
public_param.serialize_with_mode(&mut data, compress)?;
|
||||
|
||||
PublicParams::deserialize_with_mode(data.as_slice(), compress, Validate::No)
|
||||
};
|
||||
let serialize_then_deserialize = |public_param: &PublicParams<Curve>,
|
||||
compress: bool|
|
||||
-> bincode::Result<PublicParams<Curve>> {
|
||||
match compress {
|
||||
true => PublicParams::uncompress(bincode::deserialize(&bincode::serialize(
|
||||
&public_param.clone().compress(),
|
||||
)?)?)
|
||||
.map_err(|e| Box::new(ErrorKind::Custom(format!("Failed to uncompress: {}", e)))),
|
||||
false => bincode::deserialize(&bincode::serialize(&public_param)?),
|
||||
}
|
||||
};
|
||||
|
||||
// To check management of bigger k_max from CRS during test
|
||||
let crs_k = k + 1 + (rng.gen::<usize>() % (d - k));
|
||||
@@ -2289,9 +2513,9 @@ mod tests {
|
||||
let original_public_param =
|
||||
crs_gen::<Curve>(d, crs_k, B, q, t, msbs_zero_padding_bit_count, rng);
|
||||
let public_param_that_was_compressed =
|
||||
serialize_then_deserialize(&original_public_param, Compress::No).unwrap();
|
||||
serialize_then_deserialize(&original_public_param, true).unwrap();
|
||||
let public_param_that_was_not_compressed =
|
||||
serialize_then_deserialize(&original_public_param, Compress::Yes).unwrap();
|
||||
serialize_then_deserialize(&original_public_param, false).unwrap();
|
||||
|
||||
for (
|
||||
public_param,
|
||||
@@ -2375,12 +2599,14 @@ mod tests {
|
||||
let B = 1048576;
|
||||
let q = 0;
|
||||
let t = 1024;
|
||||
|
||||
let msbs_zero_padding_bit_count = 1;
|
||||
let effective_cleartext_t = t >> msbs_zero_padding_bit_count;
|
||||
|
||||
let delta = {
|
||||
let q = if q == 0 { 1i128 << 64 } else { q as i128 };
|
||||
// delta takes the encoding with the padding bit
|
||||
|
||||
(q / t as i128) as u64
|
||||
};
|
||||
|
||||
@@ -2476,15 +2702,17 @@ mod tests {
|
||||
|
||||
type Curve = crate::curve_api::Bls12_446;
|
||||
|
||||
let serialize_then_deserialize =
|
||||
|public_param: &PublicParams<Curve>,
|
||||
compress: Compress|
|
||||
-> Result<PublicParams<Curve>, SerializationError> {
|
||||
let mut data = Vec::new();
|
||||
public_param.serialize_with_mode(&mut data, compress)?;
|
||||
|
||||
PublicParams::deserialize_with_mode(data.as_slice(), compress, Validate::No)
|
||||
};
|
||||
let serialize_then_deserialize = |public_param: &PublicParams<Curve>,
|
||||
compress: bool|
|
||||
-> bincode::Result<PublicParams<Curve>> {
|
||||
match compress {
|
||||
true => PublicParams::uncompress(bincode::deserialize(&bincode::serialize(
|
||||
&public_param.clone().compress(),
|
||||
)?)?)
|
||||
.map_err(|e| Box::new(ErrorKind::Custom(format!("Failed to uncompress: {}", e)))),
|
||||
false => bincode::deserialize(&bincode::serialize(&public_param)?),
|
||||
}
|
||||
};
|
||||
|
||||
// To check management of bigger k_max from CRS during test
|
||||
let crs_k = k + 1 + (rng.gen::<usize>() % (d - k));
|
||||
@@ -2492,9 +2720,9 @@ mod tests {
|
||||
let original_public_param =
|
||||
crs_gen::<Curve>(d, crs_k, B, q, t, msbs_zero_padding_bit_count, rng);
|
||||
let public_param_that_was_compressed =
|
||||
serialize_then_deserialize(&original_public_param, Compress::No).unwrap();
|
||||
serialize_then_deserialize(&original_public_param, true).unwrap();
|
||||
let public_param_that_was_not_compressed =
|
||||
serialize_then_deserialize(&original_public_param, Compress::Yes).unwrap();
|
||||
serialize_then_deserialize(&original_public_param, false).unwrap();
|
||||
|
||||
for public_param in [
|
||||
original_public_param,
|
||||
@@ -2527,4 +2755,156 @@ mod tests {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_proof_compression() {
|
||||
let d = 2048;
|
||||
let k = 320;
|
||||
let B = 1048576;
|
||||
let q = 0;
|
||||
let t = 1024;
|
||||
|
||||
let msbs_zero_padding_bit_count = 1;
|
||||
let effective_cleartext_t = t >> msbs_zero_padding_bit_count;
|
||||
|
||||
let delta = {
|
||||
let q = if q == 0 { 1i128 << 64 } else { q as i128 };
|
||||
(q / t as i128) as u64
|
||||
};
|
||||
|
||||
let rng = &mut StdRng::seed_from_u64(0);
|
||||
|
||||
let polymul_rev = |a: &[i64], b: &[i64]| -> Vec<i64> {
|
||||
assert_eq!(a.len(), b.len());
|
||||
let d = a.len();
|
||||
let mut c = vec![0i64; d];
|
||||
|
||||
for i in 0..d {
|
||||
for j in 0..d {
|
||||
if i + j < d {
|
||||
c[i + j] = c[i + j].wrapping_add(a[i].wrapping_mul(b[d - j - 1]));
|
||||
} else {
|
||||
c[i + j - d] = c[i + j - d].wrapping_sub(a[i].wrapping_mul(b[d - j - 1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c
|
||||
};
|
||||
|
||||
let a = (0..d).map(|_| rng.gen::<i64>()).collect::<Vec<_>>();
|
||||
let s = (0..d)
|
||||
.map(|_| (rng.gen::<u64>() % 2) as i64)
|
||||
.collect::<Vec<_>>();
|
||||
let e = (0..d)
|
||||
.map(|_| (rng.gen::<u64>() % (2 * B)) as i64 - B as i64)
|
||||
.collect::<Vec<_>>();
|
||||
let e1 = (0..d)
|
||||
.map(|_| (rng.gen::<u64>() % (2 * B)) as i64 - B as i64)
|
||||
.collect::<Vec<_>>();
|
||||
let e2 = (0..k)
|
||||
.map(|_| (rng.gen::<u64>() % (2 * B)) as i64 - B as i64)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let r = (0..d)
|
||||
.map(|_| (rng.gen::<u64>() % 2) as i64)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let m = (0..k)
|
||||
.map(|_| (rng.gen::<u64>() % effective_cleartext_t) as i64)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let b = polymul_rev(&a, &s)
|
||||
.into_iter()
|
||||
.zip(e.iter())
|
||||
.map(|(x, e)| x.wrapping_add(*e))
|
||||
.collect::<Vec<_>>();
|
||||
let c1 = polymul_rev(&a, &r)
|
||||
.into_iter()
|
||||
.zip(e1.iter())
|
||||
.map(|(x, e1)| x.wrapping_add(*e1))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let mut c2 = vec![0i64; k];
|
||||
|
||||
for i in 0..k {
|
||||
let mut dot = 0i64;
|
||||
for j in 0..d {
|
||||
let b = if i + j < d {
|
||||
b[d - j - i - 1]
|
||||
} else {
|
||||
b[2 * d - j - i - 1].wrapping_neg()
|
||||
};
|
||||
|
||||
dot = dot.wrapping_add(r[d - j - 1].wrapping_mul(b));
|
||||
}
|
||||
|
||||
c2[i] = dot
|
||||
.wrapping_add(e2[i])
|
||||
.wrapping_add((delta * m[i] as u64) as i64);
|
||||
}
|
||||
|
||||
// One of our usecases uses 320 bits of additional metadata
|
||||
const METADATA_LEN: usize = (320 / u8::BITS) as usize;
|
||||
|
||||
let mut metadata = [0u8; METADATA_LEN];
|
||||
metadata.fill_with(|| rng.gen::<u8>());
|
||||
|
||||
let mut m_roundtrip = vec![0i64; k];
|
||||
for i in 0..k {
|
||||
let mut dot = 0i128;
|
||||
for j in 0..d {
|
||||
let c = if i + j < d {
|
||||
c1[d - j - i - 1]
|
||||
} else {
|
||||
c1[2 * d - j - i - 1].wrapping_neg()
|
||||
};
|
||||
|
||||
dot += s[d - j - 1] as i128 * c as i128;
|
||||
}
|
||||
|
||||
let q = if q == 0 { 1i128 << 64 } else { q as i128 };
|
||||
let val = ((c2[i] as i128).wrapping_sub(dot)) * t as i128;
|
||||
let div = val.div_euclid(q);
|
||||
let rem = val.rem_euclid(q);
|
||||
let result = div as i64 + (rem > (q / 2)) as i64;
|
||||
let result = result.rem_euclid(effective_cleartext_t as i64);
|
||||
m_roundtrip[i] = result;
|
||||
}
|
||||
|
||||
type Curve = crate::curve_api::Bls12_446;
|
||||
|
||||
let crs_k = k + 1 + (rng.gen::<usize>() % (d - k));
|
||||
|
||||
let public_param = crs_gen::<Curve>(d, crs_k, B, q, t, msbs_zero_padding_bit_count, rng);
|
||||
|
||||
let (public_commit, private_commit) = commit(
|
||||
a.clone(),
|
||||
b.clone(),
|
||||
c1.clone(),
|
||||
c2.clone(),
|
||||
r.clone(),
|
||||
e1.clone(),
|
||||
m.clone(),
|
||||
e2.clone(),
|
||||
&public_param,
|
||||
rng,
|
||||
);
|
||||
|
||||
for load in [ComputeLoad::Proof, ComputeLoad::Verify] {
|
||||
let proof = prove(
|
||||
(&public_param, &public_commit),
|
||||
&private_commit,
|
||||
&metadata,
|
||||
load,
|
||||
rng,
|
||||
);
|
||||
|
||||
let compressed_proof = bincode::serialize(&proof.clone().compress()).unwrap();
|
||||
let proof =
|
||||
Proof::uncompress(bincode::deserialize(&compressed_proof).unwrap()).unwrap();
|
||||
|
||||
verify(&proof, (&public_param, &public_commit), &metadata).unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,9 @@ impl Error for InvalidArraySizeError {}
|
||||
|
||||
/// Tries to convert a Vec into a constant size array, and returns an [`InvalidArraySizeError`] if
|
||||
/// the size does not match
|
||||
fn try_vec_to_array<T, const N: usize>(vec: Vec<T>) -> Result<[T; N], InvalidArraySizeError> {
|
||||
pub(crate) fn try_vec_to_array<T, const N: usize>(
|
||||
vec: Vec<T>,
|
||||
) -> Result<[T; N], InvalidArraySizeError> {
|
||||
let len = vec.len();
|
||||
|
||||
vec.try_into().map_err(|_| InvalidArraySizeError {
|
||||
@@ -75,24 +77,6 @@ impl<P: FpConfig<N>, const N: usize> TryFrom<SerializableFp> for Fp<P, N> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct InvalidSerializedFpError {
|
||||
expected_len: usize,
|
||||
found_len: usize,
|
||||
}
|
||||
|
||||
impl Display for InvalidSerializedFpError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"Invalid serialized FP: found array of size {}, expected {}",
|
||||
self.found_len, self.expected_len
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for InvalidSerializedFpError {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum InvalidSerializedAffineError {
|
||||
InvalidFp(InvalidArraySizeError),
|
||||
@@ -421,16 +405,16 @@ pub struct SerializablePKEv2PublicParams {
|
||||
pub t: u64,
|
||||
pub msbs_zero_padding_bit_count: u64,
|
||||
// We use Vec<u8> since serde does not support fixed size arrays of 256 elements
|
||||
hash: Vec<u8>,
|
||||
hash_R: Vec<u8>,
|
||||
hash_t: Vec<u8>,
|
||||
hash_w: Vec<u8>,
|
||||
hash_agg: Vec<u8>,
|
||||
hash_lmap: Vec<u8>,
|
||||
hash_phi: Vec<u8>,
|
||||
hash_xi: Vec<u8>,
|
||||
hash_z: Vec<u8>,
|
||||
hash_chi: Vec<u8>,
|
||||
pub(crate) hash: Vec<u8>,
|
||||
pub(crate) hash_R: Vec<u8>,
|
||||
pub(crate) hash_t: Vec<u8>,
|
||||
pub(crate) hash_w: Vec<u8>,
|
||||
pub(crate) hash_agg: Vec<u8>,
|
||||
pub(crate) hash_lmap: Vec<u8>,
|
||||
pub(crate) hash_phi: Vec<u8>,
|
||||
pub(crate) hash_xi: Vec<u8>,
|
||||
pub(crate) hash_z: Vec<u8>,
|
||||
pub(crate) hash_chi: Vec<u8>,
|
||||
}
|
||||
|
||||
impl<G: Curve> From<PKEv2PublicParams<G>> for SerializablePKEv2PublicParams
|
||||
|
||||
Reference in New Issue
Block a user