opt ready

This commit is contained in:
Dmitry Khovratovich
2024-02-06 17:09:38 +01:00
parent 4768d0e5cf
commit 0a2626274a
3 changed files with 211 additions and 12 deletions

101
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,101 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Debug unit tests in library 'caulk'",
"cargo": {
"args": [
"test",
"--no-run",
"--lib",
"--package=caulk"
],
"filter": {
"name": "caulk",
"kind": "lib"
}
},
"args": [],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug example 'multi_lookup'",
"cargo": {
"args": [
"build",
"--example=multi_lookup",
"--package=caulk"
],
"filter": {
"name": "multi_lookup",
"kind": "example"
}
},
"args": [],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug unit tests in example 'multi_lookup'",
"cargo": {
"args": [
"test",
"--no-run",
"--example=multi_lookup",
"--package=caulk"
],
"filter": {
"name": "multi_lookup",
"kind": "example"
}
},
"args": [],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug example 'single_opening'",
"cargo": {
"args": [
"build",
"--example=single_opening",
"--package=caulk"
],
"filter": {
"name": "single_opening",
"kind": "example"
}
},
"args": [],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug unit tests in example 'single_opening'",
"cargo": {
"args": [
"test",
"--no-run",
"--example=single_opening",
"--package=caulk"
],
"filter": {
"name": "single_opening",
"kind": "example"
}
},
"args": [],
"cwd": "${workspaceFolder}"
}
]
}

View File

