From b739ad0f1abbcb038f5a4bf2a5a75b966c64ecfe Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Wed, 17 Jan 2024 09:41:30 -0600 Subject: [PATCH 01/14] Optimize `verify_kzg_proof_multi_impl` --- .../polynomial-commitments-sampling.md | 50 +++++++++++++++---- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/specs/_features/eip7594/polynomial-commitments-sampling.md b/specs/_features/eip7594/polynomial-commitments-sampling.md index b356792e34..9ab191aee5 100644 --- a/specs/_features/eip7594/polynomial-commitments-sampling.md +++ b/specs/_features/eip7594/polynomial-commitments-sampling.md @@ -304,20 +304,30 @@ def compute_kzg_proof_multi_impl( ```python def verify_kzg_proof_multi_impl(commitment: KZGCommitment, - zs: Sequence[BLSFieldElement], + x: BLSFieldElement, ys: Sequence[BLSFieldElement], proof: KZGProof) -> bool: """ Helper function that verifies a KZG multiproof """ + assert len(ys) == FIELD_ELEMENTS_PER_CELL + roots_of_unity = compute_roots_of_unity(FIELD_ELEMENTS_PER_CELL) + interp = fft_field(ys, roots_of_unity, inv=True) - assert len(zs) == len(ys) + inv_x = bls_modular_inverse(x) + inv_x_pow = inv_x + for i in range(1, FIELD_ELEMENTS_PER_CELL): + interp[i] = BLSFieldElement(int(interp[i]) * int(inv_x_pow) % BLS_MODULUS) + inv_x_pow = BLSFieldElement(int(inv_x_pow) * int(inv_x) % BLS_MODULUS) - zero_poly = g2_lincomb(KZG_SETUP_G2_MONOMIAL[:len(zs) + 1], vanishing_polynomialcoeff(zs)) - interpolated_poly = g1_lincomb(KZG_SETUP_G1_MONOMIAL[:len(zs)], interpolate_polynomialcoeff(zs, ys)) + x_pow = bls_modular_inverse(inv_x_pow) + xn2 = bls.multiply(bls.G2(), x_pow) + xn_minus_yn = bls.add(bls.bytes96_to_G2(KZG_SETUP_G2_MONOMIAL[FIELD_ELEMENTS_PER_CELL]), bls.neg(xn2)) + + interpolated_poly = g1_lincomb(KZG_SETUP_G1_MONOMIAL[:FIELD_ELEMENTS_PER_CELL], interp) return (bls.pairing_check([ - [bls.bytes48_to_G1(proof), bls.bytes96_to_G2(zero_poly)], + [bls.bytes48_to_G1(proof), xn_minus_yn], [ bls.add(bls.bytes48_to_G1(commitment), bls.neg(bls.bytes48_to_G1(interpolated_poly))), bls.neg(bls.bytes96_to_G2(KZG_SETUP_G2_MONOMIAL[0])), @@ -396,9 +406,23 @@ def compute_cells(blob: Blob) -> Vector[Cell, CELLS_PER_BLOB]: #### `verify_cell_proof` +```python +def reverse_bits_limited(max_value: uint64, value: uint64) -> uint64: + """ + Reverse the low-order bits in an integer. + """ + assert 0 <= value <= max_value + num_bits = max_value.bit_length() + reversed_bits = uint64(0) + for _ in range(num_bits): + reversed_bits = (reversed_bits << 1) | (value & 1) + value = value >> 1 + return reversed_bits +``` + ```python def verify_cell_proof(commitment: KZGCommitment, - cell_id: int, + column_id: int, cell: Cell, proof: KZGProof) -> bool: """ @@ -406,9 +430,10 @@ def verify_cell_proof(commitment: KZGCommitment, Public method. """ - coset = coset_for_cell(cell_id) - - return verify_kzg_proof_multi_impl(commitment, coset, cell, proof) + roots_of_unity = compute_roots_of_unity(2 * FIELD_ELEMENTS_PER_BLOB) + x = roots_of_unity[reverse_bits_limited(CELLS_PER_BLOB-1, column_id)] + ys = bit_reversal_permutation(cell) + return verify_kzg_proof_multi_impl(commitment, x, ys, proof) ``` #### `verify_cell_proof_batch` @@ -430,12 +455,17 @@ def verify_cell_proof_batch(row_commitments: Sequence[KZGCommitment], Public method. """ + roots_of_unity = compute_roots_of_unity(2 * FIELD_ELEMENTS_PER_BLOB) # Get commitments via row IDs commitments = [row_commitments[row_id] for row_id in row_ids] return all( - verify_kzg_proof_multi_impl(commitment, coset_for_cell(column_id), cell, proof) + verify_kzg_proof_multi_impl( + commitment, + roots_of_unity[reverse_bits_limited(CELLS_PER_BLOB-1, column_id)], + bit_reversal_permutation(cell), + proof) for commitment, column_id, cell, proof in zip(commitments, column_ids, cells, proofs) ) ``` From 9e90e04266638819f1fd585bdf91302bf28fb87e Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Wed, 17 Jan 2024 09:55:13 -0600 Subject: [PATCH 02/14] Fix lint errors --- specs/_features/eip7594/polynomial-commitments-sampling.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/_features/eip7594/polynomial-commitments-sampling.md b/specs/_features/eip7594/polynomial-commitments-sampling.md index 9ab191aee5..2d86559764 100644 --- a/specs/_features/eip7594/polynomial-commitments-sampling.md +++ b/specs/_features/eip7594/polynomial-commitments-sampling.md @@ -431,7 +431,7 @@ def verify_cell_proof(commitment: KZGCommitment, Public method. """ roots_of_unity = compute_roots_of_unity(2 * FIELD_ELEMENTS_PER_BLOB) - x = roots_of_unity[reverse_bits_limited(CELLS_PER_BLOB-1, column_id)] + x = roots_of_unity[reverse_bits_limited(CELLS_PER_BLOB - 1, column_id)] ys = bit_reversal_permutation(cell) return verify_kzg_proof_multi_impl(commitment, x, ys, proof) ``` @@ -463,7 +463,7 @@ def verify_cell_proof_batch(row_commitments: Sequence[KZGCommitment], return all( verify_kzg_proof_multi_impl( commitment, - roots_of_unity[reverse_bits_limited(CELLS_PER_BLOB-1, column_id)], + roots_of_unity[reverse_bits_limited(CELLS_PER_BLOB - 1, column_id)], bit_reversal_permutation(cell), proof) for commitment, column_id, cell, proof in zip(commitments, column_ids, cells, proofs) From 1f58d9521441a921478ca326d89ae0e0a4d45c7d Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Wed, 17 Jan 2024 10:01:51 -0600 Subject: [PATCH 03/14] Move `reverse_bits_limited` to better spot --- .../polynomial-commitments-sampling.md | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/specs/_features/eip7594/polynomial-commitments-sampling.md b/specs/_features/eip7594/polynomial-commitments-sampling.md index 2d86559764..302443a155 100644 --- a/specs/_features/eip7594/polynomial-commitments-sampling.md +++ b/specs/_features/eip7594/polynomial-commitments-sampling.md @@ -351,6 +351,22 @@ def coset_for_cell(cell_id: int) -> Cell: return Cell(roots_of_unity_brp[FIELD_ELEMENTS_PER_CELL * cell_id:FIELD_ELEMENTS_PER_CELL * (cell_id + 1)]) ``` +#### `reverse_bits_limited` + +```python +def reverse_bits_limited(max_value: uint64, value: uint64) -> uint64: + """ + Reverse the low-order bits in an integer. + """ + assert 0 <= value <= max_value + num_bits = max_value.bit_length() + reversed_bits = uint64(0) + for _ in range(num_bits): + reversed_bits = (reversed_bits << 1) | (value & 1) + value = value >> 1 + return reversed_bits +``` + ## Cells ### Cell computation @@ -406,20 +422,6 @@ def compute_cells(blob: Blob) -> Vector[Cell, CELLS_PER_BLOB]: #### `verify_cell_proof` -```python -def reverse_bits_limited(max_value: uint64, value: uint64) -> uint64: - """ - Reverse the low-order bits in an integer. - """ - assert 0 <= value <= max_value - num_bits = max_value.bit_length() - reversed_bits = uint64(0) - for _ in range(num_bits): - reversed_bits = (reversed_bits << 1) | (value & 1) - value = value >> 1 - return reversed_bits -``` - ```python def verify_cell_proof(commitment: KZGCommitment, column_id: int, From 213c6318bcb0ccdd3e3656641f0fdc86d94b8410 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Wed, 17 Jan 2024 10:17:27 -0600 Subject: [PATCH 04/14] Fix table of contents --- specs/_features/eip7594/polynomial-commitments-sampling.md | 1 + 1 file changed, 1 insertion(+) diff --git a/specs/_features/eip7594/polynomial-commitments-sampling.md b/specs/_features/eip7594/polynomial-commitments-sampling.md index 302443a155..8ca137d6d2 100644 --- a/specs/_features/eip7594/polynomial-commitments-sampling.md +++ b/specs/_features/eip7594/polynomial-commitments-sampling.md @@ -32,6 +32,7 @@ - [`verify_kzg_proof_multi_impl`](#verify_kzg_proof_multi_impl) - [Cell cosets](#cell-cosets) - [`coset_for_cell`](#coset_for_cell) + - [`reverse_bits_limited`](#reverse_bits_limited) - [Cells](#cells-1) - [Cell computation](#cell-computation) - [`compute_cells_and_proofs`](#compute_cells_and_proofs) From a0799844c1fc7cd65c94827126eca847481bd4f4 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Wed, 17 Jan 2024 11:24:57 -0600 Subject: [PATCH 05/14] Update test to verify all cells --- .../polynomial_commitments/test_polynomial_commitments.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/eip7594/unittests/polynomial_commitments/test_polynomial_commitments.py b/tests/core/pyspec/eth2spec/test/eip7594/unittests/polynomial_commitments/test_polynomial_commitments.py index d3e848772a..e9e9eb60eb 100644 --- a/tests/core/pyspec/eth2spec/test/eip7594/unittests/polynomial_commitments/test_polynomial_commitments.py +++ b/tests/core/pyspec/eth2spec/test/eip7594/unittests/polynomial_commitments/test_polynomial_commitments.py @@ -34,10 +34,8 @@ def test_verify_cell_proof(spec): blob = get_sample_blob(spec) commitment = spec.blob_to_kzg_commitment(blob) cells, proofs = spec.compute_cells_and_proofs(blob) - cell_id = 0 - assert spec.verify_cell_proof(commitment, cell_id, cells[cell_id], proofs[cell_id]) - cell_id = 1 - assert spec.verify_cell_proof(commitment, cell_id, cells[cell_id], proofs[cell_id]) + for cell_id in range(spec.CELLS_PER_BLOB): + assert spec.verify_cell_proof(commitment, cell_id, cells[cell_id], proofs[cell_id]) @with_eip7594_and_later From a0892031b6d3b5dc9986e549203eccd342a7f02c Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Fri, 22 Mar 2024 13:32:21 -0500 Subject: [PATCH 06/14] Improve reverse_bits_limited --- .../eip7594/polynomial-commitments-sampling.md | 12 +++++++----- .../test_polynomial_commitments.py | 9 +++++++++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/specs/_features/eip7594/polynomial-commitments-sampling.md b/specs/_features/eip7594/polynomial-commitments-sampling.md index 8ca137d6d2..6f727f19e7 100644 --- a/specs/_features/eip7594/polynomial-commitments-sampling.md +++ b/specs/_features/eip7594/polynomial-commitments-sampling.md @@ -343,7 +343,7 @@ def verify_kzg_proof_multi_impl(commitment: KZGCommitment, ```python def coset_for_cell(cell_id: int) -> Cell: """ - Get the coset for a given ``cell_id`` + Get the coset for a given ``cell_id``. """ assert cell_id < CELLS_PER_BLOB roots_of_unity_brp = bit_reversal_permutation( @@ -355,11 +355,13 @@ def coset_for_cell(cell_id: int) -> Cell: #### `reverse_bits_limited` ```python -def reverse_bits_limited(max_value: uint64, value: uint64) -> uint64: +def reverse_bits_limited(length: uint64, value: uint64) -> uint64: """ Reverse the low-order bits in an integer. """ - assert 0 <= value <= max_value + assert value < length + assert is_power_of_two(length) + max_value = length - 1 num_bits = max_value.bit_length() reversed_bits = uint64(0) for _ in range(num_bits): @@ -434,7 +436,7 @@ def verify_cell_proof(commitment: KZGCommitment, Public method. """ roots_of_unity = compute_roots_of_unity(2 * FIELD_ELEMENTS_PER_BLOB) - x = roots_of_unity[reverse_bits_limited(CELLS_PER_BLOB - 1, column_id)] + x = roots_of_unity[reverse_bits_limited(CELLS_PER_BLOB, column_id)] ys = bit_reversal_permutation(cell) return verify_kzg_proof_multi_impl(commitment, x, ys, proof) ``` @@ -466,7 +468,7 @@ def verify_cell_proof_batch(row_commitments: Sequence[KZGCommitment], return all( verify_kzg_proof_multi_impl( commitment, - roots_of_unity[reverse_bits_limited(CELLS_PER_BLOB - 1, column_id)], + roots_of_unity[reverse_bits_limited(CELLS_PER_BLOB, column_id)], bit_reversal_permutation(cell), proof) for commitment, column_id, cell, proof in zip(commitments, column_ids, cells, proofs) diff --git a/tests/core/pyspec/eth2spec/test/eip7594/unittests/polynomial_commitments/test_polynomial_commitments.py b/tests/core/pyspec/eth2spec/test/eip7594/unittests/polynomial_commitments/test_polynomial_commitments.py index e9e9eb60eb..2ae56aed1a 100644 --- a/tests/core/pyspec/eth2spec/test/eip7594/unittests/polynomial_commitments/test_polynomial_commitments.py +++ b/tests/core/pyspec/eth2spec/test/eip7594/unittests/polynomial_commitments/test_polynomial_commitments.py @@ -26,6 +26,15 @@ def test_fft(spec): assert len(poly_eval) == len(poly_coeff) == len(poly_coeff_inversed) assert poly_coeff_inversed == poly_coeff +@with_eip7594_and_later +@spec_test +@single_phase +def test_reverse_bits_limited(spec): + rng = random.Random(5566) + for exp in range(64): + length = 2**exp + value = rng.randrange(0, length) + assert value == spec.reverse_bits_limited(length, spec.reverse_bits_limited(length, value)) @with_eip7594_and_later @spec_test From dc597055e161fc76b47c53c00da2d2ea60a33c40 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Fri, 22 Mar 2024 13:39:53 -0500 Subject: [PATCH 07/14] Fix mistake --- .../polynomial_commitments/test_polynomial_commitments.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/eip7594/unittests/polynomial_commitments/test_polynomial_commitments.py b/tests/core/pyspec/eth2spec/test/eip7594/unittests/polynomial_commitments/test_polynomial_commitments.py index fb103c2403..a4f73de86c 100644 --- a/tests/core/pyspec/eth2spec/test/eip7594/unittests/polynomial_commitments/test_polynomial_commitments.py +++ b/tests/core/pyspec/eth2spec/test/eip7594/unittests/polynomial_commitments/test_polynomial_commitments.py @@ -50,7 +50,7 @@ def test_verify_cell_proof(spec): cells, proofs = spec.compute_cells_and_proofs(blob) cells_bytes = [[field_element_bytes(element) for element in cell] for cell in cells] for cell_id in range(spec.CELLS_PER_BLOB): - assert spec.verify_cell_proof(commitment, cell_id, cell_bytes[cell_id], proofs[cell_id]) + assert spec.verify_cell_proof(commitment, cell_id, cells_bytes[cell_id], proofs[cell_id]) @with_eip7594_and_later From e3b7d7d0f7edba36aaeb9ce1f920f7cbc73ee8c0 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Fri, 22 Mar 2024 13:52:42 -0500 Subject: [PATCH 08/14] Add blank line --- .../polynomial_commitments/test_polynomial_commitments.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/core/pyspec/eth2spec/test/eip7594/unittests/polynomial_commitments/test_polynomial_commitments.py b/tests/core/pyspec/eth2spec/test/eip7594/unittests/polynomial_commitments/test_polynomial_commitments.py index a4f73de86c..cb4babbf41 100644 --- a/tests/core/pyspec/eth2spec/test/eip7594/unittests/polynomial_commitments/test_polynomial_commitments.py +++ b/tests/core/pyspec/eth2spec/test/eip7594/unittests/polynomial_commitments/test_polynomial_commitments.py @@ -31,6 +31,7 @@ def test_fft(spec): assert len(poly_eval) == len(poly_coeff) == len(poly_coeff_inversed) assert poly_coeff_inversed == poly_coeff + @with_eip7594_and_later @spec_test @single_phase From 9fc6a212483d0f7ce277f127ac2c429981c0962c Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Fri, 22 Mar 2024 13:52:55 -0500 Subject: [PATCH 09/14] Add another blank line (ugh) --- .../polynomial_commitments/test_polynomial_commitments.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/core/pyspec/eth2spec/test/eip7594/unittests/polynomial_commitments/test_polynomial_commitments.py b/tests/core/pyspec/eth2spec/test/eip7594/unittests/polynomial_commitments/test_polynomial_commitments.py index cb4babbf41..ce9f7cf2e3 100644 --- a/tests/core/pyspec/eth2spec/test/eip7594/unittests/polynomial_commitments/test_polynomial_commitments.py +++ b/tests/core/pyspec/eth2spec/test/eip7594/unittests/polynomial_commitments/test_polynomial_commitments.py @@ -42,6 +42,7 @@ def test_reverse_bits_limited(spec): value = rng.randrange(0, length) assert value == spec.reverse_bits_limited(length, spec.reverse_bits_limited(length, value)) + @with_eip7594_and_later @spec_test @single_phase From 250d890d0732ba2d8be38f9a4652913a55434c1e Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Fri, 22 Mar 2024 14:47:53 -0500 Subject: [PATCH 10/14] Convert with bytes_to_cell --- specs/_features/eip7594/polynomial-commitments-sampling.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/_features/eip7594/polynomial-commitments-sampling.md b/specs/_features/eip7594/polynomial-commitments-sampling.md index 9a09271c9f..c1241b7051 100644 --- a/specs/_features/eip7594/polynomial-commitments-sampling.md +++ b/specs/_features/eip7594/polynomial-commitments-sampling.md @@ -454,13 +454,13 @@ def verify_cell_proof(commitment_bytes: Bytes48, cell_bytes: Vector[Bytes32, FIELD_ELEMENTS_PER_CELL], proof_bytes: Bytes48) -> bool: """ - Check a cell proof + Check a cell proof. Public method. """ roots_of_unity = compute_roots_of_unity(FIELD_ELEMENTS_PER_EXT_BLOB) x = roots_of_unity[reverse_bits_limited(CELLS_PER_BLOB, cell_id)] - ys = bit_reversal_permutation(cell_bytes) + ys = bit_reversal_permutation(bytes_to_cell(cell_bytes)) return verify_kzg_proof_multi_impl(commitment_bytes, x, ys, proof_bytes) ``` From 6fdfb0837cc83aa0a83cf6a82d55da992d7e7d57 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Mon, 25 Mar 2024 08:07:23 -0500 Subject: [PATCH 11/14] Make new bitwise manipulation section --- specs/_features/eip7594/polynomial-commitments-sampling.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/specs/_features/eip7594/polynomial-commitments-sampling.md b/specs/_features/eip7594/polynomial-commitments-sampling.md index c1241b7051..9cec2cb33c 100644 --- a/specs/_features/eip7594/polynomial-commitments-sampling.md +++ b/specs/_features/eip7594/polynomial-commitments-sampling.md @@ -34,6 +34,7 @@ - [`verify_kzg_proof_multi_impl`](#verify_kzg_proof_multi_impl) - [Cell cosets](#cell-cosets) - [`coset_for_cell`](#coset_for_cell) + - [Bitwise manipulation](#bitwise-manipulation) - [`reverse_bits_limited`](#reverse_bits_limited) - [Cells](#cells-1) - [Cell computation](#cell-computation) @@ -375,6 +376,8 @@ def coset_for_cell(cell_id: CellID) -> Cell: return Cell(roots_of_unity_brp[FIELD_ELEMENTS_PER_CELL * cell_id:FIELD_ELEMENTS_PER_CELL * (cell_id + 1)]) ``` +### Bitwise manipulation + #### `reverse_bits_limited` ```python From 657e101ef89b0e24d8935f5a2334ee32776ecf9b Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Tue, 9 Apr 2024 12:30:48 -0500 Subject: [PATCH 12/14] Fix merge problem --- .../polynomial_commitments/test_polynomial_commitments.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/eip7594/unittests/polynomial_commitments/test_polynomial_commitments.py b/tests/core/pyspec/eth2spec/test/eip7594/unittests/polynomial_commitments/test_polynomial_commitments.py index bf58c49ed9..dc81d5b9d3 100644 --- a/tests/core/pyspec/eth2spec/test/eip7594/unittests/polynomial_commitments/test_polynomial_commitments.py +++ b/tests/core/pyspec/eth2spec/test/eip7594/unittests/polynomial_commitments/test_polynomial_commitments.py @@ -46,7 +46,7 @@ def test_verify_cell_proof(spec): blob = get_sample_blob(spec) commitment = spec.blob_to_kzg_commitment(blob) cells, proofs = spec.compute_cells_and_proofs(blob) - cells_bytes = [[field_element_bytes(element) for element in cell] for cell in cells] + cells_bytes = [[spec.bls_field_to_bytes(element) for element in cell] for cell in cells] for cell_id in range(spec.CELLS_PER_BLOB): assert spec.verify_cell_proof(commitment, cell_id, cells_bytes[cell_id], proofs[cell_id]) From e2bb78a224b0f765ff42b54dfb27a8ce00654411 Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Thu, 18 Apr 2024 16:41:43 +0300 Subject: [PATCH 13/14] Variable renames and documentation in the modified func --- .../polynomial-commitments-sampling.md | 41 ++++++++++++------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/specs/_features/eip7594/polynomial-commitments-sampling.md b/specs/_features/eip7594/polynomial-commitments-sampling.md index d2ea4b182b..6035535922 100644 --- a/specs/_features/eip7594/polynomial-commitments-sampling.md +++ b/specs/_features/eip7594/polynomial-commitments-sampling.md @@ -331,35 +331,46 @@ def compute_kzg_proof_multi_impl( ```python def verify_kzg_proof_multi_impl(commitment: KZGCommitment, - x: BLSFieldElement, + h: BLSFieldElement, ys: Sequence[BLSFieldElement], proof: KZGProof) -> bool: """ - Helper function that verifies a KZG multiproof + Helper function that verifies a KZG multiproof ``proof`` for the polynomial in ``commitment``. + + The evaluation domain of the multiproof is the coset generated by the coset factor ``h``, and the evaluations of + the polynomial are in ``ys``. """ assert len(ys) == FIELD_ELEMENTS_PER_CELL roots_of_unity = compute_roots_of_unity(FIELD_ELEMENTS_PER_CELL) - interp = fft_field(ys, roots_of_unity, inv=True) + # Interpolate the values ys over the roots of unity + interpolation_poly = fft_field(ys, roots_of_unity, inv=True) - inv_x = bls_modular_inverse(x) - inv_x_pow = inv_x - for i in range(1, FIELD_ELEMENTS_PER_CELL): - interp[i] = BLSFieldElement(int(interp[i]) * int(inv_x_pow) % BLS_MODULUS) - inv_x_pow = BLSFieldElement(int(inv_x_pow) * int(inv_x) % BLS_MODULUS) + inv_h = bls_modular_inverse(h) + inv_h_pow = inv_h - x_pow = bls_modular_inverse(inv_x_pow) - xn2 = bls.multiply(bls.G2(), x_pow) - xn_minus_yn = bls.add(bls.bytes96_to_G2(KZG_SETUP_G2_MONOMIAL[FIELD_ELEMENTS_PER_CELL]), bls.neg(xn2)) + # Shift the domain of the interpolation poly to be over the coset, and not the regular roots of unity + for i in range(1, FIELD_ELEMENTS_PER_CELL): + interpolation_poly[i] = BLSFieldElement(int(interpolation_poly[i]) * int(inv_h_pow) % BLS_MODULUS) + inv_h_pow = BLSFieldElement(int(inv_h_pow) * int(inv_h) % BLS_MODULUS) + + # This is now h^n + h_pow = bls_modular_inverse(inv_h_pow) + # Move [h^n] to G_2 + h_pow_g2 = bls.multiply(bls.G2(), h_pow) + # Compute [s^64 - h^64] in G_2 + s_pow_minus_h_pow = bls.add(bls.bytes96_to_G2(KZG_SETUP_G2_MONOMIAL[FIELD_ELEMENTS_PER_CELL]), bls.neg(h_pow_g2)) - interpolated_poly = g1_lincomb(KZG_SETUP_G1_MONOMIAL[:FIELD_ELEMENTS_PER_CELL], interp) + # Commit to the interpolation poly + interpolated_poly = g1_lincomb(KZG_SETUP_G1_MONOMIAL[:FIELD_ELEMENTS_PER_CELL], interpolation_poly) - return (bls.pairing_check([ - [bls.bytes48_to_G1(proof), xn_minus_yn], + # e(\pi, [s^64 - h^64]) =?= e([p(x) - I(x)], [1]) + return bls.pairing_check([ + [bls.bytes48_to_G1(proof), s_pow_minus_h_pow], [ bls.add(bls.bytes48_to_G1(commitment), bls.neg(bls.bytes48_to_G1(interpolated_poly))), bls.neg(bls.bytes96_to_G2(KZG_SETUP_G2_MONOMIAL[0])), ], - ])) + ]) ``` ### Cell cosets From e8d30b1526c0752622503dba6669490064b8613e Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Thu, 18 Apr 2024 17:09:04 +0300 Subject: [PATCH 14/14] Introduce compute_coset_factor() helper --- .../eip7594/polynomial-commitments-sampling.md | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/specs/_features/eip7594/polynomial-commitments-sampling.md b/specs/_features/eip7594/polynomial-commitments-sampling.md index 6035535922..3d24199dd1 100644 --- a/specs/_features/eip7594/polynomial-commitments-sampling.md +++ b/specs/_features/eip7594/polynomial-commitments-sampling.md @@ -34,6 +34,7 @@ - [`verify_kzg_proof_multi_impl`](#verify_kzg_proof_multi_impl) - [Cell cosets](#cell-cosets) - [`coset_for_cell`](#coset_for_cell) + - [`compute_coset_factor`](#compute_coset_factor) - [Bitwise manipulation](#bitwise-manipulation) - [`reverse_bits_limited`](#reverse_bits_limited) - [Cells](#cells-1) @@ -389,6 +390,17 @@ def coset_for_cell(cell_id: CellID) -> Cell: return Cell(roots_of_unity_brp[FIELD_ELEMENTS_PER_CELL * cell_id:FIELD_ELEMENTS_PER_CELL * (cell_id + 1)]) ``` +#### `compute_coset_factor` + +```python +def compute_coset_factor(coset_id: uint64, roots_of_unity: Sequence[BLSFieldElement]) -> Cell: + """ + Get the coset shifting factor for ``coset_id``. + """ + assert coset_id < CELLS_PER_BLOB + return roots_of_unity[reverse_bits_limited(CELLS_PER_BLOB, coset_id)] +``` + ### Bitwise manipulation #### `reverse_bits_limited` @@ -475,9 +487,9 @@ def verify_cell_proof(commitment_bytes: Bytes48, Public method. """ roots_of_unity = compute_roots_of_unity(FIELD_ELEMENTS_PER_EXT_BLOB) - x = roots_of_unity[reverse_bits_limited(CELLS_PER_BLOB, cell_id)] + h = compute_coset_factor(cell_id, roots_of_unity) ys = bit_reversal_permutation(bytes_to_cell(cell_bytes)) - return verify_kzg_proof_multi_impl(commitment_bytes, x, ys, proof_bytes) + return verify_kzg_proof_multi_impl(commitment_bytes, h, ys, proof_bytes) ``` #### `verify_cell_proof_batch` @@ -516,7 +528,7 @@ def verify_cell_proof_batch(row_commitments_bytes: Sequence[Bytes48], return all( verify_kzg_proof_multi_impl( commitment, - roots_of_unity[reverse_bits_limited(CELLS_PER_BLOB, column_index)], + compute_coset_factor(column_index, roots_of_unity), bit_reversal_permutation(cell), proof) for commitment, column_index, cell, proof in zip(commitments, column_indices, cells, proofs)