Replace `recover_data` with `recover_polynomialcoeff` (#3820)

* chore: remove recover_data

* make it look closer to final code

* Improve comments

* Fix lint issue

* Fix tests & clean things up a bit

* Replace a couple uses of "monomial" with "coefficient"

* Revert "Replace a couple uses of "monomial" with "coefficient""

This reverts commit c9a1a757d1a09190eee78767b3d36b2a84066e42.

* Only replace "monomial" with "coefficient"

---------

Co-authored-by: Justin Traglia <95511699+jtraglia@users.noreply.github.com>
Co-authored-by: Justin Traglia <jtraglia@pm.me>
This commit is contained in:
kevaundray 2024-07-17 14:23:59 +01:00 committed by GitHub
parent bb8f3caafc
commit 233129122b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 41 additions and 56 deletions

View File

@ -39,12 +39,13 @@
- [`coset_for_cell`](#coset_for_cell)
- [Cells](#cells-1)
- [Cell computation](#cell-computation)
- [`compute_cells_and_kzg_proofs_polynomialcoeff`](#compute_cells_and_kzg_proofs_polynomialcoeff)
- [`compute_cells_and_kzg_proofs`](#compute_cells_and_kzg_proofs)
- [Cell verification](#cell-verification)
- [`verify_cell_kzg_proof_batch`](#verify_cell_kzg_proof_batch)
- [Reconstruction](#reconstruction)
- [`construct_vanishing_polynomial`](#construct_vanishing_polynomial)
- [`recover_data`](#recover_data)
- [`recover_polynomialcoeff`](#recover_polynomialcoeff)
- [`recover_cells_and_kzg_proofs`](#recover_cells_and_kzg_proofs)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
@ -555,6 +556,24 @@ def coset_for_cell(cell_index: CellIndex) -> Coset:
### Cell computation
#### `compute_cells_and_kzg_proofs_polynomialcoeff`
```python
def compute_cells_and_kzg_proofs_polynomialcoeff(polynomial_coeff: PolynomialCoeff) -> Tuple[
Vector[Cell, CELLS_PER_EXT_BLOB],
Vector[KZGProof, CELLS_PER_EXT_BLOB]]:
"""
Helper function which computes cells/proofs for a polynomial in coefficient form.
"""
cells, proofs = [], []
for i in range(CELLS_PER_EXT_BLOB):
coset = coset_for_cell(CellIndex(i))
proof, ys = compute_kzg_proof_multi_impl(polynomial_coeff, coset)
cells.append(coset_evals_to_cell(ys))
proofs.append(proof)
return cells, proofs
```
#### `compute_cells_and_kzg_proofs`
```python
@ -572,17 +591,7 @@ def compute_cells_and_kzg_proofs(blob: Blob) -> Tuple[
polynomial = blob_to_polynomial(blob)
polynomial_coeff = polynomial_eval_to_coeff(polynomial)
cells = []
proofs = []
for i in range(CELLS_PER_EXT_BLOB):
coset = coset_for_cell(CellIndex(i))
proof, ys = compute_kzg_proof_multi_impl(polynomial_coeff, coset)
cells.append(coset_evals_to_cell(ys))
proofs.append(proof)
return cells, proofs
return compute_cells_and_kzg_proofs_polynomialcoeff(polynomial_coeff)
```
### Cell verification
@ -668,21 +677,19 @@ def construct_vanishing_polynomial(missing_cell_indices: Sequence[CellIndex]) ->
return zero_poly_coeff
```
### `recover_data`
### `recover_polynomialcoeff`
```python
def recover_data(cell_indices: Sequence[CellIndex],
cells: Sequence[Cell],
) -> Sequence[BLSFieldElement]:
def recover_polynomialcoeff(cell_indices: Sequence[CellIndex],
cells: Sequence[Cell]) -> Sequence[BLSFieldElement]:
"""
Recover the missing evaluations for the extended blob, given at least half of the evaluations.
Recover the polynomial in coefficient form that when evaluated at the roots of unity will give the extended blob.
"""
# Get the extended domain. This will be referred to as the FFT domain.
# Get the extended domain. This will be referred to as the FFT domain
roots_of_unity_extended = compute_roots_of_unity(FIELD_ELEMENTS_PER_EXT_BLOB)
# Flatten the cells into evaluations.
# If a cell is missing, then its evaluation is zero.
# Flatten the cells into evaluations
# If a cell is missing, then its evaluation is zero
extended_evaluation_rbo = [0] * FIELD_ELEMENTS_PER_EXT_BLOB
for cell_index, cell in zip(cell_indices, cells):
start = cell_index * FIELD_ELEMENTS_PER_CELL
@ -690,7 +697,7 @@ def recover_data(cell_indices: Sequence[CellIndex],
extended_evaluation_rbo[start:end] = cell
extended_evaluation = bit_reversal_permutation(extended_evaluation_rbo)
# Compute Z(x) in monomial form
# Compute Z(x) in coefficient form
# Z(x) is the polynomial which vanishes on all of the evaluations which are missing
missing_cell_indices = [CellIndex(cell_index) for cell_index in range(CELLS_PER_EXT_BLOB)
if cell_index not in cell_indices]
@ -703,7 +710,7 @@ def recover_data(cell_indices: Sequence[CellIndex],
extended_evaluation_times_zero = [BLSFieldElement(int(a) * int(b) % BLS_MODULUS)
for a, b in zip(zero_poly_eval, extended_evaluation)]
# Convert (E*Z)(x) to monomial form
# Convert (E*Z)(x) to coefficient form
extended_evaluation_times_zero_coeffs = fft_field(extended_evaluation_times_zero, roots_of_unity_extended, inv=True)
# Convert (E*Z)(x) to evaluation form over a coset of the FFT domain
@ -713,18 +720,12 @@ def recover_data(cell_indices: Sequence[CellIndex],
zero_poly_over_coset = coset_fft_field(zero_poly_coeff, roots_of_unity_extended)
# Compute Q_3(x) = (E*Z)(x) / Z(x) in evaluation form over a coset of the FFT domain
reconstructed_poly_over_coset = [
div(a, b)
for a, b in zip(extended_evaluations_over_coset, zero_poly_over_coset)
]
reconstructed_poly_over_coset = [div(a, b) for a, b in zip(extended_evaluations_over_coset, zero_poly_over_coset)]
# Convert Q_3(x) to monomial form
# Convert Q_3(x) to coefficient form
reconstructed_poly_coeff = coset_fft_field(reconstructed_poly_over_coset, roots_of_unity_extended, inv=True)
# Convert Q_3(x) to evaluation form over the FFT domain and bit reverse the result
reconstructed_data = bit_reversal_permutation(fft_field(reconstructed_poly_coeff, roots_of_unity_extended))
return reconstructed_data
return reconstructed_poly_coeff[:FIELD_ELEMENTS_PER_BLOB]
```
### `recover_cells_and_kzg_proofs`
@ -735,7 +736,7 @@ def recover_cells_and_kzg_proofs(cell_indices: Sequence[CellIndex],
Vector[Cell, CELLS_PER_EXT_BLOB],
Vector[KZGProof, CELLS_PER_EXT_BLOB]]:
"""
Given at least 50% of cells/proofs for a blob, recover all the cells/proofs.
Given at least 50% of cells for a blob, recover all the cells/proofs.
This algorithm uses FFTs to recover cells faster than using Lagrange
implementation, as can be seen here:
https://ethresear.ch/t/reed-solomon-erasure-code-recovery-in-n-log-2-n-time-with-ffts/3039
@ -745,6 +746,7 @@ def recover_cells_and_kzg_proofs(cell_indices: Sequence[CellIndex],
Public method.
"""
# Check we have the same number of cells and indices
assert len(cell_indices) == len(cells)
# Check we have enough cells to be able to perform the reconstruction
assert CELLS_PER_EXT_BLOB / 2 <= len(cell_indices) <= CELLS_PER_EXT_BLOB
@ -757,29 +759,12 @@ def recover_cells_and_kzg_proofs(cell_indices: Sequence[CellIndex],
for cell in cells:
assert len(cell) == BYTES_PER_CELL
# Convert cells to coset evals
# Convert cells to coset evaluations
cosets_evals = [cell_to_coset_evals(cell) for cell in cells]
reconstructed_data = recover_data(cell_indices, cosets_evals)
for cell_index, coset_evals in zip(cell_indices, cosets_evals):
start = cell_index * FIELD_ELEMENTS_PER_CELL
end = (cell_index + 1) * FIELD_ELEMENTS_PER_CELL
assert reconstructed_data[start:end] == coset_evals
recovered_cells = [
coset_evals_to_cell(reconstructed_data[i * FIELD_ELEMENTS_PER_CELL:(i + 1) * FIELD_ELEMENTS_PER_CELL])
for i in range(CELLS_PER_EXT_BLOB)]
polynomial_eval = reconstructed_data[:FIELD_ELEMENTS_PER_BLOB]
polynomial_coeff = polynomial_eval_to_coeff(polynomial_eval)
recovered_proofs = [None] * CELLS_PER_EXT_BLOB
for i in range(CELLS_PER_EXT_BLOB):
coset = coset_for_cell(CellIndex(i))
proof, ys = compute_kzg_proof_multi_impl(polynomial_coeff, coset)
assert coset_evals_to_cell(ys) == recovered_cells[i]
recovered_proofs[i] = proof
return recovered_cells, recovered_proofs
# Given the coset evaluations, recover the polynomial in coefficient form
polynomial_coeff = recover_polynomialcoeff(cell_indices, cosets_evals)
# Recompute all cells/proofs
return compute_cells_and_kzg_proofs_polynomialcoeff(polynomial_coeff)
```