Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace recover_data with recover_polynomialcoeff #3820

Merged
merged 9 commits into from
Jul 17, 2024
98 changes: 43 additions & 55 deletions specs/_features/eip7594/polynomial-commitments-sampling.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
- [`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 -->
Expand Down Expand Up @@ -255,14 +255,25 @@ def compute_verify_cell_kzg_proof_batch_challenge(commitments: Sequence[KZGCommi
```python
def polynomial_eval_to_coeff(polynomial: Polynomial) -> PolynomialCoeff:
"""
Interpolates a polynomial (given in evaluation form) to a polynomial in coefficient form.
Interpolates a polynomial evaluation form to a polynomial in coefficient form.
"""
roots_of_unity = compute_roots_of_unity(FIELD_ELEMENTS_PER_BLOB)
polynomial_coeff = fft_field(bit_reversal_permutation(list(polynomial)), roots_of_unity, inv=True)

return polynomial_coeff
```

#### `polynomial_coeff_to_eval`

```python
def polynomial_coeff_to_eval(polynomial_coeff: PolynomialCoeff) -> Polynomial:
"""
Interpolates a polynomial in coefficient form to a polynomial in evaluation form.
"""
roots_of_unity = compute_roots_of_unity(FIELD_ELEMENTS_PER_BLOB)
polynomial = bit_reversal_permutation(fft_field(list(polynomial_coeff)), roots_of_unity)
return polynomial
```

#### `add_polynomialcoeff`

```python
Expand Down Expand Up @@ -572,16 +583,14 @@ def compute_cells_and_kzg_proofs(blob: Blob) -> Tuple[

polynomial = blob_to_polynomial(blob)
polynomial_coeff = polynomial_eval_to_coeff(polynomial)

cells = []
proofs = []


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)

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
```

Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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`
Expand All @@ -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
Expand All @@ -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
Expand All @@ -757,29 +759,15 @@ 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)

# Convert the polynomial to a blob
polynomial = polynomial_coeff_to_eval(polynomial_coeff)

# Recompute all cells/proofs
return compute_cells_and_kzg_proofs(blob)
```
Loading