Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ spartan = { path = "crates/spartan" }
transcript = { path = "crates/transcript" }
verifier = { path = "crates/verifier" }
gkr = { path = "crates/gkr"}
post_gkr = { path = "crates/post_gkr" }

aes = "0.9.2"
anyhow = "1.0.93"
Expand Down
4 changes: 2 additions & 2 deletions crates/common/src/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ mod tests {
for (index, element) in packed.iter().enumerate() {
let column = index / groups_per_column;
let i_hi = index % groups_per_column;
let bits = u128::from(element.lo) | (u128::from(element.hi) << 64);
let bits = element.to_u128();
for v in 0..PACKED_BITS {
assert_eq!(
(bits >> v) & 1 == 1,
Expand Down Expand Up @@ -401,7 +401,7 @@ mod tests {
let table = BitTable::new(shape, &packed).unwrap();

for (index, element) in table.column(2).iter().enumerate() {
let bits = u128::from(element.lo) | (u128::from(element.hi) << 64);
let bits = element.to_u128();
for offset in 0..PACKED_BITS {
let row = index * PACKED_BITS + offset;
assert_eq!(table.bit(2, row), (bits >> offset) & 1 == 1, "row {row}");
Expand Down
47 changes: 38 additions & 9 deletions crates/common/src/virtual_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

use field::{F128, Fq};
use num_traits::ConstZero;
#[cfg(feature = "parallel")]
use rayon::prelude::*;

use crate::{
BitZParams, ClaimError, LinearClaim, OpeningQuery, Shape, VirtualParams, VirtualParamsError,
Expand Down Expand Up @@ -47,6 +49,8 @@ pub enum VirtualMapError {
ClaimWeightCountMismatch,
/// The input omits coordinates of `h`, or the output does not have one weight per bit of `f`.
WeightCountMismatch,
/// The map's weights on `f` outnumber the committed bits.
CommittedShapeTooSmall,
}

/// What the protocol asks of `M`.
Expand Down Expand Up @@ -153,8 +157,9 @@ impl<'a, const Q: u128, M: VirtualMap> VirtualStatement<'a, Q, M> {
///
/// Coefficients use `column * row_count + row` order. The map drops weights on
/// virtual padding. The opening subtracts the constant-column weight from the
/// target and zero-pads the remaining weights to the commitment size. A
/// single-column `InnerProduct` holds the dense weights with column weight one.
/// target and zero-pads the remaining weights to the commitment size, refusing
/// more weights than it has. A single-column `InnerProduct` holds the dense
/// weights with column weight one.
pub fn transpose_query(&self, query: OpeningQuery) -> Result<OpeningQuery, VirtualMapError> {
let shape = self.params.claim().shape();
let (weights, target) = match query {
Expand All @@ -170,12 +175,10 @@ impl<'a, const Q: u128, M: VirtualMap> VirtualStatement<'a, Q, M> {
{
return Err(VirtualMapError::ClaimWeightCountMismatch);
}
let weights = claim
.column_weights()
.iter()
.flat_map(|column| claim.row_weights().iter().map(move |row| *row * *column))
.collect();
(weights, claim.target())
(
flatten(claim.row_weights(), claim.column_weights()),
claim.target(),
)
}
};
let transposed = self.map.transpose(&weights)?;
Expand All @@ -185,7 +188,11 @@ impl<'a, const Q: u128, M: VirtualMap> VirtualStatement<'a, Q, M> {
}
let target = transposed.adjusted_target(target);
let mut weights = transposed.into_weights();
weights.resize(1 << self.params.committed_shape().log_bits(), F128::ZERO);
let committed_bits = 1 << self.params.committed_shape().log_bits();
if weights.len() > committed_bits {
return Err(VirtualMapError::CommittedShapeTooSmall);
}
weights.resize(committed_bits, F128::ZERO);
let shape = Shape::new(self.params.committed_shape().log_bits(), 0)
.expect("a valid committed bit count permits a single-column shape");
let claim = LinearClaim::from_shape(&shape, weights, vec![F128::from(1u64)], target)
Expand All @@ -194,6 +201,28 @@ impl<'a, const Q: u128, M: VirtualMap> VirtualStatement<'a, Q, M> {
}
}

/// `row_weights (x) column_weights` written out per bit of `h`, one column
/// after another.
fn flatten(row_weights: &[F128], column_weights: &[F128]) -> Vec<F128> {
let mut weights = vec![F128::ZERO; row_weights.len() * column_weights.len()];
let process_column = |(slot, &scale): (&mut [F128], &F128)| {
for (weight, &row) in slot.iter_mut().zip(row_weights) {
*weight = scale * row;
}
};
#[cfg(feature = "parallel")]
weights
.par_chunks_mut(row_weights.len())
.zip(column_weights)
.for_each(process_column);
#[cfg(not(feature = "parallel"))]
weights
.chunks_mut(row_weights.len())
.zip(column_weights)
.for_each(process_column);
weights
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
9 changes: 3 additions & 6 deletions crates/field/benches/binius64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ fn operands(count: usize, seed: u64) -> Vec<F128> {
}

fn to_binius(a: F128) -> Ghash {
Ghash::from((a.hi as u128) << 64 | a.lo as u128)
Ghash::from(a.to_u128())
}

fn from_binius(a: Ghash) -> F128 {
Expand Down Expand Up @@ -117,7 +117,7 @@ fn check_agreement(xs: &[F128], ys: &[F128]) {
);
// The timed exponents are the operands read as integers, so raising the
// generator to `x` here is the same call the `pow` row makes.
let e = (x.hi as u128) << 64 | x.lo as u128;
let e = x.to_u128();
assert_eq!(
F128::GENERATOR.pow(e),
from_binius(to_binius(F128::GENERATOR).pow([e as u64, (e >> 64) as u64])),
Expand Down Expand Up @@ -342,10 +342,7 @@ fn main() {

// Full-width exponents, square-and-multiply on both sides. This crate's
// fixed-base comb has no counterpart in binius64, so it is left out.
let exps: Vec<u128> = xs
.iter()
.map(|x| (x.hi as u128) << 64 | x.lo as u128)
.collect();
let exps: Vec<u128> = xs.iter().map(|x| x.to_u128()).collect();
let bgen = to_binius(F128::GENERATOR);
c.run(
"pow/square-and-multiply",
Expand Down
10 changes: 2 additions & 8 deletions crates/field/benches/gf128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,7 @@ fn inverse(bencher: Bencher) {
/// Full-width exponents: what the fold values are.
#[divan::bench]
fn pow_square_and_multiply(bencher: Bencher) {
let exps: Vec<u128> = xs()
.iter()
.map(|x| (x.hi as u128) << 64 | x.lo as u128)
.collect();
let exps: Vec<u128> = xs().iter().map(|x| x.to_u128()).collect();
bencher.counter(ItemsCount::new(N)).bench_local(|| {
for &e in &exps {
black_box(F128::GENERATOR.pow(e));
Expand All @@ -127,10 +124,7 @@ fn pow_square_and_multiply(bencher: Bencher) {
#[divan::bench]
fn pow_comb_w8(bencher: Bencher) {
let comb = FixedBasePow::new(F128::GENERATOR, 8);
let exps: Vec<u128> = xs()
.iter()
.map(|x| (x.hi as u128) << 64 | x.lo as u128)
.collect();
let exps: Vec<u128> = xs().iter().map(|x| x.to_u128()).collect();
bencher.counter(ItemsCount::new(N)).bench_local(|| {
for &e in &exps {
black_box(comb.pow(e));
Expand Down
5 changes: 5 additions & 0 deletions crates/field/src/gf128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ impl F128 {
const fn words(self) -> [u64; 2] {
[self.lo, self.hi]
}

/// `lo || hi` as one `u128`.
pub const fn to_u128(&self) -> u128 {
self.lo as u128 | ((self.hi as u128) << 64)
}
}

/// The bit pattern as 32 hex digits, `hi` first — how the polynomial reads on
Expand Down
3 changes: 2 additions & 1 deletion crates/pcs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ license.workspace = true

[dependencies]
bincode = { workspace = true }
blake3 = { workspace = true }
blake3 = { workspace = true, features = ["rayon"] }
common = { workspace = true }
field = { workspace = true, features = ["spongefish"] }
flock-core = { workspace = true }
post_gkr = { workspace = true }
transcript = { workspace = true }
tracing = { workspace = true }
num-traits = { workspace = true }
Expand Down
9 changes: 4 additions & 5 deletions crates/pcs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
//! Ring-switching transposes `(s_v)` into `(s_u)` and samples `batching_point`.
//! It sets `packed_target = Σ_u eq(batching_point, u) · s_u`.
//! Recursive Ligerito proves `Σ_y B(y) · q_pkd(y) = packed_target` against the committed root.
//! Quadratic sumcheck reduces factored inner-product claims to MLE claims before this opening protocol.
//! The post-GKR sumcheck (`post_gkr`) reduces factored inner-product claims to MLE claims before this opening protocol.
//!
//! # Interface
//!
Expand Down Expand Up @@ -95,7 +95,6 @@ mod ligerito;
mod mle;
mod opening;
mod profiles;
mod sumcheck;
mod transpose;

#[cfg(test)]
Expand Down Expand Up @@ -130,7 +129,7 @@ pub enum StatementBinding {
/// `q̂(r) = Σ_{b ∈ {0,1}^m} q(b) · eq(b, r) = target`, where
/// `eq(b, r) = ∏_i (b_i · r_i + (1 - b_i) · (1 - r_i))`.
/// [`OpeningQuery::InnerProduct`] accepts row weights, column weights, and a target over `F128`.
/// Quadratic sumcheck reduces this claim to an MLE claim before the opening protocol.
/// The post-GKR sumcheck reduces this claim to an MLE claim before the opening protocol.
pub trait CommitScheme {
/// The public commitment.
type Commitment;
Expand All @@ -147,7 +146,7 @@ pub trait CommitScheme {

/// Consumes the exact packed witness and proves either opening query.
///
/// Inner-product claims first pass through quadratic sumcheck and then the MLE opening protocol.
/// Inner-product claims first pass through the post-GKR sumcheck and then the MLE opening protocol.
fn prove_lin(
&self,
data: &Self::ProverData,
Expand All @@ -159,7 +158,7 @@ pub trait CommitScheme {

/// Verifies either opening query against `commitment`.
///
/// Inner-product claims first pass through quadratic sumcheck and then the MLE opening protocol.
/// Inner-product claims first pass through the post-GKR sumcheck and then the MLE opening protocol.
fn verify_lin(
&self,
commitment: &Self::Commitment,
Expand Down
Loading
Loading