Skip to content

Commit

Permalink
feat: add leaf node creation (with proofs)
Browse files Browse the repository at this point in the history
  • Loading branch information
morph-dev committed Jul 30, 2024
1 parent a932fc3 commit 65ce730
Show file tree
Hide file tree
Showing 18 changed files with 590 additions and 182 deletions.
5 changes: 3 additions & 2 deletions portal-verkle-primitives/src/ec/point.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::{fmt::Debug, iter::Sum, ops};
use alloy_primitives::B256;
use banderwagon::{CanonicalDeserialize, CanonicalSerialize, Element};
use derive_more::Constructor;
use itertools::Itertools;
use overload::overload;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use ssz::{Decode, Encode};
Expand Down Expand Up @@ -41,8 +42,8 @@ impl Point {
points: impl IntoIterator<Item = &'a Self>,
scalars: impl IntoIterator<Item = &'b ScalarField>,
) -> Self {
let points = points.into_iter().map(|p| p.inner()).collect::<Vec<_>>();
let scalars = scalars.into_iter().map(|s| s.inner()).collect::<Vec<_>>();
let points = points.into_iter().map(|p| p.inner()).collect_vec();
let scalars = scalars.into_iter().map(|s| s.inner()).collect_vec();
Self(banderwagon::multi_scalar_mul(&points, &scalars))
}
}
Expand Down
6 changes: 3 additions & 3 deletions portal-verkle-primitives/src/ec/scalar_field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use alloy_primitives::B256;
use ark_ff::batch_inversion_and_mul;
use banderwagon::{CanonicalDeserialize, CanonicalSerialize, Field, Fr, One, PrimeField, Zero};
use derive_more::Constructor;
use itertools::zip_eq;
use itertools::{zip_eq, Itertools};
use overload::overload;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use ssz::{Decode, Encode};
Expand Down Expand Up @@ -226,7 +226,7 @@ where
.as_mut()
.iter()
.map(|value| value.inner())
.collect::<Vec<_>>();
.collect_vec();
batch_inversion_and_mul(&mut values, &coeff.inner());
for (original, inverted) in zip_eq(self.as_mut(), values) {
original.0 = inverted;
Expand Down Expand Up @@ -274,7 +274,7 @@ mod tests {
&m * v.inverse().unwrap()
}
})
.collect::<Vec<_>>();
.collect_vec();
let inverted = values.batch_inverse_and_mul(&m);

assert_eq!(inverted, expected);
Expand Down
9 changes: 5 additions & 4 deletions portal-verkle-primitives/src/portal/branch_bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ use alloy_primitives::B256;
use ssz_derive::{Decode, Encode};

use crate::{
constants::{PORTAL_NETWORK_NODE_WIDTH, VERKLE_NODE_WIDTH},
constants::PORTAL_NETWORK_NODE_WIDTH,
proof::{BundleProof, MultiProof, VerifierMultiQuery},
ssz::{SparseVector, TriePathWithCommitments},
utils::branch_utils,
Point, ScalarField,
};

