From f735f514e60cf102f40db34664b2f8287eabe9c2 Mon Sep 17 00:00:00 2001 From: mgonen Date: Wed, 4 Jun 2025 13:58:18 +0300 Subject: [PATCH] Changes were done based on the feedback --- da/encoder.py | 12 ++++++------ da/kzg_rs/poly.py | 21 +++++++-------------- da/test_encoder.py | 29 ++++++++++++++++------------- da/test_verifier.py | 6 +++--- da/verifier.py | 28 +++++++++++++++------------- 5 files changed, 47 insertions(+), 49 deletions(-) diff --git a/da/encoder.py b/da/encoder.py index 2b9668f..8e57aab 100644 --- a/da/encoder.py +++ b/da/encoder.py @@ -68,19 +68,19 @@ class DAEncoder: def _combined_polynomial( polys: Sequence[Polynomial], h: BLSFieldElement ) -> Polynomial: - combined = Polynomial([0], BLS_MODULUS) + combined_polynomial = polys[0] h_int = int(h) # raw integer challenge int_pow = 1 - for poly in polys: - combined = combined + (poly * int_pow) + for poly in polys[1:]: int_pow = (int_pow * h_int) % BLS_MODULUS - return combined + combined_polynomial = combined_polynomial + Polynomial({int_pow * coeff for coeff in poly},BLS_MODULUS) + return combined_polynomial def _compute_combined_column_proofs(self, combined_poly: Polynomial) -> List[Proof]: total_cols = self.params.column_count * 2 return [ - kzg.generate_element_proof(j, combined_poly, GLOBAL_PARAMETERS, ROOTS_OF_UNITY) - for j in range(total_cols) + kzg.generate_element_proof(i, combined_poly, GLOBAL_PARAMETERS, ROOTS_OF_UNITY) + for i in range(total_cols) ] def encode(self, data: bytes) -> EncodedData: diff --git a/da/kzg_rs/poly.py b/da/kzg_rs/poly.py index d5a7f47..870ff42 100644 --- a/da/kzg_rs/poly.py +++ b/da/kzg_rs/poly.py @@ -1,3 +1,4 @@ + from itertools import zip_longest from typing import List, Sequence, Self @@ -49,19 +50,11 @@ class Polynomial[T]: ) def __mul__(self, other): - if isinstance(other, int): - return Polynomial( - [(a * other) % self.modulus for a in self.coefficients], - self.modulus - ) - elif isinstance(other, Polynomial): - result = [0] * (len(self.coefficients) + len(other.coefficients) - 1) - for i in range(len(self.coefficients)): - for j in range(len(other.coefficients)): - result[i + j] = (result[i + j] + self.coefficients[i] * other.coefficients[j]) % self.modulus - return Polynomial(result, self.modulus) - else: - raise TypeError(f"Unsupported type for multiplication: {type(other)}") + result = [0] * (len(self.coefficients) + len(other.coefficients) - 1) + for i in range(len(self.coefficients)): + for j in range(len(other.coefficients)): + result[i + j] = (result[i + j] + self.coefficients[i] * other.coefficients[j]) % self.modulus + return Polynomial(result, self.modulus) def divide(self, other): if not isinstance(other, Polynomial): @@ -116,4 +109,4 @@ class Polynomial[T]: )) % self.modulus def evaluation_form(self) -> List[T]: - return [self.eval(ROOTS_OF_UNITY[i]) for i in range(len(self))] \ No newline at end of file + return [self.eval(ROOTS_OF_UNITY[i]) for i in range(len(self))] diff --git a/da/test_encoder.py b/da/test_encoder.py index 37370fc..56eac1a 100644 --- a/da/test_encoder.py +++ b/da/test_encoder.py @@ -39,19 +39,21 @@ class TestEncoder(TestCase): # verify rows h = derive_challenge(encoded_data.row_commitments) - combined_commitment = encoded_data.row_commitments[0] - power = h + combined_commitment = bls.bytes48_to_G1(encoded_data.row_commitments[0]) + power = int(h) % BLS_MODULUS for commitment in encoded_data.row_commitments[1:]: - combined_commitment = bls.add(combined_commitment,bls.multiply(commitment, power)) - power = power * h - + commitment=bls.bytes48_to_G1(commitment) + combined_commitment = bls.add(combined_commitment,bls.multiply(commitment,power)) + power = (power * int(h)) % BLS_MODULUS + combined_commitment = bls.G1_to_bytes48(combined_commitment) for i, (column, proof) in enumerate(zip(encoded_data.extended_matrix.columns, encoded_data.combined_column_proofs)): - combined_eval_point = BLSFieldElement(0) - power = BLSFieldElement(1) - for data in column.chunks: - chunk = BLSFieldElement(int.from_bytes(bytes(data), byteorder="big")) - combined_eval_point = combined_eval_point + chunk * power - power = power * h + combined_eval_int = 0 + power_int = 1 + h_int = int(h) + for data in column: + chunk_int = int.from_bytes(bytes(data), byteorder="big") + combined_eval_point = (combined_eval_int + chunk_int * power_int) % BLS_MODULUS + power_int = (power_int * h_int) % BLS_MODULUS kzg.verify_element_proof( combined_eval_point, combined_commitment, @@ -95,7 +97,8 @@ class TestEncoder(TestCase): h = derive_challenge(row_commitments) combined_poly = self.encoder._combined_polynomial(row_polynomials, h) proofs = self.encoder._compute_combined_column_proofs(combined_poly) - self.assertEqual(len(proofs), len(row_commitments)) + expected_extended_columns = self.params.column_count * 2 + self.assertEqual(len(proofs), expected_extended_columns) def test_encode(self): from random import randbytes @@ -111,4 +114,4 @@ class TestEncoder(TestCase): for _ in range(size*encoder_params.column_count) ) ) - self.assert_encoding(encoder_params, data) + self.assert_encoding(encoder_params, data) \ No newline at end of file diff --git a/da/test_verifier.py b/da/test_verifier.py index 4c2bcc7..6e390f8 100644 --- a/da/test_verifier.py +++ b/da/test_verifier.py @@ -18,7 +18,7 @@ class TestVerifier(TestCase): _ = TestEncoder() _.setUp() encoded_data = _.encoder.encode(_.data) - for i, column in enumerate(encoded_data.chunked_data.columns): + for i, column in enumerate(encoded_data.extended_matrix.columns): verifier = DAVerifier() da_blob = DAShare( Column(column), @@ -32,7 +32,7 @@ class TestVerifier(TestCase): _ = TestEncoder() _.setUp() encoded_data = _.encoder.encode(_.data) - columns = enumerate(encoded_data.chunked_data.columns) + columns = enumerate(encoded_data.extended_matrix.columns) i, column = next(columns) da_blob = DAShare( Column(column), @@ -48,4 +48,4 @@ class TestVerifier(TestCase): encoded_data.combined_column_proofs[i], encoded_data.row_commitments, ) - self.assertTrue(self.verifier.verify(da_blob)) + self.assertIsNotNone(self.verifier.verify(da_blob)) diff --git a/da/verifier.py b/da/verifier.py index 3fefc6a..42d7ce6 100644 --- a/da/verifier.py +++ b/da/verifier.py @@ -1,6 +1,5 @@ from dataclasses import dataclass from typing import List, Sequence, Set -from hashlib import blake2b from eth2spec.utils import bls from eth2spec.deneb.mainnet import BLSFieldElement from eth2spec.eip7594.mainnet import ( @@ -30,26 +29,29 @@ class DAVerifier: @staticmethod def verify(blob: DAShare) -> bool: """ - Verifies that blob.column.chunks at index blob.column_idx is consistent - with the row commitments and the single column proof. + Verifies that blob.column at index blob.column_idx is consistent + with the row commitments and the combined column proof. Returns True if verification succeeds, False otherwise. """ # 1. Derive challenge h = derive_challenge(blob.row_commitments) # 2. Reconstruct combined commitment: combined_commitment = sum_{i=0..l-1} h^i * row_commitments[i] - combined_commitment = blob.row_commitments[0] - power = h + combined_commitment = bls.bytes48_to_G1(blob.row_commitments[0]) + power = int(h) % BLS_MODULUS for commitment in blob.row_commitments[1:]: + commitment = bls.bytes48_to_G1(commitment) combined_commitment = bls.add(combined_commitment,bls.multiply(commitment, power)) - power = power * h - + power = (power * int(h)) % BLS_MODULUS + combined_commitment = bls.G1_to_bytes48(combined_commitment) # 3. Compute combined evaluation v = sum_{i=0..l-1} (h^i * column_data[i]) - combined_eval_point = BLSFieldElement(0) - power = BLSFieldElement(1) - for data in blob.column.chunks: - chunk = BLSFieldElement(int.from_bytes(bytes(data), byteorder="big")) - combined_eval_point = combined_eval_point + chunk * power - power = power * h + combined_eval_int = 0 + power_int = 1 + h_int = int(h) % BLS_MODULUS + for chunk in blob.column: + chunk_int = int.from_bytes(bytes(chunk), byteorder="big") + combined_eval_int = (combined_eval_int + chunk_int * power_int) % BLS_MODULUS + power_int = (power_int * h_int) % BLS_MODULUS + combined_eval_point = BLSFieldElement(combined_eval_int) # 4. Verify the single KZG proof for evaluation at point w^{column_idx} return kzg.verify_element_proof(combined_eval_point,combined_commitment,blob.combined_column_proof,blob.column_idx,ROOTS_OF_UNITY)