Skip to content

Commit

Permalink
feat: add branch node creation (with proofs)
Browse files Browse the repository at this point in the history
  • Loading branch information
morph-dev committed Jul 28, 2024
1 parent 322caf1 commit a932fc3
Show file tree
Hide file tree
Showing 18 changed files with 371 additions and 103 deletions.
13 changes: 5 additions & 8 deletions portal-verkle-primitives/src/ec/crs.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
use std::array;

use banderwagon::msm::MSMPrecompWnaf;
use once_cell::sync::Lazy;
use sha2::{Digest, Sha256};

use crate::{constants::VERKLE_NODE_WIDTH, Point, ScalarField};
use crate::{constants::VERKLE_NODE_WIDTH, utils::array_long_const, Point, ScalarField};

const PEDERSEN_SEED: &[u8] = b"eth_verkle_oct_2021";

Expand All @@ -23,7 +21,7 @@ static INSTANCE: Lazy<CRS> = Lazy::new(CRS::new);
impl CRS {
fn new() -> Self {
let mut generated_elements = 0;
let mut elements: [Point; VERKLE_NODE_WIDTH] = array::from_fn(|_| Point::zero());
let mut elements = array_long_const(Point::zero());

for i in 0u64.. {
if generated_elements == elements.len() {
Expand Down Expand Up @@ -73,7 +71,7 @@ impl CRS {
}

/// Single scalar multiplication.
pub fn commit_single(index: u8, scalar: ScalarField) -> Point {
pub fn commit_single(index: u8, scalar: &ScalarField) -> Point {
if scalar.is_zero() {
Point::zero()
} else {
Expand All @@ -89,16 +87,15 @@ impl CRS {
pub fn commit_sparse(scalars: &[(u8, ScalarField)]) -> Point {
// TODO: consider if 64 is good value
if scalars.len() >= 64 {
let mut dense: [ScalarField; VERKLE_NODE_WIDTH] =
array::from_fn(|_| ScalarField::zero());
let mut dense = array_long_const(ScalarField::zero());
for (index, value) in scalars {
dense[*index as usize] = value.clone();
}
Self::commit(&dense)
} else {
scalars
.iter()
.map(|(index, value)| Self::commit_single(*index, value.clone()))
.map(|(index, value)| Self::commit_single(*index, value))
.sum()
}
}
Expand Down
1 change: 1 addition & 0 deletions portal-verkle-primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ pub mod ssz;
mod stem;
mod trie_key;
mod trie_value;
pub(crate) mod utils;
pub mod verkle;
2 changes: 1 addition & 1 deletion portal-verkle-primitives/src/portal/branch_fragment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ impl BranchFragmentNode {
.map(|(child_index, child)| {
let index =
child_index as u8 + self.fragment_index * PORTAL_NETWORK_NODE_WIDTH as u8;
CRS::commit_single(index, child.map_to_scalar_field())
CRS::commit_single(index, &child.map_to_scalar_field())
})
.sum()
})
Expand Down
9 changes: 6 additions & 3 deletions portal-verkle-primitives/src/proof/ipa.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{array, iter};
use std::iter;

use itertools::{chain, zip_eq};
use serde::{Deserialize, Serialize};
Expand All @@ -9,6 +9,7 @@ use crate::{
constants::{VERKLE_NODE_WIDTH, VERKLE_NODE_WIDTH_BITS},
ec::CRS,
proof::precomputed_weights::PrecomputedWeights,
utils::array_long_const,
BatchInversion, DotProduct, Point, ScalarField,
};

Expand Down Expand Up @@ -157,7 +158,7 @@ impl IpaProof {
// They are calculated by aggregating 1/x_i (x_agg_i) in a smart way.
// We also multiply them with -a' to avoid that step in the future, as it is needed for
// multiplication with both G and b.
let mut g_coeff: [ScalarField; VERKLE_NODE_WIDTH] = array::from_fn(|_| -a_prime);
let mut g_coeff: [ScalarField; VERKLE_NODE_WIDTH] = array_long_const(-a_prime);
for (i, g_coeff) in g_coeff.iter_mut().enumerate() {
for bit_index in 0..VERKLE_NODE_WIDTH_BITS {
if i & (1 << bit_index) != 0 {
Expand Down Expand Up @@ -187,6 +188,8 @@ impl IpaProof {

#[cfg(test)]
mod tests {
use crate::utils::array_long;

use super::*;

#[test]
Expand All @@ -212,7 +215,7 @@ mod tests {
};
let x = ScalarField::from(1234u64);
let y = eval(&x);
let poly = LagrangeBasis::new(array::from_fn(|i| eval(&ScalarField::from(i))));
let poly = LagrangeBasis::new(array_long(|i| eval(&ScalarField::from(i))));
let c = poly.commit();
let mut transcript = Transcript::new("test");
let proof = IpaProof::open_polynomial(Some(c.clone()), poly, x.clone(), &mut transcript);
Expand Down
14 changes: 9 additions & 5 deletions portal-verkle-primitives/src/proof/lagrange_basis.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
use std::{array, iter::Sum, ops};
use std::{iter::Sum, ops};

use itertools::Itertools;
use overload::overload;

use crate::{constants::VERKLE_NODE_WIDTH, DotProduct, Point, ScalarField, CRS};
use crate::{
constants::VERKLE_NODE_WIDTH,
utils::{array_long, array_long_const},
DotProduct, Point, ScalarField, CRS,
};

use super::precomputed_weights::PrecomputedWeights;

Expand Down Expand Up @@ -40,7 +44,7 @@ impl LagrangeBasis {
}

pub fn new_const(value: &ScalarField) -> Self {
Self::new(array::from_fn(|_| value.clone()))
Self::new(array_long_const(value.clone()))
}

pub fn zero() -> Self {
Expand Down Expand Up @@ -83,7 +87,7 @@ impl LagrangeBasis {
/// ```
pub fn divide_on_domain(&self, k: u8) -> Self {
let k_usize = k as usize;
let mut q = array::from_fn(|_| ScalarField::zero());
let mut q = array_long_const(ScalarField::zero());
for i in 0..VERKLE_NODE_WIDTH {
let i_u8 = i as u8;
// 1/(i-k)
Expand All @@ -109,7 +113,7 @@ impl From<&[ScalarField]> for LagrangeBasis {
fn from(other: &[ScalarField]) -> Self {
assert!(other.len() == VERKLE_NODE_WIDTH);
Self {
y: array::from_fn(|i| other[i].clone()),
y: array_long(|i| other[i as usize].clone()),
}
}
}
Expand Down
18 changes: 8 additions & 10 deletions portal-verkle-primitives/src/proof/multiproof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,34 +179,32 @@ impl MultiProof {

#[cfg(test)]
mod tests {

use std::array;

use alloy_primitives::{hex::FromHex, B256};

use crate::{
constants::{LEAF_MARKER_INDEX, LEAF_STEM_INDEX},
proof::{prover_query::ProverQuery, VerifierQuery},
utils::array_long,
Stem,
};

use super::*;

type PolynomialFn = Box<dyn Fn(usize) -> ScalarField>;
type PolynomialFn = Box<dyn Fn(u8) -> ScalarField>;

#[test]
fn simple_multi_opening() {
// p(x) = 42
let f_const = |_: usize| ScalarField::from(42u64);
let f_const = |_: u8| ScalarField::from(42u64);
// p(x) = (x + 1)(x + 10)(x - 100)
let f_poly = |x: usize| {
let f_poly = |x: u8| {
let x = ScalarField::from(x);
(&x + ScalarField::from(1u64))
* (&x + ScalarField::from(10u64))
* (&x - ScalarField::from(100u64))
};
// p(x) = (x + 2) / (x + 1) (on domain)
let f_non_poly = |x: usize| {
let f_non_poly = |x: u8| {
let x = ScalarField::from(x);
(&x + ScalarField::from(2u64)) * (&x + ScalarField::from(1u64)).inverse().unwrap()
};
Expand All @@ -222,7 +220,7 @@ mod tests {
let queries = openings
.iter()
.map(|(poly_f, z)| {
let poly = LagrangeBasis::new(array::from_fn(poly_f));
let poly = LagrangeBasis::new(array_long(poly_f));
ProverQuery {
poly,
commitment: None,
Expand All @@ -236,9 +234,9 @@ mod tests {
let queries = openings
.iter()
.map(|(poly_f, z)| VerifierQuery {
commitment: LagrangeBasis::new(array::from_fn(poly_f)).commit(),
commitment: LagrangeBasis::new(array_long(poly_f)).commit(),
z: *z,
y: poly_f(*z as usize),
y: poly_f(*z),
})
.collect();
assert!(proof.verify(queries, &mut transcript));
Expand Down
13 changes: 5 additions & 8 deletions portal-verkle-primitives/src/proof/precomputed_weights.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use std::array;

use once_cell::sync::Lazy;

use crate::{constants::VERKLE_NODE_WIDTH, BatchInversion, ScalarField};
use crate::{constants::VERKLE_NODE_WIDTH, utils::array_long, BatchInversion, ScalarField};

/// Precomputed weights for Lagrange polynomial (`L_i`) related calculations.
///
Expand Down Expand Up @@ -46,18 +44,18 @@ static INSTANCE: Lazy<PrecomputedWeights> = Lazy::new(PrecomputedWeights::new);

impl PrecomputedWeights {
fn new() -> Self {
let a_prime = array::from_fn(|i| {
let a_prime = array_long(|i| {
// ∏ (i-j)
// j≠i
(0..VERKLE_NODE_WIDTH)
.filter(|j| i != *j)
.filter(|j| i != *j as u8)
.map(|j| ScalarField::from(i) - ScalarField::from(j))
.product()
});

let a_prime_inv = a_prime.clone().batch_inverse();

let domain_inv = array::from_fn(ScalarField::from).batch_inverse();
let domain_inv = array_long(ScalarField::from).batch_inverse();

Self {
a_prime,
Expand Down Expand Up @@ -102,8 +100,7 @@ impl PrecomputedWeights {
let a_z = Self::evaluate_a(z);

// A'(i) * (z-i)
let lagrange_evaluations: [ScalarField; VERKLE_NODE_WIDTH] =
array::from_fn(|i| (z - ScalarField::from(i)) * Self::a_prime(i as u8));
let lagrange_evaluations = array_long(|i| (z - ScalarField::from(i)) * Self::a_prime(i));

// A(z) / (A'(i) * (z-i))
lagrange_evaluations.batch_inverse_and_mul(&a_z)
Expand Down
29 changes: 28 additions & 1 deletion portal-verkle-primitives/src/proof/prover_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::Point;

use super::lagrange_basis::LagrangeBasis;

#[derive(Clone)]
pub struct ProverQuery {
/// The polynomial we are commiting to.
pub poly: LagrangeBasis,
Expand All @@ -13,13 +14,39 @@ pub struct ProverQuery {
pub z: u8,
}

#[derive(Default, Deref, DerefMut, IntoIterator)]
#[derive(Default, Clone, Deref, DerefMut, IntoIterator)]
pub struct ProverMultiQuery(Vec<ProverQuery>);

impl ProverMultiQuery {
pub fn new() -> Self {
Self::default()
}

pub fn add_trie_path_proof(
&mut self,
trie_path_iter: impl IntoIterator<Item = (Point, LagrangeBasis, u8)>,
) {
for (commitment, poly, child_index) in trie_path_iter {
self.push(ProverQuery {
poly,
commitment: Some(commitment),
z: child_index,
})
}
}

pub fn add_vector(
&mut self,
commitment: Point,
poly: LagrangeBasis,
openings: impl IntoIterator<Item = u8>,
) {
self.extend(openings.into_iter().map(|child_index| ProverQuery {
poly: poly.clone(),
commitment: Some(commitment.clone()),
z: child_index,
}));
}
}

impl FromIterator<ProverQuery> for ProverMultiQuery {
Expand Down
10 changes: 10 additions & 0 deletions portal-verkle-primitives/src/ssz/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,13 @@ impl TriePathWithCommitments {
self.first().map(|(commitment, _)| commitment)
}
}

impl TryFrom<Vec<(Point, u8)>> for TriePathWithCommitments {
type Error = String;

fn try_from(value: Vec<(Point, u8)>) -> Result<Self, Self::Error> {
VariableList::new(value)
.map(Self)
.map_err(|_| "Provided vector is too long".to_string())
}
}
17 changes: 17 additions & 0 deletions portal-verkle-primitives/src/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use std::array;

use crate::constants::{PORTAL_NETWORK_NODE_WIDTH, VERKLE_NODE_WIDTH};

/// Creates the array that has [VERKLE_NODE_WIDTH] length.
pub fn array_long<T>(f: impl Fn(u8) -> T) -> [T; VERKLE_NODE_WIDTH] {
array::from_fn(|index| f(index as u8))
}

pub fn array_long_const<T: Clone>(value: T) -> [T; VERKLE_NODE_WIDTH] {
array_long(|_| value.clone())
}

/// Creates the array that has [PORTAL_NETWORK_NODE_WIDTH] length.
pub fn array_short<T>(f: impl Fn(u8) -> T) -> [T; PORTAL_NETWORK_NODE_WIDTH] {
array::from_fn(|index| f(index as u8))
}
2 changes: 1 addition & 1 deletion portal-verkle-primitives/src/verkle/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@ pub struct AuxiliaryTrieModifications {

#[derive(Clone)]
pub struct PathToLeaf<'a> {
pub branches: Vec<&'a BranchNode>,
pub branches: Vec<(&'a BranchNode, u8)>,
pub leaf: &'a LeafNode,
}
Loading

0 comments on commit a932fc3

Please sign in to comment.