mirror of
https://github.com/saymrwulf/pasta_curves-source.git
synced 2026-09-05 20:10:32 +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 };
|
let empty_circuit: MyCircuit<Fp> = MyCircuit { a: None, k };
|
||||||
|
|
||||||
// Initialize the proving key
|
// 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 prover_name = name.to_string() + "-prover";
|
||||||
let verifier_name = name.to_string() + "-verifier";
|
let verifier_name = name.to_string() + "-verifier";
|
||||||
|
|
|
||||||
|
|
@ -257,7 +257,8 @@ fn main() {
|
||||||
let empty_circuit: MyCircuit<Fp> = MyCircuit { a: None, k };
|
let empty_circuit: MyCircuit<Fp> = MyCircuit { a: None, k };
|
||||||
|
|
||||||
// Initialize the proving key
|
// 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);
|
println!("[Keygen] {}", recorder);
|
||||||
recorder.clear();
|
recorder.clear();
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@ use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
|
||||||
|
|
||||||
use super::{FieldExt, Group};
|
use super::{FieldExt, Group};
|
||||||
|
|
||||||
|
use std::io::{self, Read, Write};
|
||||||
|
|
||||||
/// This trait is a common interface for dealing with elements of an elliptic
|
/// 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
|
/// curve group in the "projective" form, where that arithmetic is usually more
|
||||||
/// efficient.
|
/// efficient.
|
||||||
|
|
@ -153,10 +155,25 @@ pub trait CurveAffine:
|
||||||
/// endian representation.
|
/// endian representation.
|
||||||
fn from_bytes(bytes: &[u8; 32]) -> CtOption<Self>;
|
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
|
/// Obtains the compressed, 32-byte little endian representation of this
|
||||||
/// element.
|
/// element.
|
||||||
fn to_bytes(&self) -> [u8; 32];
|
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
|
/// Attempts to obtain a group element from its uncompressed 64-byte little
|
||||||
/// endian representation.
|
/// endian representation.
|
||||||
fn from_bytes_wide(bytes: &[u8; 64]) -> CtOption<Self>;
|
fn from_bytes_wide(bytes: &[u8; 64]) -> CtOption<Self>;
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@ use subtle::{Choice, ConstantTimeEq, CtOption};
|
||||||
|
|
||||||
use super::Group;
|
use super::Group;
|
||||||
|
|
||||||
|
use std::io::{self, Read, Write};
|
||||||
|
|
||||||
const_assert!(size_of::<usize>() >= 4);
|
const_assert!(size_of::<usize>() >= 4);
|
||||||
|
|
||||||
/// This trait is a common interface for dealing with elements of a finite
|
/// This trait is a common interface for dealing with elements of a finite
|
||||||
|
|
@ -77,10 +79,25 @@ pub trait FieldExt:
|
||||||
/// representation.
|
/// representation.
|
||||||
fn to_bytes(&self) -> [u8; 32];
|
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
|
/// Attempts to obtain a field element from its normalized, little endian
|
||||||
/// byte representation.
|
/// byte representation.
|
||||||
fn from_bytes(bytes: &[u8; 32]) -> CtOption<Self>;
|
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
|
/// Obtains a field element that is congruent to the provided little endian
|
||||||
/// byte representation of an integer.
|
/// byte representation of an integer.
|
||||||
fn from_bytes_wide(bytes: &[u8; 64]) -> Self;
|
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
|
//! [plonk]: https://eprint.iacr.org/2019/953
|
||||||
|
|
||||||
use crate::arithmetic::CurveAffine;
|
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;
|
use crate::transcript::ChallengeScalar;
|
||||||
|
|
||||||
mod circuit;
|
mod circuit;
|
||||||
|
|
@ -23,6 +25,8 @@ pub use keygen::*;
|
||||||
pub use prover::*;
|
pub use prover::*;
|
||||||
pub use verifier::*;
|
pub use verifier::*;
|
||||||
|
|
||||||
|
use std::io;
|
||||||
|
|
||||||
/// This is a verifying key which allows for the verification of proofs for a
|
/// This is a verifying key which allows for the verification of proofs for a
|
||||||
/// particular circuit.
|
/// particular circuit.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -33,6 +37,45 @@ pub struct VerifyingKey<C: CurveAffine> {
|
||||||
cs: ConstraintSystem<C::Scalar>,
|
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
|
/// This is a proving key which allows for the creation of proofs for a
|
||||||
/// particular circuit.
|
/// particular circuit.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -442,7 +485,8 @@ fn test_proving() {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Initialize the proving key
|
// 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();
|
let mut pubinputs = pk.get_vk().get_domain().empty_lagrange();
|
||||||
pubinputs[0] = aux;
|
pubinputs[0] = aux;
|
||||||
|
|
@ -487,8 +531,11 @@ fn test_proving() {
|
||||||
let msm = guard.clone().use_challenges();
|
let msm = guard.clone().use_challenges();
|
||||||
assert!(msm.clone().eval());
|
assert!(msm.clone().eval());
|
||||||
let mut transcript = DummyHashRead::init(&proof[..], Fq::one());
|
let mut transcript = DummyHashRead::init(&proof[..], Fq::one());
|
||||||
let guard =
|
let mut vk_buffer = vec![];
|
||||||
verify_proof(¶ms, pk.get_vk(), msm, pubinput_slice, &mut transcript).unwrap();
|
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();
|
let msm = guard.clone().use_challenges();
|
||||||
assert!(msm.eval());
|
assert!(msm.eval());
|
||||||
|
|
|
||||||
|
|
@ -2,72 +2,25 @@ use ff::Field;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
circuit::{Advice, Assignment, Circuit, Column, ConstraintSystem, Fixed},
|
circuit::{Advice, Assignment, Circuit, Column, ConstraintSystem, Fixed},
|
||||||
permutation, Error, ProvingKey, VerifyingKey,
|
permutation, Error, LagrangeCoeff, Polynomial, ProvingKey, VerifyingKey,
|
||||||
};
|
};
|
||||||
use crate::arithmetic::{Curve, CurveAffine};
|
use crate::arithmetic::{Curve, CurveAffine};
|
||||||
use crate::poly::{
|
use crate::poly::{
|
||||||
commitment::{Blind, Params},
|
commitment::{Blind, Params},
|
||||||
EvaluationDomain, LagrangeCoeff, Polynomial, Rotation,
|
EvaluationDomain, Rotation,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Generate a `ProvingKey` from an instance of `Circuit`.
|
pub(crate) fn create_domain<C, ConcreteCircuit>(
|
||||||
pub fn keygen<C, ConcreteCircuit>(
|
|
||||||
params: &Params<C>,
|
params: &Params<C>,
|
||||||
circuit: &ConcreteCircuit,
|
) -> (
|
||||||
) -> Result<ProvingKey<C>, Error>
|
EvaluationDomain<C::Scalar>,
|
||||||
|
ConstraintSystem<C::Scalar>,
|
||||||
|
ConcreteCircuit::Config,
|
||||||
|
)
|
||||||
where
|
where
|
||||||
C: CurveAffine,
|
C: CurveAffine,
|
||||||
ConcreteCircuit: Circuit<C::Scalar>,
|
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 mut cs = ConstraintSystem::default();
|
||||||
let config = ConcreteCircuit::configure(&mut cs);
|
let config = ConcreteCircuit::configure(&mut cs);
|
||||||
|
|
||||||
|
|
@ -99,6 +52,71 @@ where
|
||||||
|
|
||||||
let domain = EvaluationDomain::new(degree as u32, params.k);
|
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 {
|
let mut assembly: Assembly<C::Scalar> = Assembly {
|
||||||
fixed: vec![domain.empty_lagrange(); cs.num_fixed_columns],
|
fixed: vec![domain.empty_lagrange(); cs.num_fixed_columns],
|
||||||
permutations: cs
|
permutations: cs
|
||||||
|
|
@ -109,17 +127,17 @@ where
|
||||||
_marker: std::marker::PhantomData,
|
_marker: std::marker::PhantomData,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Synthesize the circuit to obtain SRS
|
// Synthesize the circuit to obtain URS
|
||||||
circuit.synthesize(&mut assembly, config)?;
|
circuit.synthesize(&mut assembly, config)?;
|
||||||
|
|
||||||
let permutation_helper = permutation::keygen::Assembly::build_helper(params, &cs, &domain);
|
let permutation_helper = permutation::keygen::Assembly::build_helper(params, &cs, &domain);
|
||||||
|
|
||||||
let (permutation_pks, permutation_vks) = cs
|
let permutation_vks = cs
|
||||||
.permutations
|
.permutations
|
||||||
.iter()
|
.iter()
|
||||||
.zip(assembly.permutations.into_iter())
|
.zip(assembly.permutations.into_iter())
|
||||||
.map(|(p, assembly)| assembly.build_keys(params, &domain, &permutation_helper, p))
|
.map(|(p, assembly)| assembly.build_vk(params, &domain, &permutation_helper, p))
|
||||||
.unzip();
|
.collect();
|
||||||
|
|
||||||
let fixed_commitments = assembly
|
let fixed_commitments = assembly
|
||||||
.fixed
|
.fixed
|
||||||
|
|
@ -127,35 +145,77 @@ where
|
||||||
.map(|poly| params.commit_lagrange(poly, Blind::default()).to_affine())
|
.map(|poly| params.commit_lagrange(poly, Blind::default()).to_affine())
|
||||||
.collect();
|
.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
|
let fixed_polys: Vec<_> = assembly
|
||||||
.fixed
|
.fixed
|
||||||
.iter()
|
.iter()
|
||||||
.map(|poly| domain.lagrange_to_coeff(poly.clone()))
|
.map(|poly| vk.domain.lagrange_to_coeff(poly.clone()))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let fixed_cosets = cs
|
let fixed_cosets = vk
|
||||||
|
.cs
|
||||||
.fixed_queries
|
.fixed_queries
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&(column, at)| {
|
.map(|&(column, at)| {
|
||||||
let poly = fixed_polys[column.index()].clone();
|
let poly = fixed_polys[column.index()].clone();
|
||||||
domain.coeff_to_extended(poly, at)
|
vk.domain.coeff_to_extended(poly, at)
|
||||||
})
|
})
|
||||||
.collect();
|
.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)
|
// Compute l_0(X)
|
||||||
// TODO: this can be done more efficiently
|
// 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();
|
l0[0] = C::Scalar::one();
|
||||||
let l0 = domain.lagrange_to_coeff(l0);
|
let l0 = vk.domain.lagrange_to_coeff(l0);
|
||||||
let l0 = domain.coeff_to_extended(l0, Rotation::cur());
|
let l0 = vk.domain.coeff_to_extended(l0, Rotation::cur());
|
||||||
|
|
||||||
Ok(ProvingKey {
|
Ok(ProvingKey {
|
||||||
vk: VerifyingKey {
|
vk,
|
||||||
domain,
|
|
||||||
fixed_commitments,
|
|
||||||
permutations: permutation_vks,
|
|
||||||
cs,
|
|
||||||
},
|
|
||||||
l0,
|
l0,
|
||||||
fixed_values: assembly.fixed,
|
fixed_values: assembly.fixed,
|
||||||
fixed_polys,
|
fixed_polys,
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@ pub(crate) mod keygen;
|
||||||
mod prover;
|
mod prover;
|
||||||
mod verifier;
|
mod verifier;
|
||||||
|
|
||||||
|
use std::io;
|
||||||
|
|
||||||
/// A permutation argument.
|
/// A permutation argument.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct Argument {
|
pub(crate) struct Argument {
|
||||||
|
|
@ -49,6 +51,23 @@ pub(crate) struct VerifyingKey<C: CurveAffine> {
|
||||||
commitments: Vec<C>,
|
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.
|
/// The proving key for a single permutation argument.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct ProvingKey<C: CurveAffine> {
|
pub(crate) struct ProvingKey<C: CurveAffine> {
|
||||||
|
|
|
||||||
|
|
@ -132,19 +132,15 @@ impl Assembly {
|
||||||
AssemblyHelper { deltaomega }
|
AssemblyHelper { deltaomega }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn build_keys<C: CurveAffine>(
|
pub(crate) fn build_vk<C: CurveAffine>(
|
||||||
self,
|
self,
|
||||||
params: &Params<C>,
|
params: &Params<C>,
|
||||||
domain: &EvaluationDomain<C::Scalar>,
|
domain: &EvaluationDomain<C::Scalar>,
|
||||||
helper: &AssemblyHelper<C>,
|
helper: &AssemblyHelper<C>,
|
||||||
p: &Argument,
|
p: &Argument,
|
||||||
) -> (ProvingKey<C>, VerifyingKey<C>) {
|
) -> VerifyingKey<C> {
|
||||||
// Compute permutation polynomials, convert to coset form and
|
// Pre-compute commitments for the URS.
|
||||||
// pre-compute commitments for the SRS.
|
|
||||||
let mut commitments = vec![];
|
let mut commitments = vec![];
|
||||||
let mut permutations = vec![];
|
|
||||||
let mut polys = vec![];
|
|
||||||
let mut cosets = vec![];
|
|
||||||
for i in 0..p.columns.len() {
|
for i in 0..p.columns.len() {
|
||||||
// Computes the permutation polynomial based on the permutation
|
// Computes the permutation polynomial based on the permutation
|
||||||
// description in the assembly.
|
// description in the assembly.
|
||||||
|
|
@ -160,19 +156,39 @@ impl Assembly {
|
||||||
.commit_lagrange(&permutation_poly, Blind::default())
|
.commit_lagrange(&permutation_poly, Blind::default())
|
||||||
.to_affine(),
|
.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
|
// Store permutation polynomial and precompute its coset evaluation
|
||||||
permutations.push(permutation_poly.clone());
|
permutations.push(permutation_poly.clone());
|
||||||
let poly = domain.lagrange_to_coeff(permutation_poly);
|
let poly = domain.lagrange_to_coeff(permutation_poly);
|
||||||
polys.push(poly.clone());
|
polys.push(poly.clone());
|
||||||
cosets.push(domain.coeff_to_extended(poly, Rotation::cur()));
|
cosets.push(domain.coeff_to_extended(poly, Rotation::cur()));
|
||||||
}
|
}
|
||||||
(
|
ProvingKey {
|
||||||
ProvingKey {
|
permutations,
|
||||||
permutations,
|
polys,
|
||||||
polys,
|
cosets,
|
||||||
cosets,
|
}
|
||||||
},
|
|
||||||
VerifyingKey { commitments },
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,8 @@ pub use msm::MSM;
|
||||||
pub use prover::create_proof;
|
pub use prover::create_proof;
|
||||||
pub use verifier::{verify_proof, Accumulator, Guard};
|
pub use verifier::{verify_proof, Accumulator, Guard};
|
||||||
|
|
||||||
|
use std::io;
|
||||||
|
|
||||||
/// These are the public parameters for the polynomial commitment scheme.
|
/// These are the public parameters for the polynomial commitment scheme.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Params<C: CurveAffine> {
|
pub struct Params<C: CurveAffine> {
|
||||||
|
|
@ -188,6 +190,45 @@ impl<C: CurveAffine> Params<C> {
|
||||||
pub fn get_g(&self) -> Vec<C> {
|
pub fn get_g(&self) -> Vec<C> {
|
||||||
self.g.clone()
|
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.
|
/// Wrapper type around a blinding factor.
|
||||||
|
|
@ -292,13 +333,17 @@ fn test_opening_proof() {
|
||||||
commitment::{Blind, Params},
|
commitment::{Blind, Params},
|
||||||
EvaluationDomain,
|
EvaluationDomain,
|
||||||
};
|
};
|
||||||
use crate::arithmetic::{eval_polynomial, Curve, FieldExt};
|
use crate::arithmetic::{eval_polynomial, FieldExt};
|
||||||
use crate::pasta::{EpAffine, Fq};
|
use crate::pasta::{EpAffine, Fq};
|
||||||
use crate::transcript::{
|
use crate::transcript::{
|
||||||
ChallengeScalar, DummyHashRead, DummyHashWrite, Transcript, TranscriptRead, TranscriptWrite,
|
ChallengeScalar, DummyHashRead, DummyHashWrite, Transcript, TranscriptRead, TranscriptWrite,
|
||||||
};
|
};
|
||||||
|
|
||||||
let params = Params::<EpAffine>::new(K);
|
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 domain = EvaluationDomain::new(1, K);
|
||||||
|
|
||||||
let mut px = domain.empty_coeff();
|
let mut px = domain.empty_coeff();
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ use std::io;
|
||||||
/// **Important:** This function assumes that the provided `transcript` has
|
/// **Important:** This function assumes that the provided `transcript` has
|
||||||
/// already seen the common inputs: the polynomial commitment P, the claimed
|
/// 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
|
/// 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.
|
/// be rigorous.
|
||||||
pub fn create_proof<C: CurveAffine, T: TranscriptWrite<C>>(
|
pub fn create_proof<C: CurveAffine, T: TranscriptWrite<C>>(
|
||||||
params: &Params<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.
|
// this vector into smaller and smaller vectors until it is of length 1.
|
||||||
let mut g = params.g.clone();
|
let mut g = params.g.clone();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue