From 96a8ef6032e9be81f2d5043172d19dd240003573 Mon Sep 17 00:00:00 2001 From: Daniel Sanchez Date: Tue, 25 Jun 2024 13:16:25 +0200 Subject: [PATCH] Da: fk20 encoder (#664) * Use fft for rs * Specify evaluation domains * Fix domains in verifier, decoder and dispersal * Fix domains in verifier, decoder and dispersal * Fix size in verifier to fit tests --- nomos-da/kzgrs-backend/Cargo.toml | 10 + nomos-da/kzgrs-backend/src/dispersal.rs | 3 +- nomos-da/kzgrs-backend/src/encoder.rs | 222 ++++++++++-------- nomos-da/kzgrs-backend/src/global.rs | 6 +- nomos-da/kzgrs-backend/src/verifier.rs | 57 +++-- nomos-da/kzgrs/src/rs.rs | 24 +- .../verifier/src/backend/kzgrs.rs | 5 +- 7 files changed, 194 insertions(+), 133 deletions(-) diff --git a/nomos-da/kzgrs-backend/Cargo.toml b/nomos-da/kzgrs-backend/Cargo.toml index 6c110e58..85751f29 100644 --- a/nomos-da/kzgrs-backend/Cargo.toml +++ b/nomos-da/kzgrs-backend/Cargo.toml @@ -20,7 +20,17 @@ rand = "0.8.5" once_cell = "1.19" sha3 = "0.10" serde = { version = "1.0", features = ["derive"] } +rayon = { version = "1.10.0", optional = true } [dev-dependencies] rand = "0.8" +ark-bls12-381 = "0.4.0" + +[features] +default = [] +single = [] +parallel = [ + "rayon", + "kzgrs/parallel" +] diff --git a/nomos-da/kzgrs-backend/src/dispersal.rs b/nomos-da/kzgrs-backend/src/dispersal.rs index a87cd694..c3fc117d 100644 --- a/nomos-da/kzgrs-backend/src/dispersal.rs +++ b/nomos-da/kzgrs-backend/src/dispersal.rs @@ -250,6 +250,7 @@ mod tests { verifiers: &[DaVerifier], ) -> Vec { let mut attestations = Vec::new(); + let domain_size = encoded_data.extended_data.0[0].len(); for (i, column) in encoded_data.extended_data.columns().enumerate() { let verifier = &verifiers[i]; let da_blob = DaBlob { @@ -264,7 +265,7 @@ mod tests { .map(|proofs| proofs.get(i).cloned().unwrap()) .collect(), }; - attestations.push(verifier.verify(da_blob).unwrap()); + attestations.push(verifier.verify(da_blob, domain_size).unwrap()); } attestations } diff --git a/nomos-da/kzgrs-backend/src/encoder.rs b/nomos-da/kzgrs-backend/src/encoder.rs index f3cdbe6b..ad895919 100644 --- a/nomos-da/kzgrs-backend/src/encoder.rs +++ b/nomos-da/kzgrs-backend/src/encoder.rs @@ -3,15 +3,17 @@ use std::ops::Div; // crates use ark_ff::{BigInteger, PrimeField}; +use ark_poly::EvaluationDomain; use kzgrs::common::bytes_to_polynomial_unchecked; +use kzgrs::fk20::fk20_batch_generate_elements_proofs; use kzgrs::{ - bytes_to_polynomial, commit_polynomial, encode, generate_element_proof, Commitment, - Evaluations, KzgRsError, Polynomial, Proof, BYTES_PER_FIELD_ELEMENT, + bytes_to_polynomial, commit_polynomial, encode, Commitment, Evaluations, KzgRsError, + Polynomial, PolynomialEvaluationDomain, Proof, BYTES_PER_FIELD_ELEMENT, }; // internal use crate::common::{hash_column_and_commitment, Chunk, ChunksMatrix, Row}; -use crate::global::{DOMAIN, GLOBAL_PARAMETERS}; +use crate::global::GLOBAL_PARAMETERS; #[derive(Copy, Clone)] pub struct DaEncoderParams { @@ -67,6 +69,7 @@ impl DaEncoder { #[allow(clippy::type_complexity)] fn compute_kzg_row_commitments( matrix: &ChunksMatrix, + polynomial_evaluation_domain: PolynomialEvaluationDomain, ) -> Result, KzgRsError> { matrix .rows() @@ -76,7 +79,7 @@ impl DaEncoder { // Also, after rs encoding, we are sure all `Fr` elements already fits within modulus. let (evals, poly) = bytes_to_polynomial_unchecked::( r.as_bytes().as_ref(), - *DOMAIN, + polynomial_evaluation_domain, ); commit_polynomial(&poly, &GLOBAL_PARAMETERS) .map(|commitment| ((evals, poly), commitment)) @@ -84,42 +87,41 @@ impl DaEncoder { .collect() } - fn rs_encode_row(evaluations: &Evaluations, row: &Polynomial) -> Evaluations { - encode(row, evaluations, 2, *DOMAIN) + fn rs_encode_row( + row: &Polynomial, + polynomial_evaluation_domain: PolynomialEvaluationDomain, + ) -> Evaluations { + encode(row, polynomial_evaluation_domain) } - fn rs_encode_rows(rows: &[(Evaluations, Polynomial)]) -> Vec { + fn rs_encode_rows( + rows: &[Polynomial], + polynomial_evaluation_domain: PolynomialEvaluationDomain, + ) -> Vec { rows.iter() - .map(|(eval, poly)| Self::rs_encode_row(eval, poly)) + .map(|poly| Self::rs_encode_row(poly, polynomial_evaluation_domain)) .collect() } - fn compute_rows_proofs( - polynomials: &[Polynomial], - evals: &[Evaluations], - proof_count: usize, - ) -> Result>, KzgRsError> { - polynomials + fn compute_rows_proofs(polynomials: &[Polynomial]) -> Result>, KzgRsError> { + Ok(polynomials .iter() - .zip(evals) - .map(|(poly, eval)| { - (0..proof_count) - .map(|i| generate_element_proof(i, poly, eval, &GLOBAL_PARAMETERS, *DOMAIN)) - .collect() - }) - .collect() + .map(|poly| fk20_batch_generate_elements_proofs(poly, &GLOBAL_PARAMETERS)) + .collect()) } #[allow(clippy::type_complexity)] fn compute_kzg_column_commitments( matrix: &ChunksMatrix, + polynomial_evaluation_domain: PolynomialEvaluationDomain, ) -> Result, KzgRsError> { - Self::compute_kzg_row_commitments(&matrix.transposed()) + Self::compute_kzg_row_commitments(&matrix.transposed(), polynomial_evaluation_domain) } fn compute_aggregated_column_commitment( matrix: &ChunksMatrix, commitments: &[Commitment], + polynomial_evaluation_domain: PolynomialEvaluationDomain, ) -> Result<((Evaluations, Polynomial), Commitment), KzgRsError> { let hashes: Vec = matrix @@ -133,19 +135,16 @@ impl DaEncoder { .collect(); let (evals, poly) = bytes_to_polynomial::< { DaEncoderParams::MAX_BLS12_381_ENCODING_CHUNK_SIZE }, - >(hashes.as_ref(), *DOMAIN)?; + >(hashes.as_ref(), polynomial_evaluation_domain)?; let commitment = commit_polynomial(&poly, &GLOBAL_PARAMETERS)?; Ok(((evals, poly), commitment)) } - fn compute_aggregated_column_proofs( - polynomial: &Polynomial, - evals: &Evaluations, - proof_count: usize, - ) -> Result, KzgRsError> { - (0..proof_count) - .map(|i| generate_element_proof(i, polynomial, evals, &GLOBAL_PARAMETERS, *DOMAIN)) - .collect() + fn compute_aggregated_column_proofs(polynomial: &Polynomial) -> Result, KzgRsError> { + Ok(fk20_batch_generate_elements_proofs( + polynomial, + &GLOBAL_PARAMETERS, + )) } fn evals_to_chunk_matrix(evals: &[Evaluations]) -> ChunksMatrix { @@ -165,29 +164,30 @@ impl DaEncoder { pub fn encode(&self, data: &[u8]) -> Result { let chunked_data = self.chunkify(data); + let row_domain = PolynomialEvaluationDomain::new(self.params.column_count) + .expect("Domain should be able to build"); + let column_domain = PolynomialEvaluationDomain::new(chunked_data.len()) + .expect("Domain should be able to build"); let (row_polynomials, row_commitments): (Vec<_>, Vec<_>) = - Self::compute_kzg_row_commitments(&chunked_data)? + Self::compute_kzg_row_commitments(&chunked_data, row_domain)? .into_iter() .unzip(); - let encoded_evaluations = Self::rs_encode_rows(&row_polynomials); + let (_, row_polynomials): (Vec<_>, Vec<_>) = row_polynomials.into_iter().unzip(); + let encoded_evaluations = Self::rs_encode_rows(&row_polynomials, row_domain); let extended_data = Self::evals_to_chunk_matrix(&encoded_evaluations); - let row_polynomials: Vec<_> = row_polynomials.into_iter().map(|(_, p)| p).collect(); - let rows_proofs = Self::compute_rows_proofs( - &row_polynomials, - &encoded_evaluations, - self.params.column_count, - )?; + let rows_proofs = Self::compute_rows_proofs(&row_polynomials)?; let (_column_polynomials, column_commitments): (Vec<_>, Vec<_>) = - Self::compute_kzg_column_commitments(&extended_data)? + Self::compute_kzg_column_commitments(&extended_data, column_domain)? .into_iter() .unzip(); - let ((aggregated_evals, aggregated_polynomial), aggregated_column_commitment) = - Self::compute_aggregated_column_commitment(&extended_data, &column_commitments)?; - let aggregated_column_proofs = Self::compute_aggregated_column_proofs( - &aggregated_polynomial, - &aggregated_evals, - column_commitments.len(), - )?; + let ((_aggregated_evals, aggregated_polynomial), aggregated_column_commitment) = + Self::compute_aggregated_column_commitment( + &extended_data, + &column_commitments, + row_domain, + )?; + let aggregated_column_proofs = + Self::compute_aggregated_column_proofs(&aggregated_polynomial)?; Ok(EncodedData { data: data.to_vec(), chunked_data, @@ -204,15 +204,20 @@ impl DaEncoder { #[cfg(test)] pub mod test { use crate::encoder::{DaEncoder, DaEncoderParams}; - use crate::global::{DOMAIN, GLOBAL_PARAMETERS}; + use crate::global::GLOBAL_PARAMETERS; use ark_ff::PrimeField; + use ark_poly::{EvaluationDomain, GeneralEvaluationDomain}; use itertools::izip; use kzgrs::common::bytes_to_polynomial_unchecked; - use kzgrs::{decode, verify_element_proof, FieldElement, BYTES_PER_FIELD_ELEMENT}; + use kzgrs::{ + decode, verify_element_proof, FieldElement, PolynomialEvaluationDomain, + BYTES_PER_FIELD_ELEMENT, + }; use rand::RngCore; use std::ops::Div; - pub const PARAMS: DaEncoderParams = DaEncoderParams::default_with(16); + pub const DOMAIN_SIZE: usize = 16; + pub const PARAMS: DaEncoderParams = DaEncoderParams::default_with(DOMAIN_SIZE); pub const ENCODER: DaEncoder = DaEncoder::new(PARAMS); pub fn rand_data(elements_count: usize) -> Vec { @@ -238,8 +243,9 @@ pub mod test { #[test] fn test_compute_row_kzg_commitments() { let data = rand_data(32); + let domain = GeneralEvaluationDomain::new(DOMAIN_SIZE).unwrap(); let matrix = ENCODER.chunkify(data.as_ref()); - let commitments_data = DaEncoder::compute_kzg_row_commitments(&matrix).unwrap(); + let commitments_data = DaEncoder::compute_kzg_row_commitments(&matrix, domain).unwrap(); assert_eq!(commitments_data.len(), matrix.len()); } @@ -247,11 +253,14 @@ pub mod test { fn test_evals_to_chunk_matrix() { let data = rand_data(32); let matrix = ENCODER.chunkify(data.as_ref()); - let (poly_data, _): (Vec<_>, Vec<_>) = DaEncoder::compute_kzg_row_commitments(&matrix) - .unwrap() - .into_iter() - .unzip(); - let extended_rows = DaEncoder::rs_encode_rows(&poly_data); + let domain = PolynomialEvaluationDomain::new(DOMAIN_SIZE).unwrap(); + let (poly_data, _): (Vec<_>, Vec<_>) = + DaEncoder::compute_kzg_row_commitments(&matrix, domain) + .unwrap() + .into_iter() + .unzip(); + let (_, poly_data): (Vec<_>, Vec<_>) = poly_data.into_iter().unzip(); + let extended_rows = DaEncoder::rs_encode_rows(&poly_data, domain); let extended_matrix = DaEncoder::evals_to_chunk_matrix(&extended_rows); for (r1, r2) in izip!(matrix.iter(), extended_matrix.iter()) { for (c1, c2) in izip!(r1.iter(), r2.iter()) { @@ -263,13 +272,15 @@ pub mod test { #[test] fn test_rs_encode_rows() { let data = rand_data(32); + let domain = GeneralEvaluationDomain::new(DOMAIN_SIZE).unwrap(); let matrix = ENCODER.chunkify(data.as_ref()); - let (poly_data, _): (Vec<_>, Vec<_>) = DaEncoder::compute_kzg_row_commitments(&matrix) - .unwrap() - .into_iter() - .unzip(); - let extended_rows = DaEncoder::rs_encode_rows(&poly_data); - let (evals, _): (Vec<_>, Vec<_>) = poly_data.into_iter().unzip(); + let (poly_data, _): (Vec<_>, Vec<_>) = + DaEncoder::compute_kzg_row_commitments(&matrix, domain) + .unwrap() + .into_iter() + .unzip(); + let (evals, polynomials): (Vec<_>, Vec<_>) = poly_data.into_iter().unzip(); + let extended_rows = DaEncoder::rs_encode_rows(&polynomials, domain); // check encoding went well, original evaluation points vs extended ones for (e1, e2) in izip!(evals.iter(), extended_rows.iter()) { for (c1, c2) in izip!(&e1.evals, &e2.evals) { @@ -283,10 +294,10 @@ pub mod test { assert_eq!(c1, c2); } let points: Vec<_> = evals.evals.iter().cloned().map(Some).collect(); - let poly_2 = decode(r1.len(), &points, *DOMAIN); + let poly_2 = decode(r1.len(), &points, domain); let (poly_1, _) = bytes_to_polynomial_unchecked::( r1.as_bytes().as_ref(), - *DOMAIN, + domain, ); assert_eq!(poly_1, poly_2); } @@ -295,28 +306,21 @@ pub mod test { #[test] fn test_compute_row_proofs() { let data = rand_data(32); + let domain = GeneralEvaluationDomain::new(DOMAIN_SIZE).unwrap(); let matrix = ENCODER.chunkify(data.as_ref()); let (poly_data, commitments): (Vec<_>, Vec<_>) = - DaEncoder::compute_kzg_row_commitments(&matrix) + DaEncoder::compute_kzg_row_commitments(&matrix, domain) .unwrap() .into_iter() .unzip(); - let extended_evaluations = DaEncoder::rs_encode_rows(&poly_data); - let (evals, polynomials): (Vec<_>, Vec<_>) = poly_data.into_iter().unzip(); + let (_evals, polynomials): (Vec<_>, Vec<_>) = poly_data.into_iter().unzip(); + let extended_evaluations = DaEncoder::rs_encode_rows(&polynomials, domain); let extended_matrix = DaEncoder::evals_to_chunk_matrix(&extended_evaluations); - let original_proofs = - DaEncoder::compute_rows_proofs(&polynomials, &evals, PARAMS.column_count.div(2)) - .unwrap(); - let extended_proofs = DaEncoder::compute_rows_proofs( - &polynomials, - &extended_evaluations, - PARAMS.column_count, - ) - .unwrap(); + let proofs = DaEncoder::compute_rows_proofs(&polynomials).unwrap(); - let checks = izip!(matrix.iter(), &commitments, &original_proofs); + let checks = izip!(matrix.iter(), &commitments, &proofs); for (row, commitment, proofs) in checks { - assert_eq!(proofs.len(), row.len()); + assert_eq!(proofs.len(), row.len() * 2); for (i, chunk) in row.iter().enumerate() { let element = FieldElement::from_le_bytes_mod_order(chunk.as_bytes().as_ref()); assert!(verify_element_proof( @@ -324,12 +328,12 @@ pub mod test { &element, &commitment, &proofs[i], - *DOMAIN, + domain, &GLOBAL_PARAMETERS )); } } - let checks = izip!(extended_matrix.iter(), &commitments, &extended_proofs); + let checks = izip!(extended_matrix.iter(), &commitments, &proofs); for (row, commitment, proofs) in checks { assert_eq!(proofs.len(), row.len()); for (i, chunk) in row.iter().enumerate() { @@ -339,7 +343,7 @@ pub mod test { &element, &commitment, &proofs[i], - *DOMAIN, + domain, &GLOBAL_PARAMETERS )); } @@ -349,8 +353,9 @@ pub mod test { #[test] fn test_compute_column_kzg_commitments() { let data = rand_data(32); + let domain = GeneralEvaluationDomain::new(DOMAIN_SIZE).unwrap(); let matrix = ENCODER.chunkify(data.as_ref()); - let commitments_data = DaEncoder::compute_kzg_column_commitments(&matrix).unwrap(); + let commitments_data = DaEncoder::compute_kzg_column_commitments(&matrix, domain).unwrap(); assert_eq!(commitments_data.len(), matrix.columns().count()); } @@ -358,25 +363,58 @@ pub mod test { fn test_compute_aggregated_column_kzg_commitment() { let data = rand_data(32); let matrix = ENCODER.chunkify(data.as_ref()); - let (_, commitments): (Vec<_>, Vec<_>) = DaEncoder::compute_kzg_column_commitments(&matrix) - .unwrap() - .into_iter() - .unzip(); - let _ = DaEncoder::compute_aggregated_column_commitment(&matrix, &commitments).unwrap(); + let domain = GeneralEvaluationDomain::new(DOMAIN_SIZE).unwrap(); + let (_, commitments): (Vec<_>, Vec<_>) = + DaEncoder::compute_kzg_column_commitments(&matrix, domain) + .unwrap() + .into_iter() + .unzip(); + let _ = + DaEncoder::compute_aggregated_column_commitment(&matrix, &commitments, domain).unwrap(); } #[test] fn test_compute_aggregated_column_kzg_proofs() { let data = rand_data(32); let matrix = ENCODER.chunkify(data.as_ref()); + let domain = GeneralEvaluationDomain::new(DOMAIN_SIZE).unwrap(); let (_poly_data, commitments): (Vec<_>, Vec<_>) = - DaEncoder::compute_kzg_column_commitments(&matrix) + DaEncoder::compute_kzg_column_commitments(&matrix, domain) .unwrap() .into_iter() .unzip(); - let ((evals, polynomial), _aggregated_commitment) = - DaEncoder::compute_aggregated_column_commitment(&matrix, &commitments).unwrap(); - DaEncoder::compute_aggregated_column_proofs(&polynomial, &evals, commitments.len()) - .unwrap(); + let ((_evals, polynomial), _aggregated_commitment) = + DaEncoder::compute_aggregated_column_commitment(&matrix, &commitments, domain).unwrap(); + DaEncoder::compute_aggregated_column_proofs(&polynomial).unwrap(); + } + + #[test] + fn test_full_encode_flow() { + let data = rand_data(32); + let domain = GeneralEvaluationDomain::new(DOMAIN_SIZE).unwrap(); + let encoding_data = ENCODER.encode(&data).unwrap(); + assert_eq!(encoding_data.data, data); + assert_eq!(encoding_data.row_commitments.len(), 4); + assert_eq!(encoding_data.column_commitments.len(), 16); + assert_eq!(encoding_data.rows_proofs.len(), 4); + assert_eq!(encoding_data.rows_proofs[0].len(), 16); + assert_eq!(encoding_data.aggregated_column_proofs.len(), 16); + for (row, proofs, commitment) in izip!( + encoding_data.extended_data.rows(), + encoding_data.rows_proofs, + encoding_data.row_commitments + ) { + for (chunk_idx, chunk) in row.iter().enumerate() { + let element = FieldElement::from_le_bytes_mod_order(chunk.as_bytes().as_ref()); + assert!(verify_element_proof( + chunk_idx, + &element, + &commitment, + &proofs[chunk_idx], + domain, + &GLOBAL_PARAMETERS + )); + } + } } } diff --git a/nomos-da/kzgrs-backend/src/global.rs b/nomos-da/kzgrs-backend/src/global.rs index a0695fa6..f8b52590 100644 --- a/nomos-da/kzgrs-backend/src/global.rs +++ b/nomos-da/kzgrs-backend/src/global.rs @@ -1,11 +1,7 @@ -use ark_poly::EvaluationDomain; -use kzgrs::{global_parameters_from_randomness, GlobalParameters, PolynomialEvaluationDomain}; +use kzgrs::{global_parameters_from_randomness, GlobalParameters}; use once_cell::sync::Lazy; pub static GLOBAL_PARAMETERS: Lazy = Lazy::new(|| { let mut rng = rand::thread_rng(); global_parameters_from_randomness(&mut rng) }); - -pub static DOMAIN: Lazy = - Lazy::new(|| PolynomialEvaluationDomain::new(8192).unwrap()); diff --git a/nomos-da/kzgrs-backend/src/verifier.rs b/nomos-da/kzgrs-backend/src/verifier.rs index af0469b3..fe6f118c 100644 --- a/nomos-da/kzgrs-backend/src/verifier.rs +++ b/nomos-da/kzgrs-backend/src/verifier.rs @@ -1,12 +1,13 @@ // std +use ark_poly::EvaluationDomain; // crates use blst::min_sig::{PublicKey, SecretKey}; use itertools::{izip, Itertools}; use kzgrs::common::field_element_from_bytes_le; use kzgrs::{ - bytes_to_polynomial, commit_polynomial, verify_element_proof, Commitment, Proof, - BYTES_PER_FIELD_ELEMENT, + bytes_to_polynomial, commit_polynomial, verify_element_proof, Commitment, + PolynomialEvaluationDomain, Proof, BYTES_PER_FIELD_ELEMENT, }; use crate::common::blob::DaBlob; @@ -16,7 +17,7 @@ use crate::common::{ attestation::Attestation, build_attestation_message, hash_column_and_commitment, Chunk, Column, }; use crate::encoder::DaEncoderParams; -use crate::global::{DOMAIN, GLOBAL_PARAMETERS}; +use crate::global::GLOBAL_PARAMETERS; pub struct DaVerifier { // TODO: substitute this for an abstraction to sign things over @@ -43,11 +44,15 @@ impl DaVerifier { aggregated_column_commitment: &Commitment, aggregated_column_proof: &Proof, index: usize, + rows_domain: PolynomialEvaluationDomain, ) -> bool { + let column_domain = + PolynomialEvaluationDomain::new(column.len()).expect("Domain should be able to build"); // 1. compute commitment for column - let Ok((_, polynomial)) = - bytes_to_polynomial::(column.as_bytes().as_slice(), *DOMAIN) - else { + let Ok((_, polynomial)) = bytes_to_polynomial::( + column.as_bytes().as_slice(), + column_domain, + ) else { return false; }; let Ok(computed_column_commitment) = commit_polynomial(&polynomial, &GLOBAL_PARAMETERS) @@ -69,19 +74,25 @@ impl DaVerifier { &element, aggregated_column_commitment, aggregated_column_proof, - *DOMAIN, + rows_domain, &GLOBAL_PARAMETERS, ) } - fn verify_chunk(chunk: &Chunk, commitment: &Commitment, proof: &Proof, index: usize) -> bool { + fn verify_chunk( + chunk: &Chunk, + commitment: &Commitment, + proof: &Proof, + index: usize, + domain: PolynomialEvaluationDomain, + ) -> bool { let element = field_element_from_bytes_le(chunk.as_bytes().as_slice()); verify_element_proof( index, &element, commitment, proof, - *DOMAIN, + domain, &GLOBAL_PARAMETERS, ) } @@ -91,6 +102,7 @@ impl DaVerifier { commitments: &[Commitment], proofs: &[Proof], index: usize, + domain: PolynomialEvaluationDomain, ) -> bool { if ![chunks.len(), commitments.len(), proofs.len()] .iter() @@ -99,7 +111,7 @@ impl DaVerifier { return false; } for (chunk, commitment, proof) in izip!(chunks, commitments, proofs) { - if !DaVerifier::verify_chunk(chunk, commitment, proof, index) { + if !DaVerifier::verify_chunk(chunk, commitment, proof, index, domain) { return false; } } @@ -122,13 +134,16 @@ impl DaVerifier { } } - pub fn verify(&self, blob: DaBlob) -> Option { + pub fn verify(&self, blob: DaBlob, rows_domain_size: usize) -> Option { + let rows_domain = PolynomialEvaluationDomain::new(rows_domain_size) + .expect("Domain should be able to build"); let is_column_verified = DaVerifier::verify_column( &blob.column, &blob.column_commitment, &blob.aggregated_column_commitment, &blob.aggregated_column_proof, self.index, + rows_domain, ); if !is_column_verified { return None; @@ -139,6 +154,7 @@ impl DaVerifier { &blob.rows_commitments, &blob.rows_proofs, self.index, + rows_domain, ); if !are_chunks_verified { return None; @@ -153,8 +169,9 @@ mod test { use crate::common::{hash_column_and_commitment, Chunk, Column}; use crate::encoder::test::{rand_data, ENCODER}; use crate::encoder::DaEncoderParams; - use crate::global::{DOMAIN, GLOBAL_PARAMETERS}; + use crate::global::GLOBAL_PARAMETERS; use crate::verifier::DaVerifier; + use ark_poly::{EvaluationDomain, GeneralEvaluationDomain}; use blst::min_sig::SecretKey; use kzgrs::{ bytes_to_polynomial, commit_polynomial, generate_element_proof, BYTES_PER_FIELD_ELEMENT, @@ -164,8 +181,9 @@ mod test { #[test] fn test_verify_column() { let column: Column = (0..10).map(|i| Chunk(vec![i; 32])).collect(); + let domain = GeneralEvaluationDomain::new(10).unwrap(); let (_, column_poly) = - bytes_to_polynomial::(column.as_bytes().as_slice(), *DOMAIN) + bytes_to_polynomial::(column.as_bytes().as_slice(), domain) .unwrap(); let column_commitment = commit_polynomial(&column_poly, &GLOBAL_PARAMETERS).unwrap(); let (aggregated_evals, aggregated_poly) = bytes_to_polynomial::< @@ -176,7 +194,7 @@ mod test { &column_commitment, ) .as_slice(), - *DOMAIN, + domain, ) .unwrap(); let aggregated_commitment = @@ -186,7 +204,7 @@ mod test { &aggregated_poly, &aggregated_evals, &GLOBAL_PARAMETERS, - *DOMAIN, + domain, ) .unwrap(); assert!(DaVerifier::verify_column( @@ -194,14 +212,16 @@ mod test { &column_commitment, &aggregated_commitment, &column_proof, - 0 + 0, + domain )); } #[test] fn test_verify() { let encoder = &ENCODER; - let data = rand_data(8); + let data = rand_data(32); + let domain_size = 16usize; let mut rng = thread_rng(); let sks: Vec = (0..16) .map(|_| { @@ -217,6 +237,7 @@ mod test { .collect(); let encoded_data = encoder.encode(&data).unwrap(); for (i, column) in encoded_data.extended_data.columns().enumerate() { + println!("{i}"); let verifier = &verifiers[i]; let da_blob = DaBlob { column, @@ -230,7 +251,7 @@ mod test { .map(|proofs| proofs.get(i).cloned().unwrap()) .collect(), }; - assert!(verifier.verify(da_blob).is_some()); + assert!(verifier.verify(da_blob, domain_size).is_some()); } } } diff --git a/nomos-da/kzgrs/src/rs.rs b/nomos-da/kzgrs/src/rs.rs index 68c84184..50036c43 100644 --- a/nomos-da/kzgrs/src/rs.rs +++ b/nomos-da/kzgrs/src/rs.rs @@ -1,9 +1,7 @@ use ark_bls12_381::Fr; use ark_ff::{BigInteger, Field, PrimeField}; use ark_poly::univariate::DensePolynomial; -use ark_poly::{ - DenseUVPolynomial, EvaluationDomain, Evaluations, GeneralEvaluationDomain, Polynomial, -}; +use ark_poly::{DenseUVPolynomial, EvaluationDomain, Evaluations, GeneralEvaluationDomain}; use num_traits::Zero; use std::ops::{Mul, Neg}; @@ -12,17 +10,9 @@ use std::ops::{Mul, Neg}; /// `factor` need to be `>1` pub fn encode( polynomial: &DensePolynomial, - evaluations: &Evaluations, - factor: usize, domain: GeneralEvaluationDomain, ) -> Evaluations { - assert!(factor > 1); - Evaluations::from_vec_and_domain( - (0..evaluations.evals.len() * factor) - .map(|i| polynomial.evaluate(&domain.element(i))) - .collect(), - domain, - ) + Evaluations::from_vec_and_domain(domain.fft(&polynomial.coeffs), domain) } /// Interpolate points into a polynomial, then evaluate the polynomial in the original evaluations @@ -40,8 +30,10 @@ pub fn decode( .unzip(); let coeffs = lagrange_interpolate(&points, &roots_of_unity); Evaluations::from_vec_and_domain( - (0..original_chunks_len) - .map(|i| coeffs.evaluate(&domain.element(i))) + domain + .fft(&coeffs) + .into_iter() + .take(original_chunks_len) .collect(), domain, ) @@ -105,9 +97,9 @@ mod test { let mut rng = thread_rng(); bytes.try_fill(&mut rng).unwrap(); - let (evals, poly) = bytes_to_polynomial::<31>(&bytes, *DOMAIN).unwrap(); + let (_evals, poly) = bytes_to_polynomial::<31>(&bytes, *DOMAIN).unwrap(); - let encoded = encode(&poly, &evals, 2, *DOMAIN); + let encoded = encode(&poly, *DOMAIN); let mut encoded: Vec> = encoded.evals.into_iter().map(Some).collect(); let decoded = decode(10, &encoded, *DOMAIN); diff --git a/nomos-services/data-availability/verifier/src/backend/kzgrs.rs b/nomos-services/data-availability/verifier/src/backend/kzgrs.rs index f8dc8f09..abf9b639 100644 --- a/nomos-services/data-availability/verifier/src/backend/kzgrs.rs +++ b/nomos-services/data-availability/verifier/src/backend/kzgrs.rs @@ -45,7 +45,10 @@ impl DaVerifier for KzgrsDaVerifier { fn verify(&self, blob: &Self::DaBlob) -> Result { let blob = blob.clone(); - match self.verifier.verify(blob) { + // TODO: Prepare the domain depending the size, if fixed, so fixed domain, if not it needs + // to come with some metadata. + let domain_size = 2usize; + match self.verifier.verify(blob, domain_size) { Some(attestation) => Ok(attestation), None => Err(KzgrsDaVerifierError::VerificationError), }