Use chunks for verification

This commit is contained in:
Daniel Sanchez Quiros 2024-03-06 16:02:48 +01:00
parent 0f27a16468
commit eecda172b8
5 changed files with 46 additions and 35 deletions

View File

@ -1,4 +1,5 @@
from dataclasses import dataclass
from itertools import chain
from typing import List, Generator
from eth2spec.eip7594.mainnet import Bytes32
@ -16,7 +17,8 @@ class Column(List[Bytes32]):
class Row(List[Bytes32]):
pass
def as_bytes(self) -> bytes:
return bytes(chain.from_iterable(self))
class ChunksMatrix(List[Row]):

View File

@ -3,7 +3,7 @@ from itertools import batched, chain
from typing import List, Sequence, Tuple
from eth2spec.eip7594.mainnet import KZGCommitment as Commitment, KZGProof as Proof, BLSFieldElement
from da.common import ChunksMatrix, Chunk
from da.common import ChunksMatrix, Chunk, Row
from da.kzg_rs import kzg, rs, poly
from da.kzg_rs.common import GLOBAL_PARAMETERS, ROOTS_OF_UNITY
from da.kzg_rs.poly import Polynomial
@ -32,22 +32,23 @@ class DAEncoder:
def _chunkify_data(self, data: bytes) -> ChunksMatrix:
size: int = self.params.column_count * self.params.bytes_per_field_element
return ChunksMatrix(bytes(b) for b in batched(data, size))
return ChunksMatrix(
Row([bytes(chunk) for chunk in batched(b, self.params.bytes_per_field_element)])
for b in batched(data, size)
)
@staticmethod
def _compute_row_kzg_commitments(rows: Sequence[bytes]) -> List[Tuple[Polynomial, Commitment]]:
return [kzg.bytes_to_commitment(row, GLOBAL_PARAMETERS) for row in rows]
def _compute_row_kzg_commitments(rows: Sequence[Row]) -> List[Tuple[Polynomial, Commitment]]:
return [kzg.bytes_to_commitment(row.as_bytes(), GLOBAL_PARAMETERS) for row in rows]
def _rs_encode_rows(self, chunks_matrix: ChunksMatrix) -> ChunksMatrix:
def __rs_encode_row(row: bytes) -> bytes:
polynomial = kzg.bytes_to_polynomial(row)
return bytes(
chain.from_iterable(
Chunk(BLSFieldElement.to_bytes(
x,
length=self.params.bytes_per_field_element, byteorder="big"
)) for x in rs.encode(polynomial, 2, ROOTS_OF_UNITY)
)
def __rs_encode_row(row: Row) -> Row:
polynomial = kzg.bytes_to_polynomial(row.as_bytes())
return Row(
Chunk(BLSFieldElement.to_bytes(
x,
length=self.params.bytes_per_field_element, byteorder="big"
)) for x in rs.encode(polynomial, 2, ROOTS_OF_UNITY)
)
return ChunksMatrix(__rs_encode_row(row) for row in chunks_matrix)
@ -61,7 +62,7 @@ class DAEncoder:
proofs.append(
[
kzg.generate_element_proof(i, poly, GLOBAL_PARAMETERS, ROOTS_OF_UNITY)
for i in range(len(row)//self.params.bytes_per_field_element)
for i in range(len(row))
]
)
return proofs

View File

@ -54,14 +54,14 @@ def generate_element_proof(
def verify_element_proof(
polynomial: Polynomial,
chunk: BLSFieldElement,
commitment: Commitment,
proof: Proof,
element_index: int,
roots_of_unity: Sequence[BLSFieldElement],
) -> bool:
u = int(roots_of_unity[element_index])
v = polynomial.eval(u)
v = chunk
commitment_check_G1 = bls.bytes48_to_G1(commitment) - bls.multiply(bls.G1(), v)
proof_check_g2 = bls.add(
GLOBAL_PARAMETERS_G2[1],

View File

@ -2,7 +2,7 @@ from itertools import chain, batched
from random import randrange
from unittest import TestCase
from eth2spec.deneb.mainnet import BLS_MODULUS, bytes_to_bls_field
from eth2spec.deneb.mainnet import BLS_MODULUS, bytes_to_bls_field, BLSFieldElement
from da.kzg_rs import kzg
from da.kzg_rs.common import BYTES_PER_FIELD_ELEMENT, GLOBAL_PARAMETERS, ROOTS_OF_UNITY, GLOBAL_PARAMETERS_G2
@ -12,11 +12,11 @@ from da.kzg_rs.trusted_setup import verify_setup
class TestKZG(TestCase):
@staticmethod
def rand_bytes(size=1024):
return bytearray(
def rand_bytes(n_chunks=1024):
return bytes(
chain.from_iterable(
int.to_bytes(randrange(BLS_MODULUS), length=BYTES_PER_FIELD_ELEMENT)
for _ in range(size)
for _ in range(n_chunks)
)
)
@ -24,11 +24,15 @@ class TestKZG(TestCase):
self.assertTrue(verify_setup((GLOBAL_PARAMETERS, GLOBAL_PARAMETERS_G2)))
def test_poly_forms(self):
rand_bytes = self.rand_bytes(8)
n_chunks = 16
rand_bytes = self.rand_bytes(n_chunks)
eval_form = [int(bytes_to_bls_field(b)) for b in batched(rand_bytes, int(BYTES_PER_FIELD_ELEMENT))]
poly = kzg.bytes_to_polynomial(rand_bytes)
self.assertEqual(poly.evaluation_form(), eval_form)
self.assertEqual(poly.evaluation_form()[0], poly.eval(int(ROOTS_OF_UNITY[0])))
for i, chunk in enumerate(eval_form):
self.assertEqual(poly.eval(ROOTS_OF_UNITY[i]), chunk)
for i in range(n_chunks):
self.assertEqual(poly.evaluation_form()[i], poly.eval(int(ROOTS_OF_UNITY[i])))
def test_commitment(self):
rand_bytes = self.rand_bytes(32)
@ -46,16 +50,18 @@ class TestKZG(TestCase):
rand_bytes = self.rand_bytes(n_chunks)
_, commit = kzg.bytes_to_commitment(rand_bytes, GLOBAL_PARAMETERS)
poly = kzg.bytes_to_polynomial(rand_bytes)
for n in range(n_chunks):
proof = kzg.generate_element_proof(n, poly, GLOBAL_PARAMETERS, ROOTS_OF_UNITY)
for i, chunk in enumerate(batched(rand_bytes, BYTES_PER_FIELD_ELEMENT)):
chunk = bytes(chunk)
proof = kzg.generate_element_proof(i, poly, GLOBAL_PARAMETERS, ROOTS_OF_UNITY)
self.assertEqual(len(proof), 48)
self.assertEqual(poly.eval(int(ROOTS_OF_UNITY[i])), bytes_to_bls_field(chunk))
self.assertTrue(kzg.verify_element_proof(
poly, commit, proof, n, ROOTS_OF_UNITY
bytes_to_bls_field(chunk), commit, proof, i, ROOTS_OF_UNITY
)
)
proof = kzg.generate_element_proof(0, poly, GLOBAL_PARAMETERS, ROOTS_OF_UNITY)
for n in range(1, n_chunks):
self.assertFalse(kzg.verify_element_proof(
poly, commit, proof, n, ROOTS_OF_UNITY
BLSFieldElement(0), commit, proof, n, ROOTS_OF_UNITY
)
)

View File

@ -37,8 +37,9 @@ class TestEncoder(TestCase):
_encoder = encoder.DAEncoder(encoder_settings)
chunks_matrix = _encoder._chunkify_data(data)
self.assertEqual(len(chunks_matrix), elements//encoder_settings.column_count)
for column in chunks_matrix:
self.assertEqual(len(column), encoder_settings.bytes_per_field_element*encoder_settings.column_count)
for row in chunks_matrix:
self.assertEqual(len(row), encoder_settings.column_count)
self.assertEqual(len(row[0]), encoder_settings.bytes_per_field_element)
def test_compute_row_kzg_commitments(self):
chunks_matrix = self.encoder._chunkify_data(self.data)
@ -50,8 +51,8 @@ class TestEncoder(TestCase):
extended_chunks_matrix = self.encoder._rs_encode_rows(chunks_matrix)
for r1, r2 in zip(chunks_matrix, extended_chunks_matrix):
self.assertEqual(len(r1), len(r2)//2)
r2 = [BLSFieldElement.from_bytes(x) for x in batched(r2, self.params.bytes_per_field_element)]
poly_1 = kzg.bytes_to_polynomial(r1)
r2 = [BLSFieldElement.from_bytes(x) for x in r2]
poly_1 = kzg.bytes_to_polynomial(r1.as_bytes())
# we check against decoding so we now the encoding was properly done
poly_2 = rs.decode(r2, ROOTS_OF_UNITY, len(poly_1))
self.assertEqual(poly_1, poly_2)
@ -64,12 +65,13 @@ class TestEncoder(TestCase):
extended_proofs = self.encoder._compute_rows_proofs(extended_chunks_matrix, polynomials, commitments)
# check original sized matrix
for row, poly, commitment, proofs in zip(chunks_matrix, polynomials, commitments, original_proofs):
for i in range(len(proofs)):
self.assertTrue(kzg.verify_element_proof(poly, commitment, proofs[i], i, ROOTS_OF_UNITY))
self.assertEqual(len(proofs), len(row))
for i, chunk in enumerate(row):
self.assertTrue(kzg.verify_element_proof(BLSFieldElement.from_bytes(chunk), commitment, proofs[i], i, ROOTS_OF_UNITY))
# check extended matrix
for row, poly, commitment, proofs in zip(extended_chunks_matrix, polynomials, commitments, extended_proofs):
for i in range(len(proofs)):
self.assertTrue(kzg.verify_element_proof(poly, commitment, proofs[i], i, ROOTS_OF_UNITY))
for i, chunk in enumerate(row):
self.assertTrue(kzg.verify_element_proof(BLSFieldElement.from_bytes(chunk), commitment, proofs[i], i, ROOTS_OF_UNITY))
def test_compute_column_kzg_commitments(self):
pass