diff --git a/da/kzg_rs.py b/da/kzg_rs.py index b9d6d61..04fc193 100644 --- a/da/kzg_rs.py +++ b/da/kzg_rs.py @@ -4,26 +4,32 @@ from typing import List, Sequence import eth2spec.eip7594.mainnet from eth2spec.eip7594.mainnet import ( bit_reversal_permutation, KZG_SETUP_G1_LAGRANGE, Polynomial, - BYTES_PER_FIELD_ELEMENT, bytes_to_bls_field, BLSFieldElement, compute_kzg_proof_impl, KZG_ENDIANNESS, - BLS_MODULUS, compute_roots_of_unity, compute_quotient_eval_within_domain, - div, bls_modular_inverse, + BYTES_PER_FIELD_ELEMENT, bytes_to_bls_field, BLSFieldElement, compute_kzg_proof_impl, + compute_roots_of_unity, verify_kzg_proof_impl ) from eth2spec.eip7594.mainnet import KZGCommitment as Commitment, KZGProof as Proof +from eth2spec.eip7594.minimal import evaluate_polynomial_in_evaluation_form from eth2spec.utils import bls from remerkleable.basic import uint64 from contextlib import contextmanager +from da.common import Chunk + + @contextmanager def setup_field_elements(new_value: int): """ Override ethspecs setup to fit the variable sizes for our scheme """ field_elements_old_value = eth2spec.eip7594.mainnet.FIELD_ELEMENTS_PER_BLOB + minimal_field_elements_old_value = eth2spec.eip7594.minimal.FIELD_ELEMENTS_PER_BLOB eth2spec.eip7594.mainnet.FIELD_ELEMENTS_PER_BLOB = new_value + eth2spec.eip7594.minimal.FIELD_ELEMENTS_PER_BLOB = new_value setup_old_value = eth2spec.eip7594.mainnet.KZG_SETUP_G1_LAGRANGE eth2spec.eip7594.mainnet.KZG_SETUP_G1_LAGRANGE = eth2spec.eip7594.mainnet.KZG_SETUP_G1_LAGRANGE[:new_value] yield eth2spec.eip7594.mainnet.FIELD_ELEMENTS_PER_BLOB = field_elements_old_value + eth2spec.eip7594.minimal.FIELD_ELEMENTS_PER_BLOB = minimal_field_elements_old_value eth2spec.eip7594.mainnet.KZG_SETUP_G1_LAGRANGE = setup_old_value class Polynomial(List[BLSFieldElement]): @@ -77,3 +83,19 @@ def compute_kzg_proofs(b: bytearray) -> List[Proof]: for i in range(len(b)//BYTES_PER_FIELD_ELEMENT) ] + +def __verify_single_proof(polynomial: Polynomial, proof: Proof, commitment: Commitment, index: int, roots_of_unity: Sequence[BLSFieldElement]) -> bool: + challenge = roots_of_unity[index] + with setup_field_elements(len(polynomial)): + y = evaluate_polynomial_in_evaluation_form(polynomial, challenge) + return verify_kzg_proof_impl(commitment, challenge, y, proof) + + +def verify_proofs(b: bytearray, commitment: Commitment, proofs: Sequence[Proof]) -> bool: + polynomial = bytes_to_polynomial(b) + roots_of_unity_brp = bit_reversal_permutation(compute_roots_of_unity(uint64(len(polynomial)))) + return all( + __verify_single_proof(polynomial, proof, commitment, i, roots_of_unity_brp) + for i, proof in enumerate(proofs) + ) + diff --git a/da/test_kzg_rs.py b/da/test_kzg_rs.py index 326ea97..edf976c 100644 --- a/da/test_kzg_rs.py +++ b/da/test_kzg_rs.py @@ -1,10 +1,21 @@ from itertools import chain from random import randrange from unittest import TestCase -from da.kzg_rs import Polynomial, bytes_to_polynomial, bytes_to_kzg_commitment, compute_kzg_proofs, setup_field_elements +from da.kzg_rs import ( + Polynomial, + bytes_to_polynomial, + bytes_to_kzg_commitment, + compute_kzg_proofs, + verify_proofs +) from eth2spec.eip7594.mainnet import ( - Polynomial as EthPolynomial, blob_to_polynomial, BLS_MODULUS, - BYTES_PER_FIELD_ELEMENT, FIELD_ELEMENTS_PER_BLOB, Blob, blob_to_kzg_commitment + Polynomial as EthPolynomial, + blob_to_polynomial, + BLS_MODULUS, + BYTES_PER_FIELD_ELEMENT, + FIELD_ELEMENTS_PER_BLOB, + Blob, + blob_to_kzg_commitment ) @@ -36,6 +47,7 @@ class TestKzgRs(TestCase): commitment = bytes_to_kzg_commitment(rand_bytes) rand_bytes = self.rand_bytes() commitment2 = bytes_to_kzg_commitment(rand_bytes) + self.assertEqual(len(commitment), 48) self.assertEqual(len(commitment), len(commitment2)) def test_compute_kzg_proofs(self): @@ -43,3 +55,10 @@ class TestKzgRs(TestCase): rand_bytes = self.rand_bytes(chunk_size) proofs = compute_kzg_proofs(rand_bytes) self.assertEqual(len(proofs), chunk_size) + + def test_verify_kzg_proofs(self): + chunk_size = 32 + rand_bytes = self.rand_bytes(chunk_size) + commitment = bytes_to_kzg_commitment(rand_bytes) + proofs = compute_kzg_proofs(rand_bytes) + self.assertTrue(verify_proofs(rand_bytes, commitment, proofs)) \ No newline at end of file