Expand Down Expand Up @@ -86,9 +87,9 @@ impl BranchBundleNode {
for (fragment_index, fragment_commitment) in self.fragments.iter_enumerated_set_items() {
multiquery.add_for_commitment(
fragment_commitment,
(0..VERKLE_NODE_WIDTH)
.filter(|child_index| child_index / PORTAL_NETWORK_NODE_WIDTH != fragment_index)
.map(|child_index| (child_index as u8, ScalarField::zero())),
branch_utils::openings_for_bundle(fragment_index as u8)
.into_iter()
.map(|index| (index, ScalarField::zero())),
);
}
if self.bundle_proof.verify_portal_network_proof(multiquery) {
Expand Down
32 changes: 15 additions & 17 deletions portal-verkle-primitives/src/portal/branch_fragment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::{
constants::PORTAL_NETWORK_NODE_WIDTH,
proof::{MultiProof, VerifierMultiQuery},
ssz::{SparseVector, TriePathWithCommitments},
utils::{array_short, branch_utils},
Point, ScalarField, CRS,
};

Expand Down Expand Up @@ -45,19 +46,15 @@ impl BranchFragmentNodeWithProof {
// 3.2. Verify children openings to bundle commitment
multi_query.add_for_commitment(
&self.bundle_commitment,
self.node
.children
.iter()
.enumerate()
.map(|(child_index, child)| {
(
child_index as u8,
child
.as_ref()
.map(Point::map_to_scalar_field)
.unwrap_or_else(ScalarField::zero),
)
}),
array_short(|fragment_child_index| {
(
branch_utils::child_index(self.node.fragment_index, fragment_child_index),
self.node.children[fragment_child_index as usize]
.as_ref()
.map(Point::map_to_scalar_field)
.unwrap_or_else(ScalarField::zero),
)
}),
);

if self.multiproof.verify_portal_network_proof(multi_query) {
Expand Down Expand Up @@ -100,10 +97,11 @@ impl BranchFragmentNode {
self.commitment.get_or_init(|| {
self.children
.iter_enumerated_set_items()
.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())
.map(|(fragment_child_index, child)| {
CRS::commit_single(
branch_utils::child_index(self.fragment_index, fragment_child_index as u8),
&child.map_to_scalar_field(),
)
})
.sum()
})
Expand Down
33 changes: 9 additions & 24 deletions portal-verkle-primitives/src/portal/leaf_bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ use ssz_derive::{Decode, Encode};

use crate::{
constants::{
LEAF_C1_INDEX, LEAF_C2_INDEX, LEAF_MARKER_INDEX, LEAF_STEM_INDEX,
PORTAL_NETWORK_NODE_WIDTH, VERKLE_NODE_WIDTH,
LEAF_C1_INDEX, LEAF_C2_INDEX, LEAF_MARKER_INDEX, LEAF_STEM_INDEX, PORTAL_NETWORK_NODE_WIDTH,
},
proof::{BundleProof, MultiProof, VerifierMultiQuery},
ssz::{SparseVector, TriePathCommitments},
utils::leaf_utils,
Point, ScalarField, Stem, CRS,
};

Expand Down Expand Up @@ -95,7 +95,7 @@ impl LeafBundleNode {

pub fn commitment(&self) -> &Point {
self.commitment.get_or_init(|| {
let (c1, c2) = self.c1_c2();
let [c1, c2] = self.c1_c2();
CRS::commit_sparse(&[
(LEAF_MARKER_INDEX, ScalarField::from(self.marker)),
(LEAF_STEM_INDEX, ScalarField::from(&self.stem)),
Expand All @@ -105,35 +105,20 @@ impl LeafBundleNode {
})
}

pub fn c1_c2(&self) -> (Point, Point) {
pub fn c1_c2(&self) -> [Point; 2] {
let (first_half, second_half) = self.fragments.split_at(PORTAL_NETWORK_NODE_WIDTH / 2);
let sum_of_optional_points = |fragments: &[Option<Point>]| {
fragments
.iter()
.flat_map(|fragment| fragment.as_ref())
.sum::<Point>()
};
let c1 = sum_of_optional_points(first_half);
let c2 = sum_of_optional_points(second_half);
(c1, c2)
[first_half, second_half]
.map(|fragments| fragments.iter().filter_map(Option::as_ref).sum::<Point>())
}

pub fn verify_bundle_proof(&self) -> Result<(), NodeVerificationError> {
let mut multiquery = VerifierMultiQuery::new();
for (fragment_index, fragment_commitment) in self.fragments.iter_enumerated_set_items() {
multiquery.add_for_commitment(
fragment_commitment,
(0..VERKLE_NODE_WIDTH)
.filter(|child_index| child_index / PORTAL_NETWORK_NODE_WIDTH != fragment_index)
.flat_map(|child_index| {
let suffix_child_index = (child_index % (VERKLE_NODE_WIDTH / 2)) as u8;
let low_index = suffix_child_index * 2;
let high_index = low_index + 1;
[
(low_index, ScalarField::zero()),
(high_index, ScalarField::zero()),
]
}),
leaf_utils::suffix_openings_for_bundle(fragment_index as u8)
.into_iter()
.map(|index| (index, ScalarField::zero())),
);
}
if self.bundle_proof.verify_portal_network_proof(multiquery) {
Expand Down
45 changes: 14 additions & 31 deletions portal-verkle-primitives/src/portal/leaf_fragment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@ use alloy_primitives::B256;
use ssz_derive::{Decode, Encode};

use crate::{
constants::{
LEAF_C1_INDEX, LEAF_C2_INDEX, LEAF_MARKER_INDEX, LEAF_STEM_INDEX, PORTAL_NETWORK_NODE_WIDTH,
},
constants::{LEAF_MARKER_INDEX, LEAF_STEM_INDEX, PORTAL_NETWORK_NODE_WIDTH},
proof::{MultiProof, VerifierMultiQuery},
ssz::{SparseVector, TriePathCommitments},
utils::{array_short, leaf_utils},
Point, Stem, TrieValue, TrieValueSplit, CRS,
};

Expand Down Expand Up @@ -52,20 +51,14 @@ impl LeafFragmentNodeWithProof {
multi_query
.add_trie_path_proof(self.trie_path.zip_with_stem(stem), &self.bundle_commitment);

// 3.2 Verify [marker, stem, c1 or c2] openings to bundle commitment
let suffix_commitment_index =
if (self.node.fragment_index as usize) < PORTAL_NETWORK_NODE_WIDTH / 2 {
LEAF_C1_INDEX
} else {
LEAF_C2_INDEX
};
// 3.2 Verify [marker, stem, c1 /c2] openings to bundle commitment
multi_query.add_for_commitment(
&self.bundle_commitment,
[
(LEAF_MARKER_INDEX, self.marker.into()),
(LEAF_STEM_INDEX, stem.into()),
(
suffix_commitment_index,
leaf_utils::leaf_suffix_index(self.node.fragment_index),
self.suffix_commitment.map_to_scalar_field(),
),
],
Expand All @@ -74,15 +67,14 @@ impl LeafFragmentNodeWithProof {
// 3.3 Verify children openings to suffix commitment (c1 or c2)
multi_query.add_for_commitment(
&self.suffix_commitment,
self.node
.children
.iter()
.enumerate()
.flat_map(|(child_index, child)| {
let (low_index, high_index) = self.node.bases_indices(child_index as u8);
let (low_value, high_value) = child.split();
[(low_index, low_value), (high_index, high_value)]
}),
array_short(|child_index| {
let [low_index, high_index] =
leaf_utils::suffix_indices(self.node.fragment_index, child_index);
let (low_value, high_value) = self.node.children[child_index as usize].split();
[(low_index, low_value), (high_index, high_value)]
})
.into_iter()
.flatten(),
);

if self.multiproof.verify_portal_network_proof(multi_query) {
Expand Down Expand Up @@ -126,7 +118,8 @@ impl LeafFragmentNode {
self.children
.iter_enumerated_set_items()
.map(|(child_index, child)| {
let (low_index, high_index) = self.bases_indices(child_index as u8);
let [low_index, high_index] =
leaf_utils::suffix_indices(self.fragment_index, child_index as u8);
let (low_value, high_value) = child.split();
CRS::commit_sparse(&[(low_index, low_value), (high_index, high_value)])
})
Expand All @@ -151,14 +144,4 @@ impl LeafFragmentNode {
}
Ok(())
}

/// Returns the bases indices that correspond to the child index.
fn bases_indices(&self, child_index: u8) -> (u8, u8) {
let suffix_fragment_index = self.fragment_index % (PORTAL_NETWORK_NODE_WIDTH / 2) as u8;
let suffix_child_index =
child_index + suffix_fragment_index * PORTAL_NETWORK_NODE_WIDTH as u8;
let low_index = 2 * suffix_child_index;
let high_index = low_index + 1;
(low_index, high_index)
}
}
4 changes: 2 additions & 2 deletions portal-verkle-primitives/src/proof/ipa.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::iter;

use itertools::{chain, zip_eq};
use itertools::{chain, zip_eq, Itertools};
use serde::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode};
use ssz_types::{typenum, FixedVector};
Expand Down Expand Up @@ -151,7 +151,7 @@ impl IpaProof {
transcript.append_point("R", c_r);
transcript.challenge_scalar("x")
})
.collect::<Vec<_>>();
.collect_vec();
let x_inv = x.clone().batch_inverse();

// 3. Compute scalars that we will use to multiply G_i: g_coeff
Expand Down
6 changes: 3 additions & 3 deletions portal-verkle-primitives/src/proof/multiproof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ impl MultiProof {
let inverse_denominators = agg_polynomials
.keys()
.map(|z| &t - ScalarField::from(*z))
.collect::<Vec<_>>()
.collect_vec()
.batch_inverse();

// h(x)
Expand Down Expand Up @@ -148,13 +148,13 @@ impl MultiProof {
let inverse_denominators = multiquery
.iter()
.map(|query| &t - ScalarField::from(query.z))
.collect::<Vec<_>>()
.collect_vec()
.batch_inverse();

// coeff_i
let coefficients = zip_eq(powers_of_r, inverse_denominators)
.map(|(power_of_r, inverse_denominator)| power_of_r * inverse_denominator)
.collect::<Vec<_>>();
.collect_vec();

// 4. Compute E (commitment to h(x): E = [h(x)])
// E = ∑ r^i * C_i / (t - z_i) = ∑ coeff_i * C_i
Expand Down
Loading

0 comments on commit 65ce730

Please sign in to comment.