#![allow(non_snake_case)]
use curve25519_dalek::ristretto::CompressedRistretto;
use curve25519_dalek::scalar::Scalar;
use curve25519_dalek::traits::{Identity, IsIdentity};
use crate::errors::R1CSError;
use crate::inner_product_proof::InnerProductProof;
use crate::util;
use serde::de::Visitor;
use serde::{self, Deserialize, Deserializer, Serialize, Serializer};
const ONE_PHASE_COMMITMENTS: u8 = 0;
const TWO_PHASE_COMMITMENTS: u8 = 1;
#[derive(Clone, Debug)]
#[allow(non_snake_case)]
pub struct R1CSProof {
pub(super) A_I1: CompressedRistretto,
pub(super) A_O1: CompressedRistretto,
pub(super) S1: CompressedRistretto,
pub(super) A_I2: CompressedRistretto,
pub(super) A_O2: CompressedRistretto,
pub(super) S2: CompressedRistretto,
pub(super) T_1: CompressedRistretto,
pub(super) T_3: CompressedRistretto,
pub(super) T_4: CompressedRistretto,
pub(super) T_5: CompressedRistretto,
pub(super) T_6: CompressedRistretto,
pub(super) t_x: Scalar,
pub(super) t_x_blinding: Scalar,
pub(super) e_blinding: Scalar,
pub(super) ipp_proof: InnerProductProof,
}
impl R1CSProof {
pub fn to_bytes(&self) -> Vec<u8> {
let mut buf = Vec::with_capacity(self.serialized_size());
if self.missing_phase2_commitments() {
buf.push(ONE_PHASE_COMMITMENTS);
buf.extend_from_slice(self.A_I1.as_bytes());
buf.extend_from_slice(self.A_O1.as_bytes());
buf.extend_from_slice(self.S1.as_bytes());
} else {
buf.push(TWO_PHASE_COMMITMENTS);
buf.extend_from_slice(self.A_I1.as_bytes());
buf.extend_from_slice(self.A_O1.as_bytes());
buf.extend_from_slice(self.S1.as_bytes());
buf.extend_from_slice(self.A_I2.as_bytes());
buf.extend_from_slice(self.A_O2.as_bytes());
buf.extend_from_slice(self.S2.as_bytes());
}
buf.extend_from_slice(self.T_1.as_bytes());
buf.extend_from_slice(self.T_3.as_bytes());
buf.extend_from_slice(self.T_4.as_bytes());
buf.extend_from_slice(self.T_5.as_bytes());
buf.extend_from_slice(self.T_6.as_bytes());
buf.extend_from_slice(self.t_x.as_bytes());
buf.extend_from_slice(self.t_x_blinding.as_bytes());
buf.extend_from_slice(self.e_blinding.as_bytes());
buf.extend(self.ipp_proof.to_bytes_iter());
buf
}
pub fn serialized_size(&self) -> usize {
let elements = if self.missing_phase2_commitments() {
11
} else {
14
};
1 + elements * 32 + self.ipp_proof.serialized_size()
}
fn missing_phase2_commitments(&self) -> bool {
self.A_I2.is_identity() && self.A_O2.is_identity() && self.S2.is_identity()
}
pub fn from_bytes(slice: &[u8]) -> Result<R1CSProof, R1CSError> {
if slice.len() < 1 {
return Err(R1CSError::FormatError);
}
let version = slice[0];
let mut slice = &slice[1..];
if slice.len() % 32 != 0 {
return Err(R1CSError::FormatError);
}
let minlength = match version {
ONE_PHASE_COMMITMENTS => 11 * 32,
TWO_PHASE_COMMITMENTS => 14 * 32,
_ => return Err(R1CSError::FormatError),
};
if slice.len() < minlength {
return Err(R1CSError::FormatError);
}
macro_rules! read32 {
() => {{
let tmp = util::read32(slice);
slice = &slice[32..];
tmp
}};
}
let A_I1 = CompressedRistretto(read32!());
let A_O1 = CompressedRistretto(read32!());
let S1 = CompressedRistretto(read32!());
let (A_I2, A_O2, S2) = if version == ONE_PHASE_COMMITMENTS {
(
CompressedRistretto::identity(),
CompressedRistretto::identity(),
CompressedRistretto::identity(),
)
} else {
(
CompressedRistretto(read32!()),
CompressedRistretto(read32!()),
CompressedRistretto(read32!()),
)
};
let T_1 = CompressedRistretto(read32!());
let T_3 = CompressedRistretto(read32!());
let T_4 = CompressedRistretto(read32!());
let T_5 = CompressedRistretto(read32!());
let T_6 = CompressedRistretto(read32!());
let t_x = Scalar::from_canonical_bytes(read32!()).ok_or(R1CSError::FormatError)?;
let t_x_blinding = Scalar::from_canonical_bytes(read32!()).ok_or(R1CSError::FormatError)?;
let e_blinding = Scalar::from_canonical_bytes(read32!()).ok_or(R1CSError::FormatError)?;
let ipp_proof = InnerProductProof::from_bytes(slice).map_err(|_| R1CSError::FormatError)?;
Ok(R1CSProof {
A_I1,
A_O1,
S1,
A_I2,
A_O2,
S2,
T_1,
T_3,
T_4,
T_5,
T_6,
t_x,
t_x_blinding,
e_blinding,
ipp_proof,
})
}
}
impl Serialize for R1CSProof {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_bytes(&self.to_bytes()[..])
}
}
impl<'de> Deserialize<'de> for R1CSProof {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct R1CSProofVisitor;
impl<'de> Visitor<'de> for R1CSProofVisitor {
type Value = R1CSProof;
fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
formatter.write_str("a valid R1CSProof")
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<R1CSProof, E>
where
E: serde::de::Error,
{
#[cfg(feature = "std")]
return R1CSProof::from_bytes(v).map_err(serde::de::Error::custom);
#[cfg(not(feature = "std"))]
return R1CSProof::from_bytes(v)
.map_err(|_| serde::de::Error::custom("deserialization error"));
}
}
deserializer.deserialize_bytes(R1CSProofVisitor)
}
}