@@ -72,7 +72,7 @@ where
// h_i= c_d[x^{d-i-1}]+c_{d-1}[x^{d-i-2}]+c_{d-2}[x^{d-i-3}]+\cdots +
// c_{i+2}[x]+c_{i+1}[1]
pub fn compute_h_23<F, G>(
c_poly: &DensePolynomial<F>, /* c(X) degree up to d<2^p , i.e. c_poly has at most d+1 coeffs
c_poly: &DensePolynomial<F>, /* c(X) degree up to d<=2^p , i.e. c_poly has at most d+1 coeffs
* non-zero */
powers: &[G], // SRS
p: usize,
@@ -87,36 +87,40 @@ where
let fpzero = F::zero();
coeffs.resize(dom_size, fpzero);
// 1. x_ext = [[x^(d-1)], [x^{d-2},...,[x],[1], d+2 [0]'s]
// 1. x_ext = [[x^(d-1)], [x^{d-2},...,[x],[1], d [0]'s]
let step1_timer = start_timer!(|| "step 1");
let mut x_ext: Vec<G> = powers.iter().take(dom_size - 1).rev().copied().collect();
x_ext.resize(2 * dom_size, G::zero()); // filling 2d+2 neutral elements
x_ext.resize(2 * dom_size, G::zero()); // filling 2d neutral elements
let y = group_dft::<F, G>(&x_ext, p + 1);
end_timer!(step1_timer);
// 2. c_ext = [c_d, d zeroes, c_d,c_{0},c_1,...,c_{d-2},c_{d-1}]
// 2. c_ext = [ d zeroes, c_{0},c_1,...,c_{d-2},c_{d-1}]
let step2_timer = start_timer!(|| "step 2");
let mut c_ext = vec![coeffs[coeffs.len() - 1]];
let mut c_ext = vec![fpzero];
c_ext.resize(dom_size, fpzero);
c_ext.push(coeffs[coeffs.len() - 1]);
for &e in coeffs.iter().take(coeffs.len() - 1) {
for &e in coeffs.iter().take(coeffs.len()) {
c_ext.push(e);
}
assert_eq!(c_ext.len(), 2 * dom_size);
let v = field_dft::<F>(&c_ext, p + 1);
let mut v = field_dft::<F>(&c_ext, p + 1);
end_timer!(step2_timer);
// 3. u = y o v
// 3. u = y o v o powers
let step3_timer = start_timer!(|| "step 3");
let input_domain: GeneralEvaluationDomain<F> = EvaluationDomain::new(2*dom_size).unwrap();
for i in 0..2*dom_size{
v[i] = v[i].mul(input_domain.element(i));
}
let u: Vec<_> = y
.into_iter()
.zip(v.into_iter())
.map(|(a, b)| a.mul(b.into_repr()))
.collect();
end_timer!(step3_timer);
// 4. h_ext = idft_{2d+2}(u)
// 4. h_ext = idft_{2d}(u)
let step4_timer = start_timer!(|| "step 4");
let h_ext = group_inv_dft::<F, G>(&u, p + 1);
end_timer!(step4_timer);
@@ -125,6 +129,61 @@ where
h_ext[0..dom_size].to_vec()
}
// compute all pre-proofs using DFT
// h_i= c_d[x^{d-i-1}]+c_{d-1}[x^{d-i-2}]+c_{d-2}[x^{d-i-3}]+\cdots +
// c_{i+2}[x]+c_{i+1}[1]
pub fn compute_h_evals<F, G>(
c_poly: &DensePolynomial<F>, /* c(X) degree up to d<=2^p , i.e. c_poly has at most d+1 coeffs
* non-zero */
powers: &[G], // SRS
p: usize,
) -> Vec<G>
where
F: PrimeField,
G: ProjectiveCurve,
{
let timer = start_timer!(|| "compute h");
let mut coeffs = c_poly.coeffs().to_vec();
let dom_size = 1 << p;
let fpzero = F::zero();
coeffs.resize(dom_size, fpzero);
// 1. x_ext = [[x^(d-1)], [x^{d-2},...,[x],[1], d [0]'s]
let step1_timer = start_timer!(|| "step 1");
let mut x_ext: Vec<G> = powers.iter().take(dom_size - 1).rev().copied().collect();
x_ext.resize(2 * dom_size, G::zero()); // filling 2d neutral elements
let y = group_dft::<F, G>(&x_ext, p + 1);
end_timer!(step1_timer);
// 2. c_ext = [ d zeroes, c_{0},c_1,...,c_{d-2},c_{d-1}]
let step2_timer = start_timer!(|| "step 2");
let mut c_ext = vec![fpzero];
c_ext.resize(dom_size, fpzero);
for &e in coeffs.iter().take(coeffs.len()) {
c_ext.push(e);
}
assert_eq!(c_ext.len(), 2 * dom_size);
let mut v = field_dft::<F>(&c_ext, p + 1);
end_timer!(step2_timer);
// 3. u = y o v o powers
let step3_timer = start_timer!(|| "step 3");
let input_domain: GeneralEvaluationDomain<F> = EvaluationDomain::new(2*dom_size).unwrap();
for i in 0..2*dom_size{
v[i] = v[i].mul(input_domain.element(i));
}
let u: Vec<_> = y
.into_iter()
.zip(v.into_iter())
.map(|(a, b)| a.mul(b.into_repr()))
.collect();
end_timer!(step3_timer);
u
}
// compute DFT of size @dom_size over vector of Fr elements
// q_i = h_0 + h_1w^i + h_2w^{2i}+\cdots + h_{dom_size-1}w^{(dom_size-1)i} for
// 0<= i< dom_size=2^p

View File

@@ -5,7 +5,7 @@
// (4) hash_caulk_single is for hashing group and field elements into a field
// element (5) random_field is for generating random field elements
use crate::{compute_h,compute_h_23, group_dft, util::convert_to_bigints};
use crate::{compute_h,compute_h_23, compute_h_evals, group_dft, util::convert_to_bigints};
use ark_ec::{msm::VariableBaseMSM, AffineCurve, PairingEngine, ProjectiveCurve};
use ark_ff::{Field, PrimeField};
use ark_poly::{
@@ -156,6 +156,45 @@ impl<E: PairingEngine> KZGCommit<E> {
res
}
// compute all openings to c_poly using a smart formula
// This Code implements an algorithm for calculating n openings of a KZG vector
// commitment of size n in n log(n) time. The algorithm is by Feist and
// Khovratovich updated in the 2023 paper https://eprint.iacr.org/2023/033.pdf
pub fn multiple_open_24<G>(
c_poly: &DensePolynomial<E::Fr>, // c(X)
powers: &[G], // SRS
p: usize,
) -> Vec<G>
where
G: AffineCurve<ScalarField = E::Fr> + Sized,
{
let timer = start_timer!(|| "multiple open");
let degree = c_poly.coeffs.len() - 1;
let input_domain: GeneralEvaluationDomain<E::Fr> = EvaluationDomain::new(degree).unwrap();
let h_timer = start_timer!(|| "compute h");
let powers: Vec<G::Projective> = powers.iter().map(|x| x.into_projective()).collect();
let h2 = compute_h_evals(c_poly, &powers, p);
end_timer!(h_timer);
let dom_size = input_domain.size();
assert_eq!(1 << p, dom_size);
assert_eq!(degree + 1, dom_size);
let mut q2 = vec![h2[0]];
for i in 1..dom_size{
q2.push(h2[2*i]);
}
let normalization_timer = start_timer!(|| "batch normalization");
let res = G::Projective::batch_normalization_into_affine(q2.as_ref());
end_timer!(normalization_timer);
end_timer!(timer);
res
}
////////////////////////////////////////////////
// KZG.Open( srs_KZG, f(X, Y), deg, alpha )
// returns ([f(alpha, x)]_1, pi)
@@ -686,7 +725,7 @@ pub mod tests {
let mut rng = test_rng();
// current kzg setup should be changed with output from a setup ceremony
let p: usize = 4;
let p: usize = 8;
let max_degree: usize = 1 << p + 1;
let actual_degree: usize = (1 << p) - 1;
let pp = caulk_single_setup(max_degree, actual_degree, &mut rng);