-
Notifications
You must be signed in to change notification settings - Fork 5
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
chore: Initial impl for KZG10 #234
Draft
kevaundray
wants to merge
3
commits into
master
Choose a base branch
from
kw/single-open
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
[package] | ||
name = "crate_crypto_kzg_single_open" | ||
description = "This crate provides an implementation for KZG10 suited for DAS in Ethereum" | ||
version = { workspace = true } | ||
authors = { workspace = true } | ||
edition = { workspace = true } | ||
license = { workspace = true } | ||
rust-version = { workspace = true } | ||
repository = { workspace = true } | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
bls12_381 = { workspace = true } | ||
polynomial = { workspace = true } | ||
hex = { workspace = true } | ||
rayon = { workspace = true } | ||
# We should not be importing this library here | ||
# We need it for the CommitKey | ||
kzg_multi_open = { workspace = true } | ||
pairing = { version = "0.23" } | ||
|
||
|
||
[dev-dependencies] | ||
criterion = "0.5.1" | ||
rand = "0.8.4" | ||
|
||
[[bench]] | ||
name = "benchmark" | ||
harness = false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
use bls12_381::Scalar; | ||
use bls12_381::{ff::Field, group::Group, G1Projective}; | ||
use crate_crypto_kzg_single_open::compute_proof; | ||
use criterion::{criterion_group, criterion_main, Criterion}; | ||
use kzg_multi_open::commit_key::CommitKey; | ||
use polynomial::domain::Domain; | ||
|
||
pub fn bench_single_opening_proof(c: &mut Criterion) { | ||
const NUM_G1_ELEMENTS: usize = 4096; | ||
|
||
let polynomial_4096: Vec<_> = (0..4096) | ||
.into_iter() | ||
.map(|i| -Scalar::from(i as u64)) | ||
.collect(); | ||
let G1s: Vec<_> = (0..NUM_G1_ELEMENTS) | ||
.into_iter() | ||
.map(|i| (G1Projective::generator() * (Scalar::from((i + 123456789) as u64))).into()) | ||
.collect(); | ||
let ck = CommitKey::new(G1s); | ||
let rand_point = Scalar::random(&mut rand::thread_rng()); | ||
let domain = Domain::new(4096); | ||
c.bench_function("compute single proof", |b| { | ||
b.iter(|| compute_proof(&ck, &domain, &polynomial_4096, rand_point)) | ||
}); | ||
} | ||
|
||
criterion_group!(benches, bench_single_opening_proof); | ||
criterion_main!(benches); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
use bls12_381::{multi_pairings, G1Point, G2Point, G2Prepared, Scalar}; | ||
use kzg_multi_open::{commit_key::CommitKey, opening_key::OpeningKey}; | ||
use polynomial::{domain::Domain, monomial::PolyCoeff}; | ||
|
||
pub struct Proof { | ||
pub quotient_commitment: bls12_381::G1Point, | ||
pub claimed_evaluation: Scalar, | ||
} | ||
|
||
/// Takes a polynomial in lagrange form in reverse bit order and an input point | ||
/// and computes a proof that the polynomial is correctly evaluated at the input point. | ||
/// | ||
// Note: The total time taken is around 40-50ms on a single thread. 2-3ms of this is | ||
// division, fft and poly_eval. The rest of it is committing. | ||
pub fn compute_proof( | ||
commit_key: &CommitKey, | ||
domain: &Domain, | ||
polynomial_lagrange: &[Scalar], | ||
input_point: Scalar, | ||
) -> Proof { | ||
// Bit reverse the polynomial and interpolate it. | ||
// | ||
// The bit-reversal is an artifact of a feature we want to maintain | ||
// when we use FK20. | ||
let mut poly_lagrange = polynomial_lagrange.to_vec(); | ||
reverse_bit_order(&mut poly_lagrange); | ||
let polynomial_coeff = domain.ifft_scalars(poly_lagrange); | ||
|
||
let quotient_poly = divide_by_linear(&polynomial_coeff, input_point); | ||
let quotient_commitment = commit_key.commit_g1("ient_poly); | ||
let claimed_evaluation = poly_eval(&polynomial_coeff, &input_point); | ||
|
||
Proof { | ||
quotient_commitment: quotient_commitment.into(), | ||
claimed_evaluation, | ||
} | ||
} | ||
|
||
pub(crate) fn reverse_bits(n: usize, bits: u32) -> usize { | ||
let mut n = n; | ||
let mut r = 0; | ||
for _ in 0..bits { | ||
r = (r << 1) | (n & 1); | ||
n >>= 1; | ||
} | ||
r | ||
} | ||
|
||
/// Computes log2 of an integer. | ||
/// | ||
/// Panics if the integer is not a power of two | ||
pub(crate) fn log2(x: u32) -> u32 { | ||
assert!(x > 0 && x.is_power_of_two(), "x must be a power of two."); | ||
x.trailing_zeros() | ||
} | ||
|
||
// Taken and modified from: https://github.com/filecoin-project/ec-gpu/blob/bdde768d0613ae546524c5612e2ad576a646e036/ec-gpu-gen/src/fft_cpu.rs#L10C8-L10C18 | ||
pub fn reverse_bit_order<T>(a: &mut [T]) { | ||
let n = a.len() as u32; | ||
assert!(n.is_power_of_two(), "n must be a power of two"); | ||
let log_n = log2(n); | ||
|
||
for k in 0..n { | ||
let rk = reverse_bits(k as usize, log_n) as u32; | ||
if k < rk { | ||
a.swap(rk as usize, k as usize); | ||
} | ||
} | ||
} | ||
|
||
/// Checks that a polynomial `p` was evaluated at a point `z` and returned the value specified `y`. | ||
/// ie. y = p(z). | ||
pub fn verify( | ||
opening_key: OpeningKey, | ||
input_point: Scalar, | ||
output_point: Scalar, | ||
poly_comm: G1Point, | ||
witness_comm: G1Point, | ||
) -> bool { | ||
let inner_a: G1Point = (poly_comm - (opening_key.g1s[0] * output_point)).into(); | ||
let inner_b: G2Point = (opening_key.g2s[1] - (opening_key.g2s[0] * input_point)).into(); | ||
let prepared_inner_b = G2Prepared::from(-inner_b); | ||
|
||
let g2_gen_affine: G2Point = opening_key.g2s[0].into(); | ||
let prepared_g2_gen = G2Prepared::from(g2_gen_affine); | ||
|
||
multi_pairings(&[ | ||
(&inner_a, &prepared_g2_gen), | ||
(&witness_comm, &prepared_inner_b), | ||
]) | ||
} | ||
|
||
pub fn poly_eval(poly: &PolyCoeff, value: &Scalar) -> Scalar { | ||
let mut result = Scalar::from(0u64); | ||
for coeff in poly.iter().rev() { | ||
result = result * value + coeff; | ||
} | ||
result | ||
} | ||
|
||
/// Division using ruffini's rule | ||
fn divide_by_linear(poly: &[Scalar], z: Scalar) -> Vec<Scalar> { | ||
let mut quotient: Vec<Scalar> = Vec::with_capacity(poly.len()); | ||
let mut k = Scalar::from(0u64); | ||
|
||
for coeff in poly.iter().rev() { | ||
let t = *coeff + k; | ||
quotient.push(t); | ||
k = z * t; | ||
} | ||
|
||
// Pop off the remainder term | ||
quotient.pop(); | ||
|
||
// Reverse the results as monomial form stores coefficients starting with lowest degree | ||
quotient.reverse(); | ||
quotient | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would usually be controlled by the threadpool, but since its not been integrated, I just turn off all threads