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:
parent
bb8f3caafc
commit
233129122b
|
@ -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)
|
||||
```
|
||||
|
|
Loading…
Reference in New Issue