Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add (de)compress trait in bls module #22

Merged
merged 9 commits into from
Mar 7, 2024
Prev Previous commit
Next Next commit
Merge remote-tracking branch 'origin/master' into feat-trait-compress
jacobkaufmann committed Mar 7, 2024
commit ea8da06a70baf0a884aa8559a10871dad06aec78
331 changes: 46 additions & 285 deletions src/kzg/setup.rs
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ use std::{

use super::{Bytes32, Bytes48, Commitment, Error, Polynomial, Proof};
use crate::{
blob::Blob,
blob::{Blob, Error as BlobError},
bls::{self, Decompress, ECGroupError, Error as BlsError, Fr, P1, P2},
math,
};
@@ -108,8 +108,8 @@ impl<const G1: usize, const G2: usize> Setup<G1, G2> {
point: &Bytes32,
eval: &Bytes32,
) -> Result<bool, Error> {
let proof = Proof::deserialize(proof).map_err(|err| Error::from(BlsError::ECGroup(err)))?;
let commitment = Commitment::deserialize(commitment)
let proof = Proof::decompress(proof).map_err(|err| Error::from(BlsError::ECGroup(err)))?;
let commitment = Commitment::decompress(commitment)
.map_err(|err| Error::from(BlsError::ECGroup(err)))?;
let point =
Fr::from_be_slice(point).map_err(|err| Error::from(BlsError::FiniteField(err)))?;
@@ -184,7 +184,7 @@ impl<const G1: usize, const G2: usize> Setup<G1, G2> {

pub fn blob_proof(&self, blob: impl AsRef<[u8]>, commitment: &Bytes48) -> Result<Proof, Error> {
let blob: Blob<G1> = Blob::from_slice(blob).map_err(Error::from)?;
let commitment = Commitment::deserialize(commitment)
let commitment = Commitment::decompress(commitment)
.map_err(|err| Error::from(BlsError::ECGroup(err)))?;
let proof = self.blob_proof_inner(&blob, &commitment);
Ok(proof)
@@ -220,9 +220,9 @@ impl<const G1: usize, const G2: usize> Setup<G1, G2> {
proof: &Bytes48,
) -> Result<bool, Error> {
let blob: Blob<G1> = Blob::from_slice(blob).map_err(Error::from)?;
let commitment = Commitment::deserialize(commitment)
let commitment = Commitment::decompress(commitment)
.map_err(|err| Error::from(BlsError::ECGroup(err)))?;
let proof = Proof::deserialize(proof).map_err(|err| Error::from(BlsError::ECGroup(err)))?;
let proof = Proof::decompress(proof).map_err(|err| Error::from(BlsError::ECGroup(err)))?;

let verified = self.verify_blob_proof_inner(&blob, &commitment, &proof);
Ok(verified)
@@ -271,12 +271,12 @@ impl<const G1: usize, const G2: usize> Setup<G1, G2> {
let commitments: Result<Vec<Commitment>, _> = commitments
.as_ref()
.iter()
.map(Commitment::deserialize)
.map(Commitment::decompress)
.collect();
let commitments = commitments.map_err(|err| Error::from(BlsError::ECGroup(err)))?;

let proofs: Result<Vec<Proof>, _> =
proofs.as_ref().iter().map(Proof::deserialize).collect();
proofs.as_ref().iter().map(Proof::decompress).collect();
let proofs = proofs.map_err(|err| Error::from(BlsError::ECGroup(err)))?;

let verified = self.verify_blob_proof_batch_inner(blobs, commitments, proofs);
@@ -286,14 +286,12 @@ impl<const G1: usize, const G2: usize> Setup<G1, G2> {

#[cfg(test)]
mod tests {
use self::bls::Decompress;

use super::*;

use crate::kzg::spec::{
use crate::{bls::Compress, kzg::spec::{
BlobToCommitment, ComputeBlobProof, ComputeProof, VerifyBlobProof, VerifyBlobProofBatch,
VerifyProof,
};
}};

use std::{
fs::{self, File},
@@ -305,234 +303,6 @@ mod tests {
const FIELD_ELEMENTS_PER_BLOB: usize = 4096;
const SETUP_G2_LEN: usize = 65;

#[derive(serde::Deserialize, serde::Serialize)]
struct ComputeKzgProofInputUnchecked {
pub blob: Bytes,
pub z: Bytes,
}

#[derive(serde::Deserialize, serde::Serialize)]
struct ComputeKzgProofUnchecked {
input: ComputeKzgProofInputUnchecked,
output: Option<(FixedBytes<{ Proof::BYTES }>, FixedBytes<{ Fr::BYTES }>)>,
}

struct ComputeKzgProofInput {
pub blob: Blob<FIELD_ELEMENTS_PER_BLOB>,
pub z: Fr,
}

impl ComputeKzgProofInput {
pub fn from_unchecked(unchecked: ComputeKzgProofInputUnchecked) -> Result<Self, ()> {
let blob = Blob::from_slice(unchecked.blob).map_err(|_| ())?;
match Fr::from_be_slice(unchecked.z) {
Ok(z) => Ok(ComputeKzgProofInput { blob, z }),
Err(_) => Err(()),
}
}
}

#[derive(serde::Deserialize, serde::Serialize)]
struct BlobToCommitmentInputUnchecked {
pub blob: Bytes,
}

#[derive(serde::Deserialize, serde::Serialize)]
struct BlobToCommitmentUnchecked {
input: BlobToCommitmentInputUnchecked,
output: Option<FixedBytes<{ Commitment::BYTES }>>,
}

struct BlobToCommitmentInput {
pub blob: Blob<FIELD_ELEMENTS_PER_BLOB>,
}

impl BlobToCommitmentInput {
pub fn from_unchecked(unchecked: BlobToCommitmentInputUnchecked) -> Result<Self, ()> {
let blob = Blob::from_slice(unchecked.blob).map_err(|_| ())?;
Ok(Self { blob })
}
}

#[derive(serde::Deserialize, serde::Serialize)]
struct ComputeBlobKzgProofInputUnchecked {
blob: Bytes,
commitment: Bytes,
}

#[derive(serde::Deserialize, serde::Serialize)]
struct ComputeBlobKzgProofUnchecked {
input: ComputeBlobKzgProofInputUnchecked,
output: Option<FixedBytes<{ Proof::BYTES }>>,
}

struct ComputeBlobKzgProofInput {
blob: Blob<FIELD_ELEMENTS_PER_BLOB>,
commitment: Commitment,
}

impl ComputeBlobKzgProofInput {
pub fn from_unchecked(unchecked: ComputeBlobKzgProofInputUnchecked) -> Result<Self, ()> {
let blob = Blob::from_slice(unchecked.blob).map_err(|_| ())?;
if unchecked.commitment.len() != Commitment::BYTES {
return Err(());
}
let commitment = FixedBytes::<{ Commitment::BYTES }>::from_slice(&unchecked.commitment);
let commitment = Commitment::decompress(commitment).map_err(|_| ())?;
Ok(Self { blob, commitment })
}
}

#[derive(serde::Deserialize, serde::Serialize)]
struct VerifyKzgProofUnchecked {
input: VerifyKzgProofInputUnchecked,
output: Option<bool>,
}

#[derive(serde::Deserialize, serde::Serialize)]
struct VerifyKzgProofInputUnchecked {
pub commitment: Bytes,
pub z: Bytes,
pub y: Bytes,
pub proof: Bytes,
}

struct VerifyKzgProofInput {
pub commitment: Commitment,
pub z: Fr,
pub y: Fr,
pub proof: Proof,
}

impl VerifyKzgProofInput {
pub fn from_unchecked(unchecked: VerifyKzgProofInputUnchecked) -> Result<Self, ()> {
if unchecked.commitment.len() != Commitment::BYTES {
return Err(());
}
let commitment = FixedBytes::<{ Commitment::BYTES }>::from_slice(&unchecked.commitment);
let commitment = Commitment::decompress(commitment).map_err(|_| ())?;

let z = Fr::from_be_slice(unchecked.z).map_err(|_| ())?;
let y = Fr::from_be_slice(unchecked.y).map_err(|_| ())?;

if unchecked.proof.len() != Proof::BYTES {
return Err(());
}
let proof = FixedBytes::<{ Proof::BYTES }>::from_slice(&unchecked.proof);
let proof = Proof::decompress(proof).map_err(|_| ())?;

Ok(Self {
commitment,
z,
y,
proof,
})
}
}

#[derive(serde::Deserialize, serde::Serialize)]
struct VerifyBlobKzgProofUnchecked {
input: VerifyBlobKzgProofInputUnchecked,
output: Option<bool>,
}

#[derive(serde::Deserialize, serde::Serialize)]
struct VerifyBlobKzgProofInputUnchecked {
pub blob: Bytes,
pub commitment: Bytes,
pub proof: Bytes,
}

struct VerifyBlobKzgProofInput {
pub blob: Blob<FIELD_ELEMENTS_PER_BLOB>,
pub commitment: Commitment,
pub proof: Proof,
}

impl VerifyBlobKzgProofInput {
pub fn from_unchecked(unchecked: VerifyBlobKzgProofInputUnchecked) -> Result<Self, ()> {
let blob = Blob::from_slice(unchecked.blob).map_err(|_| ())?;
if unchecked.commitment.len() != Commitment::BYTES {
return Err(());
}
let commitment = FixedBytes::<{ Commitment::BYTES }>::from_slice(&unchecked.commitment);
let commitment = Commitment::decompress(commitment).map_err(|_| ())?;
if unchecked.proof.len() != Proof::BYTES {
return Err(());
}
let proof = FixedBytes::<{ Proof::BYTES }>::from_slice(&unchecked.proof);
let proof = Proof::decompress(proof).map_err(|_| ())?;
Ok(Self {
blob,
commitment,
proof,
})
}
}

#[derive(serde::Deserialize, serde::Serialize)]
struct VerifyBlobKzgProofBatchInputUnchecked {
blobs: Vec<Bytes>,
commitments: Vec<Bytes>,
proofs: Vec<Bytes>,
}

#[derive(serde::Deserialize, serde::Serialize)]
struct VerifyBlobKzgProofBatchUnchecked {
input: VerifyBlobKzgProofBatchInputUnchecked,
output: Option<bool>,
}

struct VerifyBlobKzgProofBatchInput {
blobs: Vec<Blob<FIELD_ELEMENTS_PER_BLOB>>,
commitments: Vec<Commitment>,
proofs: Vec<Proof>,
}

impl VerifyBlobKzgProofBatchInput {
pub fn from_unchecked(
unchecked: VerifyBlobKzgProofBatchInputUnchecked,
) -> Result<Self, ()> {
if unchecked.blobs.len() != unchecked.commitments.len()
|| unchecked.blobs.len() != unchecked.proofs.len()
{
return Err(());
}

let mut blobs = vec![];
for blob in unchecked.blobs {
let blob = Blob::from_slice(blob).map_err(|_| ())?;
blobs.push(blob);
}

let mut commitments = vec![];
for commitment in unchecked.commitments {
if commitment.len() != Commitment::BYTES {
return Err(());
}
let commitment = FixedBytes::<{ Commitment::BYTES }>::from_slice(&commitment);
let commitment = Commitment::decompress(commitment).map_err(|_| ())?;
commitments.push(commitment);
}

let mut proofs = vec![];
for proof in unchecked.proofs {
if proof.len() != Proof::BYTES {
return Err(());
}
let proof = FixedBytes::<{ Proof::BYTES }>::from_slice(&proof);
let proof = Proof::decompress(proof).map_err(|_| ())?;
proofs.push(proof);
}

Ok(Self {
blobs,
commitments,
proofs,
})
}
}

fn setup() -> Setup<FIELD_ELEMENTS_PER_BLOB, SETUP_G2_LEN> {
let path = format!("{}/trusted_setup_4096.json", env!("CARGO_MANIFEST_DIR"));
let path = PathBuf::from(path);
@@ -563,23 +333,20 @@ mod tests {
let reader = BufReader::new(file);
let case: ComputeProof = serde_yaml::from_reader(reader).unwrap();

match ComputeKzgProofInput::from_unchecked(case.input) {
Ok(input) => {
let (proof, eval) = case.output.unwrap();
let expected_eval = Fr::from_be_bytes(eval).unwrap();
let expected_proof = P1::decompress(proof).unwrap();

let poly = Polynomial(&input.blob.elements);
let eval = poly.evaluate(input.z, &setup);
let (_eval, proof) = poly.prove(input.z, &setup);

assert_eq!(eval, expected_eval);
assert_eq!(proof, expected_proof);
}
Err(_) => {
assert!(case.output.is_none());
}
}
let expected = case.output();
let Some((blob, z)) = case.input() else {
assert!(expected.is_none());
continue;
};
let Ok((proof, y)) = setup.proof(blob, &z) else {
assert!(expected.is_none());
continue;
};
let (expected_proof, expected_y) = expected.unwrap();
let mut proof_bytes = [0u8; Proof::BYTES];
proof.compress(&mut proof_bytes).unwrap();
assert_eq!(proof_bytes, expected_proof);
assert_eq!(y.to_be_bytes(), expected_y);
}
}

@@ -592,20 +359,19 @@ mod tests {
let reader = BufReader::new(file);
let case: ComputeBlobProof = serde_yaml::from_reader(reader).unwrap();

match ComputeBlobKzgProofInput::from_unchecked(case.input) {
Ok(input) => {
let proof = case.output.unwrap();
let proof = P1::decompress(proof).unwrap();
let expected_proof = Proof::from(proof);

let proof = setup.blob_proof(&input.blob, &input.commitment);

assert_eq!(proof, expected_proof);
}
Err(_) => {
assert!(case.output.is_none());
}
}
let expected = case.output();
let Some((blob, commitment)) = case.input() else {
assert!(expected.is_none());
continue;
};
let Ok(proof) = setup.blob_proof(&blob, &commitment) else {
assert!(expected.is_none());
continue;
};
let expected = expected.unwrap();
let mut proof_bytes = [0u8; Proof::BYTES];
proof.compress(&mut proof_bytes).unwrap();
assert_eq!(proof_bytes, expected);
}
}

@@ -619,20 +385,15 @@ mod tests {
let reader = BufReader::new(file);
let case: BlobToCommitment = serde_yaml::from_reader(reader).unwrap();

match BlobToCommitmentInput::from_unchecked(case.input) {
Ok(input) => {
let comm = case.output.unwrap();
let comm = P1::decompress(comm).unwrap();
let expected_comm = Commitment::from(comm);

let comm = input.blob.commitment(&setup);

assert_eq!(comm, expected_comm);
}
Err(_) => {
assert!(case.output.is_none());
}
}
let expected = case.output();
let Ok(commitment) = setup.blob_to_commitment(case.input()) else {
assert!(expected.is_none());
continue;
};
let expected = expected.unwrap();
let mut commitment_bytes = [0u8; Commitment::BYTES];
commitment.compress(&mut commitment_bytes).unwrap();
assert_eq!(commitment_bytes, expected);
}
}

You are viewing a condensed version of this merge commit. You can view the full changes here.