mirror of
https://github.com/zama-ai/tfhe-rs.git
synced 2026-01-08 22:28:01 -05:00
refactor(zk): convert ark types to custom types before serialization
This commit is contained in:
committed by
Nicolas Sarlin
parent
5cfc57f51a
commit
e76503984a
@@ -1,29 +1,14 @@
|
||||
use ark_ec::pairing::PairingOutput;
|
||||
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, Compress, Validate};
|
||||
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
|
||||
use core::fmt;
|
||||
use core::ops::{Add, AddAssign, Div, Mul, Neg, Sub, SubAssign};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
fn ark_se<S, A: CanonicalSerialize>(a: &A, s: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
let mut bytes = vec![];
|
||||
a.serialize_with_mode(&mut bytes, Compress::Yes)
|
||||
.map_err(serde::ser::Error::custom)?;
|
||||
s.serialize_bytes(&bytes)
|
||||
}
|
||||
|
||||
fn ark_de<'de, D, A: CanonicalDeserialize>(data: D) -> Result<A, D::Error>
|
||||
where
|
||||
D: serde::de::Deserializer<'de>,
|
||||
{
|
||||
let s: Vec<u8> = serde::de::Deserialize::deserialize(data)?;
|
||||
let a = A::deserialize_with_mode(s.as_slice(), Compress::Yes, Validate::Yes);
|
||||
a.map_err(serde::de::Error::custom)
|
||||
}
|
||||
use crate::serialization::{SerializableAffine, SerializableFp, SerializableFp12, SerializableFp2};
|
||||
|
||||
struct MontIntDisplay<'a, T>(&'a T);
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@ fn bigint_to_le_bytes(x: [u64; 6]) -> [u8; 6 * 8] {
|
||||
}
|
||||
|
||||
mod g1 {
|
||||
use crate::serialization::InvalidSerializedAffineError;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[derive(
|
||||
@@ -48,12 +50,31 @@ mod g1 {
|
||||
CanonicalSerialize,
|
||||
CanonicalDeserialize,
|
||||
)]
|
||||
#[serde(
|
||||
try_from = "SerializableAffine<SerializableFp>",
|
||||
into = "SerializableAffine<SerializableFp>"
|
||||
)]
|
||||
#[repr(transparent)]
|
||||
pub struct G1Affine {
|
||||
#[serde(serialize_with = "ark_se", deserialize_with = "ark_de")]
|
||||
pub(crate) inner: ark_bls12_381::g1::G1Affine,
|
||||
}
|
||||
|
||||
impl From<G1Affine> for SerializableAffine<SerializableFp> {
|
||||
fn from(value: G1Affine) -> Self {
|
||||
SerializableAffine::compressed(value.inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<SerializableAffine<SerializableFp>> for G1Affine {
|
||||
type Error = InvalidSerializedAffineError;
|
||||
|
||||
fn try_from(value: SerializableAffine<SerializableFp>) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
inner: value.try_into()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl G1Affine {
|
||||
pub fn multi_mul_scalar(bases: &[Self], scalars: &[Zp]) -> G1 {
|
||||
// SAFETY: interpreting a `repr(transparent)` pointer as its contents.
|
||||
@@ -80,12 +101,31 @@ mod g1 {
|
||||
CanonicalSerialize,
|
||||
CanonicalDeserialize,
|
||||
)]
|
||||
#[serde(
|
||||
try_from = "SerializableAffine<SerializableFp>",
|
||||
into = "SerializableAffine<SerializableFp>"
|
||||
)]
|
||||
#[repr(transparent)]
|
||||
pub struct G1 {
|
||||
#[serde(serialize_with = "ark_se", deserialize_with = "ark_de")]
|
||||
pub(crate) inner: ark_bls12_381::G1Projective,
|
||||
}
|
||||
|
||||
impl From<G1> for SerializableAffine<SerializableFp> {
|
||||
fn from(value: G1) -> Self {
|
||||
SerializableAffine::compressed(value.inner.into_affine())
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<SerializableAffine<SerializableFp>> for G1 {
|
||||
type Error = InvalidSerializedAffineError;
|
||||
|
||||
fn try_from(value: SerializableAffine<SerializableFp>) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
inner: Affine::try_from(value)?.into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for G1 {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("G1")
|
||||
@@ -210,6 +250,8 @@ mod g1 {
|
||||
}
|
||||
|
||||
mod g2 {
|
||||
use crate::serialization::InvalidSerializedAffineError;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[derive(
|
||||
@@ -224,12 +266,31 @@ mod g2 {
|
||||
CanonicalSerialize,
|
||||
CanonicalDeserialize,
|
||||
)]
|
||||
#[serde(
|
||||
try_from = "SerializableAffine<SerializableFp2>",
|
||||
into = "SerializableAffine<SerializableFp2>"
|
||||
)]
|
||||
#[repr(transparent)]
|
||||
pub struct G2Affine {
|
||||
#[serde(serialize_with = "ark_se", deserialize_with = "ark_de")]
|
||||
pub(crate) inner: ark_bls12_381::g2::G2Affine,
|
||||
}
|
||||
|
||||
impl From<G2Affine> for SerializableAffine<SerializableFp2> {
|
||||
fn from(value: G2Affine) -> Self {
|
||||
SerializableAffine::compressed(value.inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<SerializableAffine<SerializableFp2>> for G2Affine {
|
||||
type Error = InvalidSerializedAffineError;
|
||||
|
||||
fn try_from(value: SerializableAffine<SerializableFp2>) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
inner: value.try_into()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl G2Affine {
|
||||
pub fn multi_mul_scalar(bases: &[Self], scalars: &[Zp]) -> G2 {
|
||||
// SAFETY: interpreting a `repr(transparent)` pointer as its contents.
|
||||
@@ -256,12 +317,31 @@ mod g2 {
|
||||
CanonicalSerialize,
|
||||
CanonicalDeserialize,
|
||||
)]
|
||||
#[serde(
|
||||
try_from = "SerializableAffine<SerializableFp2>",
|
||||
into = "SerializableAffine<SerializableFp2>"
|
||||
)]
|
||||
#[repr(transparent)]
|
||||
pub struct G2 {
|
||||
#[serde(serialize_with = "ark_se", deserialize_with = "ark_de")]
|
||||
pub(crate) inner: ark_bls12_381::G2Projective,
|
||||
}
|
||||
|
||||
impl From<G2> for SerializableAffine<SerializableFp2> {
|
||||
fn from(value: G2) -> Self {
|
||||
SerializableAffine::compressed(value.inner.into_affine())
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<SerializableAffine<SerializableFp2>> for G2 {
|
||||
type Error = InvalidSerializedAffineError;
|
||||
|
||||
fn try_from(value: SerializableAffine<SerializableFp2>) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
inner: Affine::try_from(value)?.into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for G2 {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
#[allow(dead_code)]
|
||||
@@ -433,16 +513,34 @@ mod g2 {
|
||||
}
|
||||
|
||||
mod gt {
|
||||
use crate::serialization::InvalidArraySizeError;
|
||||
|
||||
use super::*;
|
||||
use ark_ec::pairing::Pairing;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)]
|
||||
#[serde(try_from = "SerializableFp12", into = "SerializableFp12")]
|
||||
#[repr(transparent)]
|
||||
pub struct Gt {
|
||||
#[serde(serialize_with = "ark_se", deserialize_with = "ark_de")]
|
||||
inner: ark_ec::pairing::PairingOutput<ark_bls12_381::Bls12_381>,
|
||||
}
|
||||
|
||||
impl From<Gt> for SerializableFp12 {
|
||||
fn from(value: Gt) -> Self {
|
||||
value.inner.0.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<SerializableFp12> for Gt {
|
||||
type Error = InvalidArraySizeError;
|
||||
|
||||
fn try_from(value: SerializableFp12) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
inner: PairingOutput(value.try_into()?),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Gt {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
#[allow(dead_code)]
|
||||
@@ -566,6 +664,8 @@ mod gt {
|
||||
}
|
||||
|
||||
mod zp {
|
||||
use crate::serialization::InvalidArraySizeError;
|
||||
|
||||
use super::*;
|
||||
use ark_ff::Fp;
|
||||
use zeroize::Zeroize;
|
||||
@@ -605,12 +705,27 @@ mod zp {
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Hash, Zeroize)]
|
||||
#[serde(try_from = "SerializableFp", into = "SerializableFp")]
|
||||
#[repr(transparent)]
|
||||
pub struct Zp {
|
||||
#[serde(serialize_with = "ark_se", deserialize_with = "ark_de")]
|
||||
pub(crate) inner: ark_bls12_381::Fr,
|
||||
}
|
||||
|
||||
impl From<Zp> for SerializableFp {
|
||||
fn from(value: Zp) -> Self {
|
||||
value.inner.into()
|
||||
}
|
||||
}
|
||||
impl TryFrom<SerializableFp> for Zp {
|
||||
type Error = InvalidArraySizeError;
|
||||
|
||||
fn try_from(value: SerializableFp) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
inner: value.try_into()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Zp {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("Zp")
|
||||
|
||||
@@ -34,6 +34,8 @@ fn bigint_to_le_bytes(x: [u64; 7]) -> [u8; 7 * 8] {
|
||||
}
|
||||
|
||||
mod g1 {
|
||||
use crate::serialization::InvalidSerializedAffineError;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[derive(
|
||||
@@ -45,15 +47,34 @@ mod g1 {
|
||||
Serialize,
|
||||
Deserialize,
|
||||
Hash,
|
||||
CanonicalSerialize,
|
||||
CanonicalDeserialize,
|
||||
CanonicalSerialize,
|
||||
)]
|
||||
#[serde(
|
||||
try_from = "SerializableAffine<SerializableFp>",
|
||||
into = "SerializableAffine<SerializableFp>"
|
||||
)]
|
||||
#[repr(transparent)]
|
||||
pub struct G1Affine {
|
||||
#[serde(serialize_with = "ark_se", deserialize_with = "ark_de")]
|
||||
pub(crate) inner: crate::curve_446::g1::G1Affine,
|
||||
}
|
||||
|
||||
impl From<G1Affine> for SerializableAffine<SerializableFp> {
|
||||
fn from(value: G1Affine) -> Self {
|
||||
SerializableAffine::compressed(value.inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<SerializableAffine<SerializableFp>> for G1Affine {
|
||||
type Error = InvalidSerializedAffineError;
|
||||
|
||||
fn try_from(value: SerializableAffine<SerializableFp>) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
inner: value.try_into()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl G1Affine {
|
||||
#[track_caller]
|
||||
pub fn multi_mul_scalar(bases: &[Self], scalars: &[Zp]) -> G1 {
|
||||
@@ -81,12 +102,31 @@ mod g1 {
|
||||
CanonicalSerialize,
|
||||
CanonicalDeserialize,
|
||||
)]
|
||||
#[serde(
|
||||
try_from = "SerializableAffine<SerializableFp>",
|
||||
into = "SerializableAffine<SerializableFp>"
|
||||
)]
|
||||
#[repr(transparent)]
|
||||
pub struct G1 {
|
||||
#[serde(serialize_with = "ark_se", deserialize_with = "ark_de")]
|
||||
pub(crate) inner: crate::curve_446::g1::G1Projective,
|
||||
}
|
||||
|
||||
impl From<G1> for SerializableAffine<SerializableFp> {
|
||||
fn from(value: G1) -> Self {
|
||||
SerializableAffine::compressed(value.inner.into_affine())
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<SerializableAffine<SerializableFp>> for G1 {
|
||||
type Error = InvalidSerializedAffineError;
|
||||
|
||||
fn try_from(value: SerializableAffine<SerializableFp>) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
inner: Affine::try_from(value)?.into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for G1 {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("G1")
|
||||
@@ -212,6 +252,7 @@ mod g1 {
|
||||
|
||||
mod g2 {
|
||||
use super::*;
|
||||
use crate::serialization::InvalidSerializedAffineError;
|
||||
|
||||
#[derive(
|
||||
Copy,
|
||||
@@ -225,12 +266,31 @@ mod g2 {
|
||||
CanonicalSerialize,
|
||||
CanonicalDeserialize,
|
||||
)]
|
||||
#[serde(
|
||||
try_from = "SerializableAffine<SerializableFp2>",
|
||||
into = "SerializableAffine<SerializableFp2>"
|
||||
)]
|
||||
#[repr(transparent)]
|
||||
pub struct G2Affine {
|
||||
#[serde(serialize_with = "ark_se", deserialize_with = "ark_de")]
|
||||
pub(crate) inner: crate::curve_446::g2::G2Affine,
|
||||
}
|
||||
|
||||
impl From<G2Affine> for SerializableAffine<SerializableFp2> {
|
||||
fn from(value: G2Affine) -> Self {
|
||||
SerializableAffine::compressed(value.inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<SerializableAffine<SerializableFp2>> for G2Affine {
|
||||
type Error = InvalidSerializedAffineError;
|
||||
|
||||
fn try_from(value: SerializableAffine<SerializableFp2>) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
inner: value.try_into()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl G2Affine {
|
||||
#[track_caller]
|
||||
pub fn multi_mul_scalar(bases: &[Self], scalars: &[Zp]) -> G2 {
|
||||
@@ -348,12 +408,31 @@ mod g2 {
|
||||
CanonicalSerialize,
|
||||
CanonicalDeserialize,
|
||||
)]
|
||||
#[serde(
|
||||
try_from = "SerializableAffine<SerializableFp2>",
|
||||
into = "SerializableAffine<SerializableFp2>"
|
||||
)]
|
||||
#[repr(transparent)]
|
||||
pub struct G2 {
|
||||
#[serde(serialize_with = "ark_se", deserialize_with = "ark_de")]
|
||||
pub(crate) inner: crate::curve_446::g2::G2Projective,
|
||||
}
|
||||
|
||||
impl From<G2> for SerializableAffine<SerializableFp2> {
|
||||
fn from(value: G2) -> Self {
|
||||
SerializableAffine::compressed(value.inner.into_affine())
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<SerializableAffine<SerializableFp2>> for G2 {
|
||||
type Error = InvalidSerializedAffineError;
|
||||
|
||||
fn try_from(value: SerializableAffine<SerializableFp2>) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
inner: Affine::try_from(value)?.into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for G2 {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
#[allow(dead_code)]
|
||||
@@ -525,6 +604,7 @@ mod g2 {
|
||||
|
||||
mod gt {
|
||||
use crate::curve_446::{Fq, Fq12, Fq2};
|
||||
use crate::serialization::InvalidSerializedAffineError;
|
||||
|
||||
use super::*;
|
||||
use ark_ec::pairing::{MillerLoopOutput, Pairing};
|
||||
@@ -699,12 +779,28 @@ mod gt {
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)]
|
||||
#[serde(try_from = "SerializableFp12", into = "SerializableFp12")]
|
||||
#[repr(transparent)]
|
||||
pub struct Gt {
|
||||
#[serde(serialize_with = "ark_se", deserialize_with = "ark_de")]
|
||||
pub(crate) inner: ark_ec::pairing::PairingOutput<crate::curve_446::Bls12_446>,
|
||||
}
|
||||
|
||||
impl From<Gt> for SerializableFp12 {
|
||||
fn from(value: Gt) -> Self {
|
||||
value.inner.0.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<SerializableFp12> for Gt {
|
||||
type Error = InvalidSerializedAffineError;
|
||||
|
||||
fn try_from(value: SerializableFp12) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
inner: PairingOutput(value.try_into()?),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Gt {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
#[allow(dead_code)]
|
||||
@@ -827,6 +923,7 @@ mod gt {
|
||||
|
||||
mod zp {
|
||||
use super::*;
|
||||
use crate::serialization::InvalidArraySizeError;
|
||||
use ark_ff::Fp;
|
||||
use zeroize::Zeroize;
|
||||
|
||||
@@ -865,12 +962,27 @@ mod zp {
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Hash, Zeroize)]
|
||||
#[serde(try_from = "SerializableFp", into = "SerializableFp")]
|
||||
#[repr(transparent)]
|
||||
pub struct Zp {
|
||||
#[serde(serialize_with = "ark_se", deserialize_with = "ark_de")]
|
||||
pub inner: crate::curve_446::Fr,
|
||||
}
|
||||
|
||||
impl From<Zp> for SerializableFp {
|
||||
fn from(value: Zp) -> Self {
|
||||
value.inner.into()
|
||||
}
|
||||
}
|
||||
impl TryFrom<SerializableFp> for Zp {
|
||||
type Error = InvalidArraySizeError;
|
||||
|
||||
fn try_from(value: SerializableFp) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
inner: value.try_into()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Zp {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("Zp")
|
||||
|
||||
@@ -3,5 +3,6 @@ pub use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Compress, Vali
|
||||
pub mod curve_446;
|
||||
pub mod curve_api;
|
||||
pub mod proofs;
|
||||
pub mod serialization;
|
||||
|
||||
mod four_squares;
|
||||
|
||||
231
tfhe-zk-pok/src/serialization.rs
Normal file
231
tfhe-zk-pok/src/serialization.rs
Normal file
@@ -0,0 +1,231 @@
|
||||
use std::error::Error;
|
||||
use std::fmt::Display;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use ark_ec::short_weierstrass::{Affine, SWCurveConfig};
|
||||
use ark_ec::AffineRepr;
|
||||
use ark_ff::{BigInt, Field, Fp, Fp2, Fp6, Fp6Config, FpConfig, QuadExtConfig, QuadExtField};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Error returned when a conversion from a vec to a fixed size array failed because the vec size is
|
||||
/// incorrect
|
||||
#[derive(Debug)]
|
||||
pub struct InvalidArraySizeError {
|
||||
expected_len: usize,
|
||||
found_len: usize,
|
||||
}
|
||||
|
||||
impl Display for InvalidArraySizeError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"Invalid serialized array: found array of size {}, expected {}",
|
||||
self.found_len, self.expected_len
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
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> {
|
||||
let len = vec.len();
|
||||
|
||||
vec.try_into().map_err(|_| InvalidArraySizeError {
|
||||
expected_len: len,
|
||||
found_len: N,
|
||||
})
|
||||
}
|
||||
|
||||
/// Serialization equivalent of the [`Fp`] struct, where the bigint is split into
|
||||
/// multiple u64.
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct SerializableFp {
|
||||
val: Vec<u64>, // Use a Vec<u64> since serde does not support fixed size arrays with a generic
|
||||
}
|
||||
|
||||
impl<P: FpConfig<N>, const N: usize> From<Fp<P, N>> for SerializableFp {
|
||||
fn from(value: Fp<P, N>) -> Self {
|
||||
Self {
|
||||
val: value.0 .0.to_vec(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: FpConfig<N>, const N: usize> TryFrom<SerializableFp> for Fp<P, N> {
|
||||
type Error = InvalidArraySizeError;
|
||||
|
||||
fn try_from(value: SerializableFp) -> Result<Self, Self::Error> {
|
||||
Ok(Fp(BigInt(try_vec_to_array(value.val)?), PhantomData))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum InvalidSerializedAffineError {
|
||||
InvalidFp(InvalidArraySizeError),
|
||||
InvalidCompressedXCoordinate,
|
||||
}
|
||||
|
||||
impl Display for InvalidSerializedAffineError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
InvalidSerializedAffineError::InvalidFp(fp_error) => {
|
||||
write!(f, "Invalid fp element in affine: {}", fp_error)
|
||||
}
|
||||
InvalidSerializedAffineError::InvalidCompressedXCoordinate => {
|
||||
write!(
|
||||
f,
|
||||
"Cannot uncompress affine: X coordinate does not belong to the curve"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for InvalidSerializedAffineError {
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match self {
|
||||
InvalidSerializedAffineError::InvalidFp(fp_error) => Some(fp_error),
|
||||
InvalidSerializedAffineError::InvalidCompressedXCoordinate => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<InvalidArraySizeError> for InvalidSerializedAffineError {
|
||||
fn from(value: InvalidArraySizeError) -> Self {
|
||||
Self::InvalidFp(value)
|
||||
}
|
||||
}
|
||||
|
||||
/// Serialization equivalent to the [`Affine`], which support an optional compression mode
|
||||
/// where only the `x` coordinate is stored, and the `y` is computed on load.
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub(crate) enum SerializableAffine<F> {
|
||||
Infinity,
|
||||
Compressed { x: F, take_largest_y: bool },
|
||||
Uncompressed { x: F, y: F },
|
||||
}
|
||||
|
||||
impl<F> SerializableAffine<F> {
|
||||
#[allow(unused)]
|
||||
pub fn uncompressed<BaseField: Into<F> + Field, C: SWCurveConfig<BaseField = BaseField>>(
|
||||
value: Affine<C>,
|
||||
) -> Self {
|
||||
if value.is_zero() {
|
||||
Self::Infinity
|
||||
} else {
|
||||
Self::Uncompressed {
|
||||
x: value.x.into(),
|
||||
y: value.y.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compressed<BaseField: Into<F> + Field, C: SWCurveConfig<BaseField = BaseField>>(
|
||||
value: Affine<C>,
|
||||
) -> Self {
|
||||
if value.is_zero() {
|
||||
Self::Infinity
|
||||
} else {
|
||||
let take_largest_y = value.y > -value.y;
|
||||
Self::Compressed {
|
||||
x: value.x.into(),
|
||||
take_largest_y,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, C: SWCurveConfig> TryFrom<SerializableAffine<F>> for Affine<C>
|
||||
where
|
||||
F: TryInto<C::BaseField, Error = InvalidArraySizeError>,
|
||||
{
|
||||
type Error = InvalidSerializedAffineError;
|
||||
|
||||
fn try_from(value: SerializableAffine<F>) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
SerializableAffine::Infinity => Ok(Self::zero()),
|
||||
SerializableAffine::Compressed { x, take_largest_y } => {
|
||||
Self::get_point_from_x_unchecked(x.try_into()?, take_largest_y)
|
||||
.ok_or(InvalidSerializedAffineError::InvalidCompressedXCoordinate)
|
||||
}
|
||||
SerializableAffine::Uncompressed { x, y } => {
|
||||
Ok(Self::new_unchecked(x.try_into()?, y.try_into()?))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub(crate) struct SerializableQuadExtField<F> {
|
||||
c0: F,
|
||||
c1: F,
|
||||
}
|
||||
|
||||
pub(crate) type SerializableFp2 = SerializableQuadExtField<SerializableFp>;
|
||||
|
||||
impl<F, P: QuadExtConfig> From<QuadExtField<P>> for SerializableQuadExtField<F>
|
||||
where
|
||||
F: From<P::BaseField>,
|
||||
{
|
||||
fn from(value: QuadExtField<P>) -> Self {
|
||||
Self {
|
||||
c0: value.c0.into(),
|
||||
c1: value.c1.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, P: QuadExtConfig> TryFrom<SerializableQuadExtField<F>> for QuadExtField<P>
|
||||
where
|
||||
F: TryInto<P::BaseField, Error = InvalidArraySizeError>,
|
||||
{
|
||||
type Error = InvalidArraySizeError;
|
||||
|
||||
fn try_from(value: SerializableQuadExtField<F>) -> Result<Self, Self::Error> {
|
||||
Ok(QuadExtField {
|
||||
c0: value.c0.try_into()?,
|
||||
c1: value.c1.try_into()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub(crate) struct SerializableCubicExtField<F> {
|
||||
c0: F,
|
||||
c1: F,
|
||||
c2: F,
|
||||
}
|
||||
|
||||
type SerializableFp6 = SerializableCubicExtField<SerializableFp2>;
|
||||
|
||||
impl<F, P6: Fp6Config> From<Fp6<P6>> for SerializableCubicExtField<F>
|
||||
where
|
||||
F: From<Fp2<P6::Fp2Config>>,
|
||||
{
|
||||
fn from(value: Fp6<P6>) -> Self {
|
||||
Self {
|
||||
c0: value.c0.into(),
|
||||
c1: value.c1.into(),
|
||||
c2: value.c2.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, P6: Fp6Config> TryFrom<SerializableCubicExtField<F>> for Fp6<P6>
|
||||
where
|
||||
F: TryInto<Fp2<P6::Fp2Config>, Error = InvalidArraySizeError>,
|
||||
{
|
||||
type Error = InvalidArraySizeError;
|
||||
|
||||
fn try_from(value: SerializableCubicExtField<F>) -> Result<Self, Self::Error> {
|
||||
Ok(Fp6 {
|
||||
c0: value.c0.try_into()?,
|
||||
c1: value.c1.try_into()?,
|
||||
c2: value.c2.try_into()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) type SerializableFp12 = SerializableQuadExtField<SerializableFp6>;
|
||||
Reference in New Issue
Block a user