mirror of
https://github.com/saymrwulf/pasta_curves-source.git
synced 2026-09-04 20:03:39 +00:00
commit
5f89227cdd
10 changed files with 318 additions and 95 deletions
|
|
@ -226,7 +226,8 @@ fn bench_with_k(name: &str, k: u32, c: &mut Criterion) {
|
|||
let empty_circuit: MyCircuit<Fp> = MyCircuit { a: None, k };
|
||||
|
||||
// Initialize the proving key
|
||||
let pk = keygen(¶ms, &empty_circuit).expect("keygen should not fail");
|
||||
let vk = keygen_vk(¶ms, &empty_circuit).expect("keygen_vk should not fail");
|
||||
let pk = keygen_pk(¶ms, vk, &empty_circuit).expect("keygen_pk should not fail");
|
||||
|
||||
let prover_name = name.to_string() + "-prover";
|
||||
let verifier_name = name.to_string() + "-verifier";
|
||||
|
|
|
|||
|
|
@ -257,7 +257,8 @@ fn main() {
|
|||
let empty_circuit: MyCircuit<Fp> = MyCircuit { a: None, k };
|
||||
|
||||
// Initialize the proving key
|
||||
let pk = keygen(¶ms, &empty_circuit).expect("keygen should not fail");
|
||||
let vk = keygen_vk(¶ms, &empty_circuit).expect("keygen_vk should not fail");
|
||||
let pk = keygen_pk(¶ms, vk, &empty_circuit).expect("keygen_pk should not fail");
|
||||
|
||||
println!("[Keygen] {}", recorder);
|
||||
recorder.clear();
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
|
|||
|
||||
use super::{FieldExt, Group};
|
||||
|
||||
use std::io::{self, Read, Write};
|
||||
|
||||
/// This trait is a common interface for dealing with elements of an elliptic
|
||||
/// curve group in the "projective" form, where that arithmetic is usually more
|
||||
/// efficient.
|
||||
|
|
@ -153,10 +155,25 @@ pub trait CurveAffine:
|
|||
/// endian representation.
|
||||
fn from_bytes(bytes: &[u8; 32]) -> CtOption<Self>;
|
||||
|
||||
/// Reads a compressed element from the buffer and attempts to parse it
|
||||
/// using `from_bytes`.
|
||||
fn read<R: Read>(reader: &mut R) -> io::Result<Self> {
|
||||
let mut compressed = [0u8; 32];
|
||||
reader.read_exact(&mut compressed[..])?;
|
||||
Option::from(Self::from_bytes(&compressed))
|
||||
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "invalid point encoding in proof"))
|
||||
}
|
||||
|
||||
/// Obtains the compressed, 32-byte little endian representation of this
|
||||
/// element.
|
||||
fn to_bytes(&self) -> [u8; 32];
|
||||
|
||||
/// Writes an element in compressed form to the buffer.
|
||||
fn write<W: Write>(&self, writer: &mut W) -> io::Result<()> {
|
||||
let compressed = self.to_bytes();
|
||||
writer.write_all(&compressed[..])
|
||||
}
|
||||
|
||||
/// Attempts to obtain a group element from its uncompressed 64-byte little
|
||||
/// endian representation.
|
||||
fn from_bytes_wide(bytes: &[u8; 64]) -> CtOption<Self>;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ use subtle::{Choice, ConstantTimeEq, CtOption};
|
|||
|
||||
use super::Group;
|
||||
|
||||
use std::io::{self, Read, Write};
|
||||
|
||||
const_assert!(size_of::<usize>() >= 4);
|
||||
|
||||
/// This trait is a common interface for dealing with elements of a finite
|
||||
|
|
@ -77,10 +79,25 @@ pub trait FieldExt:
|
|||
/// representation.
|
||||
fn to_bytes(&self) -> [u8; 32];
|
||||
|
||||
/// Writes this element in its normalized, little endian form into a buffer.
|
||||
fn write<W: Write>(&self, writer: &mut W) -> io::Result<()> {
|
||||
let compressed = self.to_bytes();
|
||||
writer.write_all(&compressed[..])
|
||||
}
|
||||
|
||||
/// Attempts to obtain a field element from its normalized, little endian
|
||||
/// byte representation.
|
||||
fn from_bytes(bytes: &[u8; 32]) -> CtOption<Self>;
|
||||
|
||||
/// Reads a normalized, little endian represented field element from a
|
||||
/// buffer.
|
||||
fn read<R: Read>(reader: &mut R) -> io::Result<Self> {
|
||||
let mut compressed = [0u8; 32];
|
||||
reader.read_exact(&mut compressed[..])?;
|
||||
Option::from(Self::from_bytes(&compressed))
|
||||
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "invalid point encoding in proof"))
|
||||
}
|
||||
|
||||
/// Obtains a field element that is congruent to the provided little endian
|
||||
/// byte representation of an integer.
|
||||
fn from_bytes_wide(bytes: &[u8; 64]) -> Self;
|
||||
|
|
|
|||
55
src/plonk.rs
55
src/plonk.rs
|
|
@ -6,7 +6,9 @@
|
|||
//! [plonk]: https://eprint.iacr.org/2019/953
|
||||
|
||||
use crate::arithmetic::CurveAffine;
|
||||
use crate::poly::{Coeff, EvaluationDomain, ExtendedLagrangeCoeff, LagrangeCoeff, Polynomial};
|
||||
use crate::poly::{
|
||||
commitment::Params, Coeff, EvaluationDomain, ExtendedLagrangeCoeff, LagrangeCoeff, Polynomial,
|
||||
};
|
||||
use crate::transcript::ChallengeScalar;
|
||||
|
||||
mod circuit;
|
||||
|
|
@ -23,6 +25,8 @@ pub use keygen::*;
|
|||
pub use prover::*;
|
||||
pub use verifier::*;
|
||||
|
||||
use std::io;
|
||||
|
||||
/// This is a verifying key which allows for the verification of proofs for a
|
||||
/// particular circuit.
|
||||
#[derive(Debug)]
|
||||
|
|
@ -33,6 +37,45 @@ pub struct VerifyingKey<C: CurveAffine> {
|
|||
cs: ConstraintSystem<C::Scalar>,
|
||||
}
|
||||
|
||||
impl<C: CurveAffine> VerifyingKey<C> {
|
||||
/// Writes a verifying key to a buffer.
|
||||
pub fn write<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
|
||||
for commitment in &self.fixed_commitments {
|
||||
writer.write_all(&commitment.to_bytes())?;
|
||||
}
|
||||
for permutation in &self.permutations {
|
||||
permutation.write(writer)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Reads a verification key from a buffer.
|
||||
pub fn read<R: io::Read, ConcreteCircuit: Circuit<C::Scalar>>(
|
||||
reader: &mut R,
|
||||
params: &Params<C>,
|
||||
) -> io::Result<Self> {
|
||||
let (domain, cs, _) = keygen::create_domain::<C, ConcreteCircuit>(params);
|
||||
|
||||
let fixed_commitments: Vec<_> = (0..cs.num_fixed_columns)
|
||||
.map(|_| C::read(reader))
|
||||
.collect::<Result<_, _>>()?;
|
||||
|
||||
let permutations: Vec<_> = cs
|
||||
.permutations
|
||||
.iter()
|
||||
.map(|argument| permutation::VerifyingKey::read(reader, argument))
|
||||
.collect::<Result<_, _>>()?;
|
||||
|
||||
Ok(VerifyingKey {
|
||||
domain,
|
||||
fixed_commitments,
|
||||
permutations,
|
||||
cs,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// This is a proving key which allows for the creation of proofs for a
|
||||
/// particular circuit.
|
||||
#[derive(Debug)]
|
||||
|
|
@ -442,7 +485,8 @@ fn test_proving() {
|
|||
};
|
||||
|
||||
// Initialize the proving key
|
||||
let pk = keygen(¶ms, &empty_circuit).expect("keygen should not fail");
|
||||
let vk = keygen_vk(¶ms, &empty_circuit).expect("keygen_vk should not fail");
|
||||
let pk = keygen_pk(¶ms, vk, &empty_circuit).expect("keygen_pk should not fail");
|
||||
|
||||
let mut pubinputs = pk.get_vk().get_domain().empty_lagrange();
|
||||
pubinputs[0] = aux;
|
||||
|
|
@ -487,8 +531,11 @@ fn test_proving() {
|
|||
let msm = guard.clone().use_challenges();
|
||||
assert!(msm.clone().eval());
|
||||
let mut transcript = DummyHashRead::init(&proof[..], Fq::one());
|
||||
let guard =
|
||||
verify_proof(¶ms, pk.get_vk(), msm, pubinput_slice, &mut transcript).unwrap();
|
||||
let mut vk_buffer = vec![];
|
||||
pk.get_vk().write(&mut vk_buffer).unwrap();
|
||||
let vk = VerifyingKey::<EqAffine>::read::<_, MyCircuit<Fp>>(&mut &vk_buffer[..], ¶ms)
|
||||
.unwrap();
|
||||
let guard = verify_proof(¶ms, &vk, msm, pubinput_slice, &mut transcript).unwrap();
|
||||
{
|
||||
let msm = guard.clone().use_challenges();
|
||||
assert!(msm.eval());
|
||||
|
|
|
|||
|
|
@ -2,72 +2,25 @@ use ff::Field;
|
|||
|
||||
use super::{
|
||||
circuit::{Advice, Assignment, Circuit, Column, ConstraintSystem, Fixed},
|
||||
permutation, Error, ProvingKey, VerifyingKey,
|
||||
permutation, Error, LagrangeCoeff, Polynomial, ProvingKey, VerifyingKey,
|
||||
};
|
||||
use crate::arithmetic::{Curve, CurveAffine};
|
||||
use crate::poly::{
|
||||
commitment::{Blind, Params},
|
||||
EvaluationDomain, LagrangeCoeff, Polynomial, Rotation,
|
||||
EvaluationDomain, Rotation,
|
||||
};
|
||||
|
||||
/// Generate a `ProvingKey` from an instance of `Circuit`.
|
||||
pub fn keygen<C, ConcreteCircuit>(
|
||||
pub(crate) fn create_domain<C, ConcreteCircuit>(
|
||||
params: &Params<C>,
|
||||
circuit: &ConcreteCircuit,
|
||||
) -> Result<ProvingKey<C>, Error>
|
||||
) -> (
|
||||
EvaluationDomain<C::Scalar>,
|
||||
ConstraintSystem<C::Scalar>,
|
||||
ConcreteCircuit::Config,
|
||||
)
|
||||
where
|
||||
C: CurveAffine,
|
||||
ConcreteCircuit: Circuit<C::Scalar>,
|
||||
{
|
||||
struct Assembly<F: Field> {
|
||||
fixed: Vec<Polynomial<F, LagrangeCoeff>>,
|
||||
permutations: Vec<permutation::keygen::Assembly>,
|
||||
_marker: std::marker::PhantomData<F>,
|
||||
}
|
||||
|
||||
impl<F: Field> Assignment<F> for Assembly<F> {
|
||||
fn assign_advice(
|
||||
&mut self,
|
||||
_: Column<Advice>,
|
||||
_: usize,
|
||||
_: impl FnOnce() -> Result<F, Error>,
|
||||
) -> Result<(), Error> {
|
||||
// We only care about fixed columns here
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn assign_fixed(
|
||||
&mut self,
|
||||
column: Column<Fixed>,
|
||||
row: usize,
|
||||
to: impl FnOnce() -> Result<F, Error>,
|
||||
) -> Result<(), Error> {
|
||||
*self
|
||||
.fixed
|
||||
.get_mut(column.index())
|
||||
.and_then(|v| v.get_mut(row))
|
||||
.ok_or(Error::BoundsFailure)? = to()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn copy(
|
||||
&mut self,
|
||||
permutation: usize,
|
||||
left_column: usize,
|
||||
left_row: usize,
|
||||
right_column: usize,
|
||||
right_row: usize,
|
||||
) -> Result<(), Error> {
|
||||
// Check bounds first
|
||||
if permutation >= self.permutations.len() {
|
||||
return Err(Error::BoundsFailure);
|
||||
}
|
||||
|
||||
self.permutations[permutation].copy(left_column, left_row, right_column, right_row)
|
||||
}
|
||||
}
|
||||
|
||||
let mut cs = ConstraintSystem::default();
|
||||
let config = ConcreteCircuit::configure(&mut cs);
|
||||
|
||||
|
|
@ -99,6 +52,71 @@ where
|
|||
|
||||
let domain = EvaluationDomain::new(degree as u32, params.k);
|
||||
|
||||
(domain, cs, config)
|
||||
}
|
||||
|
||||
/// Assembly to be used in circuit synthesis.
|
||||
#[derive(Debug)]
|
||||
pub struct Assembly<F: Field> {
|
||||
fixed: Vec<Polynomial<F, LagrangeCoeff>>,
|
||||
permutations: Vec<permutation::keygen::Assembly>,
|
||||
_marker: std::marker::PhantomData<F>,
|
||||
}
|
||||
|
||||
impl<F: Field> Assignment<F> for Assembly<F> {
|
||||
fn assign_advice(
|
||||
&mut self,
|
||||
_: Column<Advice>,
|
||||
_: usize,
|
||||
_: impl FnOnce() -> Result<F, Error>,
|
||||
) -> Result<(), Error> {
|
||||
// We only care about fixed columns here
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn assign_fixed(
|
||||
&mut self,
|
||||
column: Column<Fixed>,
|
||||
row: usize,
|
||||
to: impl FnOnce() -> Result<F, Error>,
|
||||
) -> Result<(), Error> {
|
||||
*self
|
||||
.fixed
|
||||
.get_mut(column.index())
|
||||
.and_then(|v| v.get_mut(row))
|
||||
.ok_or(Error::BoundsFailure)? = to()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn copy(
|
||||
&mut self,
|
||||
permutation: usize,
|
||||
left_column: usize,
|
||||
left_row: usize,
|
||||
right_column: usize,
|
||||
right_row: usize,
|
||||
) -> Result<(), Error> {
|
||||
// Check bounds first
|
||||
if permutation >= self.permutations.len() {
|
||||
return Err(Error::BoundsFailure);
|
||||
}
|
||||
|
||||
self.permutations[permutation].copy(left_column, left_row, right_column, right_row)
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate a `VerifyingKey` from an instance of `Circuit`.
|
||||
pub fn keygen_vk<C, ConcreteCircuit>(
|
||||
params: &Params<C>,
|
||||
circuit: &ConcreteCircuit,
|
||||
) -> Result<VerifyingKey<C>, Error>
|
||||
where
|
||||
C: CurveAffine,
|
||||
ConcreteCircuit: Circuit<C::Scalar>,
|
||||
{
|
||||
let (domain, cs, config) = create_domain::<C, ConcreteCircuit>(params);
|
||||
|
||||
let mut assembly: Assembly<C::Scalar> = Assembly {
|
||||
fixed: vec![domain.empty_lagrange(); cs.num_fixed_columns],
|
||||
permutations: cs
|
||||
|
|
@ -109,17 +127,17 @@ where
|
|||
_marker: std::marker::PhantomData,
|
||||
};
|
||||
|
||||
// Synthesize the circuit to obtain SRS
|
||||
// Synthesize the circuit to obtain URS
|
||||
circuit.synthesize(&mut assembly, config)?;
|
||||
|
||||
let permutation_helper = permutation::keygen::Assembly::build_helper(params, &cs, &domain);
|
||||
|
||||
let (permutation_pks, permutation_vks) = cs
|
||||
let permutation_vks = cs
|
||||
.permutations
|
||||
.iter()
|
||||
.zip(assembly.permutations.into_iter())
|
||||
.map(|(p, assembly)| assembly.build_keys(params, &domain, &permutation_helper, p))
|
||||
.unzip();
|
||||
.map(|(p, assembly)| assembly.build_vk(params, &domain, &permutation_helper, p))
|
||||
.collect();
|
||||
|
||||
let fixed_commitments = assembly
|
||||
.fixed
|
||||
|
|
@ -127,35 +145,77 @@ where
|
|||
.map(|poly| params.commit_lagrange(poly, Blind::default()).to_affine())
|
||||
.collect();
|
||||
|
||||
Ok(VerifyingKey {
|
||||
domain,
|
||||
fixed_commitments,
|
||||
permutations: permutation_vks,
|
||||
cs,
|
||||
})
|
||||
}
|
||||
|
||||
/// Generate a `ProvingKey` from a `VerifyingKey` and an instance of `Circuit`.
|
||||
pub fn keygen_pk<C, ConcreteCircuit>(
|
||||
params: &Params<C>,
|
||||
vk: VerifyingKey<C>,
|
||||
circuit: &ConcreteCircuit,
|
||||
) -> Result<ProvingKey<C>, Error>
|
||||
where
|
||||
C: CurveAffine,
|
||||
ConcreteCircuit: Circuit<C::Scalar>,
|
||||
{
|
||||
let mut cs = ConstraintSystem::default();
|
||||
let config = ConcreteCircuit::configure(&mut cs);
|
||||
|
||||
let mut assembly: Assembly<C::Scalar> = Assembly {
|
||||
fixed: vec![vk.domain.empty_lagrange(); vk.cs.num_fixed_columns],
|
||||
permutations: vk
|
||||
.cs
|
||||
.permutations
|
||||
.iter()
|
||||
.map(|p| permutation::keygen::Assembly::new(params.n as usize, p))
|
||||
.collect(),
|
||||
_marker: std::marker::PhantomData,
|
||||
};
|
||||
|
||||
// Synthesize the circuit to obtain URS
|
||||
circuit.synthesize(&mut assembly, config)?;
|
||||
|
||||
let fixed_polys: Vec<_> = assembly
|
||||
.fixed
|
||||
.iter()
|
||||
.map(|poly| domain.lagrange_to_coeff(poly.clone()))
|
||||
.map(|poly| vk.domain.lagrange_to_coeff(poly.clone()))
|
||||
.collect();
|
||||
|
||||
let fixed_cosets = cs
|
||||
let fixed_cosets = vk
|
||||
.cs
|
||||
.fixed_queries
|
||||
.iter()
|
||||
.map(|&(column, at)| {
|
||||
let poly = fixed_polys[column.index()].clone();
|
||||
domain.coeff_to_extended(poly, at)
|
||||
vk.domain.coeff_to_extended(poly, at)
|
||||
})
|
||||
.collect();
|
||||
|
||||
let permutation_helper =
|
||||
permutation::keygen::Assembly::build_helper(params, &vk.cs, &vk.domain);
|
||||
|
||||
let permutation_pks = vk
|
||||
.cs
|
||||
.permutations
|
||||
.iter()
|
||||
.zip(assembly.permutations.into_iter())
|
||||
.map(|(p, assembly)| assembly.build_pk(&vk.domain, &permutation_helper, p))
|
||||
.collect();
|
||||
|
||||
// Compute l_0(X)
|
||||
// TODO: this can be done more efficiently
|
||||
let mut l0 = domain.empty_lagrange();
|
||||
let mut l0 = vk.domain.empty_lagrange();
|
||||
l0[0] = C::Scalar::one();
|
||||
let l0 = domain.lagrange_to_coeff(l0);
|
||||
let l0 = domain.coeff_to_extended(l0, Rotation::cur());
|
||||
let l0 = vk.domain.lagrange_to_coeff(l0);
|
||||
let l0 = vk.domain.coeff_to_extended(l0, Rotation::cur());
|
||||
|
||||
Ok(ProvingKey {
|
||||
vk: VerifyingKey {
|
||||
domain,
|
||||
fixed_commitments,
|
||||
permutations: permutation_vks,
|
||||
cs,
|
||||
},
|
||||
vk,
|
||||
l0,
|
||||
fixed_values: assembly.fixed,
|
||||
fixed_polys,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ pub(crate) mod keygen;
|
|||
mod prover;
|
||||
mod verifier;
|
||||
|
||||
use std::io;
|
||||
|
||||
/// A permutation argument.
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct Argument {
|
||||
|
|
@ -49,6 +51,23 @@ pub(crate) struct VerifyingKey<C: CurveAffine> {
|
|||
commitments: Vec<C>,
|
||||
}
|
||||
|
||||
impl<C: CurveAffine> VerifyingKey<C> {
|
||||
pub(crate) fn write<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
|
||||
for commitment in &self.commitments {
|
||||
commitment.write(writer)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn read<R: io::Read>(reader: &mut R, argument: &Argument) -> io::Result<Self> {
|
||||
let commitments = (0..argument.columns.len())
|
||||
.map(|_| C::read(reader))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
Ok(VerifyingKey { commitments })
|
||||
}
|
||||
}
|
||||
|
||||
/// The proving key for a single permutation argument.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct ProvingKey<C: CurveAffine> {
|
||||
|
|
|
|||
|
|
@ -132,19 +132,15 @@ impl Assembly {
|
|||
AssemblyHelper { deltaomega }
|
||||
}
|
||||
|
||||
pub(crate) fn build_keys<C: CurveAffine>(
|
||||
pub(crate) fn build_vk<C: CurveAffine>(
|
||||
self,
|
||||
params: &Params<C>,
|
||||
domain: &EvaluationDomain<C::Scalar>,
|
||||
helper: &AssemblyHelper<C>,
|
||||
p: &Argument,
|
||||
) -> (ProvingKey<C>, VerifyingKey<C>) {
|
||||
// Compute permutation polynomials, convert to coset form and
|
||||
// pre-compute commitments for the SRS.
|
||||
) -> VerifyingKey<C> {
|
||||
// Pre-compute commitments for the URS.
|
||||
let mut commitments = vec![];
|
||||
let mut permutations = vec![];
|
||||
let mut polys = vec![];
|
||||
let mut cosets = vec![];
|
||||
for i in 0..p.columns.len() {
|
||||
// Computes the permutation polynomial based on the permutation
|
||||
// description in the assembly.
|
||||
|
|
@ -160,19 +156,39 @@ impl Assembly {
|
|||
.commit_lagrange(&permutation_poly, Blind::default())
|
||||
.to_affine(),
|
||||
);
|
||||
}
|
||||
VerifyingKey { commitments }
|
||||
}
|
||||
|
||||
pub(crate) fn build_pk<C: CurveAffine>(
|
||||
self,
|
||||
domain: &EvaluationDomain<C::Scalar>,
|
||||
helper: &AssemblyHelper<C>,
|
||||
p: &Argument,
|
||||
) -> ProvingKey<C> {
|
||||
// Compute permutation polynomials, convert to coset form.
|
||||
let mut permutations = vec![];
|
||||
let mut polys = vec![];
|
||||
let mut cosets = vec![];
|
||||
for i in 0..p.columns.len() {
|
||||
// Computes the permutation polynomial based on the permutation
|
||||
// description in the assembly.
|
||||
let mut permutation_poly = domain.empty_lagrange();
|
||||
for (j, p) in permutation_poly.iter_mut().enumerate() {
|
||||
let (permuted_i, permuted_j) = self.mapping[i][j];
|
||||
*p = helper.deltaomega[permuted_i][permuted_j];
|
||||
}
|
||||
|
||||
// Store permutation polynomial and precompute its coset evaluation
|
||||
permutations.push(permutation_poly.clone());
|
||||
let poly = domain.lagrange_to_coeff(permutation_poly);
|
||||
polys.push(poly.clone());
|
||||
cosets.push(domain.coeff_to_extended(poly, Rotation::cur()));
|
||||
}
|
||||
(
|
||||
ProvingKey {
|
||||
permutations,
|
||||
polys,
|
||||
cosets,
|
||||
},
|
||||
VerifyingKey { commitments },
|
||||
)
|
||||
ProvingKey {
|
||||
permutations,
|
||||
polys,
|
||||
cosets,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ pub use msm::MSM;
|
|||
pub use prover::create_proof;
|
||||
pub use verifier::{verify_proof, Accumulator, Guard};
|
||||
|
||||
use std::io;
|
||||
|
||||
/// These are the public parameters for the polynomial commitment scheme.
|
||||
#[derive(Debug)]
|
||||
pub struct Params<C: CurveAffine> {
|
||||
|
|
@ -188,6 +190,45 @@ impl<C: CurveAffine> Params<C> {
|
|||
pub fn get_g(&self) -> Vec<C> {
|
||||
self.g.clone()
|
||||
}
|
||||
|
||||
/// Writes params to a buffer.
|
||||
pub fn write<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
|
||||
writer.write_all(&self.k.to_le_bytes())?;
|
||||
for g_element in &self.g {
|
||||
writer.write_all(&g_element.to_bytes())?;
|
||||
}
|
||||
for g_lagrange_element in &self.g_lagrange {
|
||||
writer.write_all(&g_lagrange_element.to_bytes())?;
|
||||
}
|
||||
writer.write_all(&self.h.to_bytes())?;
|
||||
writer.write_all(&self.u.to_bytes())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Reads params from a buffer.
|
||||
pub fn read<R: io::Read>(reader: &mut R) -> io::Result<Self> {
|
||||
let mut k = [0u8; 4];
|
||||
reader.read_exact(&mut k[..])?;
|
||||
let k = u32::from_le_bytes(k);
|
||||
|
||||
let n: u64 = 1 << k;
|
||||
|
||||
let g: Vec<_> = (0..n).map(|_| C::read(reader)).collect::<Result<_, _>>()?;
|
||||
let g_lagrange: Vec<_> = (0..n).map(|_| C::read(reader)).collect::<Result<_, _>>()?;
|
||||
|
||||
let h = C::read(reader)?;
|
||||
let u = C::read(reader)?;
|
||||
|
||||
Ok(Params {
|
||||
k,
|
||||
n,
|
||||
g,
|
||||
g_lagrange,
|
||||
h,
|
||||
u,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Wrapper type around a blinding factor.
|
||||
|
|
@ -292,13 +333,17 @@ fn test_opening_proof() {
|
|||
commitment::{Blind, Params},
|
||||
EvaluationDomain,
|
||||
};
|
||||
use crate::arithmetic::{eval_polynomial, Curve, FieldExt};
|
||||
use crate::arithmetic::{eval_polynomial, FieldExt};
|
||||
use crate::pasta::{EpAffine, Fq};
|
||||
use crate::transcript::{
|
||||
ChallengeScalar, DummyHashRead, DummyHashWrite, Transcript, TranscriptRead, TranscriptWrite,
|
||||
};
|
||||
|
||||
let params = Params::<EpAffine>::new(K);
|
||||
let mut params_buffer = vec![];
|
||||
params.write(&mut params_buffer).unwrap();
|
||||
let params: Params<EpAffine> = Params::read::<_>(&mut ¶ms_buffer[..]).unwrap();
|
||||
|
||||
let domain = EvaluationDomain::new(1, K);
|
||||
|
||||
let mut px = domain.empty_coeff();
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ use std::io;
|
|||
/// **Important:** This function assumes that the provided `transcript` has
|
||||
/// already seen the common inputs: the polynomial commitment P, the claimed
|
||||
/// opening v, and the point x. It's probably also nice for the transcript
|
||||
/// to have seen the elliptic curve description and the SRS, if you want to
|
||||
/// to have seen the elliptic curve description and the URS, if you want to
|
||||
/// be rigorous.
|
||||
pub fn create_proof<C: CurveAffine, T: TranscriptWrite<C>>(
|
||||
params: &Params<C>,
|
||||
|
|
@ -82,7 +82,7 @@ pub fn create_proof<C: CurveAffine, T: TranscriptWrite<C>>(
|
|||
}
|
||||
}
|
||||
|
||||
// Initialize the vector `G` from the SRS. We'll be progressively collapsing
|
||||
// Initialize the vector `G` from the URS. We'll be progressively collapsing
|
||||
// this vector into smaller and smaller vectors until it is of length 1.
|
||||
let mut g = params.g.clone();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue