Rename `recover_cells` to `recover_polynomial` and fix function signature. Add basic test case.

This commit is contained in:
Hsiao-Wei Wang 2024-01-08 23:18:51 +08:00
parent 8fa4ed571d
commit 9a0727000c
No known key found for this signature in database
GPG Key ID: AE3D6B174F971DE4
6 changed files with 64 additions and 29 deletions

View File

@ -0,0 +1,6 @@
# Mainnet preset - PeerDAS
# Misc
# ---------------------------------------------------------------
# `uint64(2**6)` (= 64)
FIELD_ELEMENTS_PER_CELL: 64

View File

@ -0,0 +1,6 @@
# Minimal preset - PeerDAS
# Misc
# ---------------------------------------------------------------
# `uint64(2**6)` (= 64)
FIELD_ELEMENTS_PER_CELL: 64

View File

@ -12,3 +12,9 @@ class PeerDASSpecBuilder(BaseSpecBuilder):
return f''' return f'''
from eth2spec.deneb import {preset_name} as deneb from eth2spec.deneb import {preset_name} as deneb
''' '''
@classmethod
def hardcoded_custom_type_dep_constants(cls, spec_object) -> Dict[str, str]:
return {
'FIELD_ELEMENTS_PER_CELL': spec_object.preset_vars['FIELD_ELEMENTS_PER_CELL'].value,
}

View File

@ -42,7 +42,7 @@
- [`verify_cell_proof`](#verify_cell_proof) - [`verify_cell_proof`](#verify_cell_proof)
- [`verify_cell_proof_batch`](#verify_cell_proof_batch) - [`verify_cell_proof_batch`](#verify_cell_proof_batch)
- [Reconstruction](#reconstruction) - [Reconstruction](#reconstruction)
- [`recover_cells`](#recover_cells) - [`recover_polynomial`](#recover_polynomial)
<!-- END doctoc generated TOC please keep comment here to allow auto update --> <!-- END doctoc generated TOC please keep comment here to allow auto update -->
<!-- /TOC --> <!-- /TOC -->
@ -60,6 +60,8 @@ Public functions MUST accept raw bytes as input and perform the required cryptog
| Name | SSZ equivalent | Description | | Name | SSZ equivalent | Description |
| - | - | - | | - | - | - |
| `PolynomialCoeff` | `Vector[BLSFieldElement, FIELD_ELEMENTS_PER_BLOB]` | A polynomial in coefficient form | | `PolynomialCoeff` | `Vector[BLSFieldElement, FIELD_ELEMENTS_PER_BLOB]` | A polynomial in coefficient form |
| `Cell` | `Vector[BLSFieldElement, FIELD_ELEMENTS_PER_CELL]` | The unit of blob data that can come with their own KZG proofs |
| `CellID` | `uint64` | Cell identifier |
## Constants ## Constants
@ -334,15 +336,13 @@ def verify_kzg_proof_multi_impl(commitment: KZGCommitment,
#### `coset_for_cell` #### `coset_for_cell`
```python ```python
def coset_for_cell(cell_id: int) -> Vector[BLSFieldElement, FIELD_ELEMENTS_PER_CELL]: 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 assert cell_id < CELLS_PER_BLOB
roots_of_unity_brp = bit_reversal_permutation(ROOTS_OF_UNITY_EXTENDED) roots_of_unity_brp = bit_reversal_permutation(ROOTS_OF_UNITY_EXTENDED)
return Vector[BLSFieldElement, FIELD_ELEMENTS_PER_CELL]( return Cell(roots_of_unity_brp[FIELD_ELEMENTS_PER_CELL * cell_id:FIELD_ELEMENTS_PER_CELL * (cell_id + 1)])
roots_of_unity_brp[FIELD_ELEMENTS_PER_CELL * cell_id:FIELD_ELEMENTS_PER_CELL * (cell_id + 1)]
)
``` ```
## Cells ## Cells
@ -353,7 +353,7 @@ def coset_for_cell(cell_id: int) -> Vector[BLSFieldElement, FIELD_ELEMENTS_PER_C
```python ```python
def compute_cells_and_proofs(blob: Blob) -> Tuple[ def compute_cells_and_proofs(blob: Blob) -> Tuple[
Vector[Vector[BLSFieldElement, FIELD_ELEMENTS_PER_CELL], CELLS_PER_BLOB], Vector[Cell, CELLS_PER_BLOB],
Vector[KZGProof, CELLS_PER_BLOB]]: Vector[KZGProof, CELLS_PER_BLOB]]:
""" """
Compute all the cell proofs for one blob. This is an inefficient O(n^2) algorithm, Compute all the cell proofs for one blob. This is an inefficient O(n^2) algorithm,
@ -380,7 +380,7 @@ def compute_cells_and_proofs(blob: Blob) -> Tuple[
#### `compute_cells` #### `compute_cells`
```python ```python
def compute_cells(blob: Blob) -> Vector[Vector[BLSFieldElement, FIELD_ELEMENTS_PER_CELL], CELLS_PER_BLOB]: def compute_cells(blob: Blob) -> Vector[Cell, CELLS_PER_BLOB]:
""" """
Compute the cell data for a blob (without computing the proofs). Compute the cell data for a blob (without computing the proofs).
@ -402,7 +402,7 @@ def compute_cells(blob: Blob) -> Vector[Vector[BLSFieldElement, FIELD_ELEMENTS_P
```python ```python
def verify_cell_proof(commitment: KZGCommitment, def verify_cell_proof(commitment: KZGCommitment,
cell_id: int, cell_id: int,
data: Vector[BLSFieldElement, FIELD_ELEMENTS_PER_CELL], cell: Cell,
proof: KZGProof) -> bool: proof: KZGProof) -> bool:
""" """
Check a cell proof Check a cell proof
@ -411,7 +411,7 @@ def verify_cell_proof(commitment: KZGCommitment,
""" """
coset = coset_for_cell(cell_id) coset = coset_for_cell(cell_id)
return verify_kzg_proof_multi_impl(commitment, coset, data, proof) return verify_kzg_proof_multi_impl(commitment, coset, cell, proof)
``` ```
#### `verify_cell_proof_batch` #### `verify_cell_proof_batch`
@ -420,7 +420,7 @@ def verify_cell_proof(commitment: KZGCommitment,
def verify_cell_proof_batch(row_commitments: Sequence[KZGCommitment], def verify_cell_proof_batch(row_commitments: Sequence[KZGCommitment],
row_ids: Sequence[int], row_ids: Sequence[int],
column_ids: Sequence[int], column_ids: Sequence[int],
datas: Sequence[Vector[BLSFieldElement, FIELD_ELEMENTS_PER_CELL]], cells: Sequence[Cell],
proofs: Sequence[KZGProof]) -> bool: proofs: Sequence[KZGProof]) -> bool:
""" """
Check multiple cell proofs. This function implements the naive algorithm of checking every cell Check multiple cell proofs. This function implements the naive algorithm of checking every cell
@ -433,16 +433,18 @@ def verify_cell_proof_batch(row_commitments: Sequence[KZGCommitment],
# Get commitments via row IDs # Get commitments via row IDs
commitments = [row_commitments[row_id] for row_id in 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), data, proof) return all(
for commitment, column_id, data, proof in zip(commitments, column_ids, datas, proofs)) verify_kzg_proof_multi_impl(commitment, coset_for_cell(column_id), cell, proof)
for commitment, column_id, cell, proof in zip(commitments, column_ids, cells, proofs)
)
``` ```
## Reconstruction ## Reconstruction
### `recover_cells` ### `recover_polynomial`
```python ```python
def recover_cells(cells: Sequence[Tuple[int, ByteVector[BYTES_PER_CELL]]]) -> Polynomial: def recover_polynomial(cell_ids: Sequence[CellID], cells: Sequence[Cell]) -> Polynomial:
""" """
Recovers a polynomial from 2 * FIELD_ELEMENTS_PER_CELL evaluations, half of which can be missing. Recovers a polynomial from 2 * FIELD_ELEMENTS_PER_CELL evaluations, half of which can be missing.
@ -452,8 +454,8 @@ def recover_cells(cells: Sequence[Tuple[int, ByteVector[BYTES_PER_CELL]]]) -> Po
Public method. Public method.
""" """
assert len(cell_ids) == len(cells)
assert len(cells) >= CELLS_PER_BLOB // 2 assert len(cells) >= CELLS_PER_BLOB // 2
cell_ids = [cell_id for cell_id, _ in cells]
missing_cell_ids = [cell_id for cell_id in range(CELLS_PER_BLOB) if cell_id not in cell_ids] missing_cell_ids = [cell_id for cell_id in range(CELLS_PER_BLOB) if cell_id not in cell_ids]
short_zero_poly = vanishing_polynomialcoeff([ short_zero_poly = vanishing_polynomialcoeff([
ROOTS_OF_UNITY_REDUCED[reverse_bits(cell_id, CELLS_PER_BLOB)] ROOTS_OF_UNITY_REDUCED[reverse_bits(cell_id, CELLS_PER_BLOB)]
@ -477,10 +479,11 @@ def recover_cells(cells: Sequence[Tuple[int, ByteVector[BYTES_PER_CELL]]]) -> Po
end = (cell_id + 1) * FIELD_ELEMENTS_PER_CELL end = (cell_id + 1) * FIELD_ELEMENTS_PER_CELL
assert all(a != 0 for a in zero_poly_eval_brp[start:end]) assert all(a != 0 for a in zero_poly_eval_brp[start:end])
extended_evaluation_rbo = [0] * FIELD_ELEMENTS_PER_BLOB * 2 extended_evaluation_rbo = [0] * (FIELD_ELEMENTS_PER_BLOB * 2)
for cell_id, cell_data in cells: for cell_id, cell in zip(cell_ids, cells):
extended_evaluation_rbo[cell_id * FIELD_ELEMENTS_PER_CELL:(cell_id + 1) * FIELD_ELEMENTS_PER_CELL] = \ start = cell_id * FIELD_ELEMENTS_PER_CELL
cell_data end = (cell_id + 1) * FIELD_ELEMENTS_PER_CELL
extended_evaluation_rbo[start:end] = cell
extended_evaluation = bit_reversal_permutation(extended_evaluation_rbo) extended_evaluation = bit_reversal_permutation(extended_evaluation_rbo)
extended_evaluation_times_zero = [a * b % BLS_MODULUS for a, b in zip(zero_poly_eval, extended_evaluation)] extended_evaluation_times_zero = [a * b % BLS_MODULUS for a, b in zip(zero_poly_eval, extended_evaluation)]
@ -507,9 +510,10 @@ def recover_cells(cells: Sequence[Tuple[int, ByteVector[BYTES_PER_CELL]]]) -> Po
reconstructed_data = bit_reversal_permutation(fft_field(reconstructed_poly, ROOTS_OF_UNITY_EXTENDED)) reconstructed_data = bit_reversal_permutation(fft_field(reconstructed_poly, ROOTS_OF_UNITY_EXTENDED))
for cell_id, cell_data in cells: for cell_id, cell in zip(cell_ids, cells):
assert reconstructed_data[cell_id * FIELD_ELEMENTS_PER_CELL:(cell_id + 1) * FIELD_ELEMENTS_PER_CELL] == \ start = cell_id * FIELD_ELEMENTS_PER_CELL
cell_data end = (cell_id + 1) * FIELD_ELEMENTS_PER_CELL
assert reconstructed_data[start:end] == cell
return reconstructed_data return reconstructed_data
``` ```

View File

@ -602,4 +602,3 @@ def verify_blob_kzg_proof_batch(blobs: Sequence[Blob],
return verify_kzg_proof_batch(commitments, evaluation_challenges, ys, proofs) return verify_kzg_proof_batch(commitments, evaluation_challenges, ys, proofs)
``` ```

View File

@ -41,9 +41,23 @@ def test_verify_cell_proof_batch(spec):
cells, proofs = spec.compute_cells_and_proofs(blob) cells, proofs = spec.compute_cells_and_proofs(blob)
assert spec.verify_cell_proof_batch( assert spec.verify_cell_proof_batch(
row_commitments = [commitment], row_commitments=[commitment],
row_ids = [0], row_ids=[0],
column_ids = [0, 1], column_ids=[0, 1],
datas = [cells[0], cells[1]], cells=cells[0:1],
proofs = proofs, proofs=proofs,
) )
@with_peerdas_and_later
@spec_test
@single_phase
def test_recover_polynomial(spec):
blob = get_sample_blob(spec)
original_polynomial = spec.blob_to_polynomial(blob)
cells = spec.compute_cells(blob)
cell_ids = list(range(spec.CELLS_PER_BLOB // 2))
known_cells = [cells[cell_id] for cell_id in cell_ids]
result = spec.recover_polynomial(cell_ids, known_cells)
assert original_polynomial == result[0:len(result) // 2]