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

eip7594: Remove proof parameter from recover_cells_and_kzg_proofs #3819

Merged
merged 3 commits into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions specs/_features/eip7594/das-core.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,8 @@ def recover_matrix(partial_matrix: Sequence[MatrixEntry],
for blob_index in range(blob_count):
cell_indices = [e.column_index for e in partial_matrix if e.row_index == blob_index]
cells = [e.cell for e in partial_matrix if e.row_index == blob_index]
proofs = [e.kzg_proof for e in partial_matrix if e.row_index == blob_index]

recovered_cells, recovered_proofs = recover_cells_and_kzg_proofs(cell_indices, cells, proofs)
recovered_cells, recovered_proofs = recover_cells_and_kzg_proofs(cell_indices, cells)
for cell_index, (cell, proof) in enumerate(zip(recovered_cells, recovered_proofs)):
extended_matrix.append(MatrixEntry(
cell=cell,
Expand Down
20 changes: 7 additions & 13 deletions specs/_features/eip7594/polynomial-commitments-sampling.md
Original file line number Diff line number Diff line change
Expand Up @@ -645,8 +645,7 @@ def recover_data(cell_indices: Sequence[CellIndex],

```python
def recover_cells_and_kzg_proofs(cell_indices: Sequence[CellIndex],
cells: Sequence[Cell],
proofs_bytes: Sequence[Bytes48]) -> Tuple[
cells: Sequence[Cell]) -> Tuple[
Vector[Cell, CELLS_PER_EXT_BLOB],
Vector[KZGProof, CELLS_PER_EXT_BLOB]]:
"""
Expand All @@ -660,7 +659,7 @@ def recover_cells_and_kzg_proofs(cell_indices: Sequence[CellIndex],

Public method.
"""
assert len(cell_indices) == len(cells) == len(proofs_bytes)
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
# Check for duplicates
Expand All @@ -671,9 +670,6 @@ def recover_cells_and_kzg_proofs(cell_indices: Sequence[CellIndex],
# Check that each cell is the correct length
for cell in cells:
assert len(cell) == BYTES_PER_CELL
# Check that each proof is the correct length
for proof_bytes in proofs_bytes:
assert len(proof_bytes) == BYTES_PER_PROOF

# Convert cells to coset evals
cosets_evals = [cell_to_coset_evals(cell) for cell in cells]
Expand All @@ -692,14 +688,12 @@ def recover_cells_and_kzg_proofs(cell_indices: Sequence[CellIndex],
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, cell_index in enumerate(cell_indices):
recovered_proofs[cell_index] = bytes_to_kzg_proof(proofs_bytes[i])

for i in range(CELLS_PER_EXT_BLOB):
if recovered_proofs[i] is None:
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
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
```
Original file line number Diff line number Diff line change
Expand Up @@ -164,12 +164,11 @@ def test_recover_cells_and_kzg_proofs(spec):
while j in cell_indices:
j = rng.randint(0, spec.CELLS_PER_EXT_BLOB - 1)
cell_indices.append(j)
# Now the cells/proofs themselves
# Now the cells themselves
known_cells = [cells[cell_index] for cell_index in cell_indices]
known_proofs = [proofs[cell_index] for cell_index in cell_indices]

# Recover the missing cells and proofs
recovered_cells, recovered_proofs = spec.recover_cells_and_kzg_proofs(cell_indices, known_cells, known_proofs)
recovered_cells, recovered_proofs = spec.recover_cells_and_kzg_proofs(cell_indices, known_cells)
recovered_data = [x for xs in recovered_cells for x in xs]

# Check that the original data match the non-extended portion of the recovered data
Expand Down
2 changes: 1 addition & 1 deletion tests/formats/kzg_7594/recover_cells_and_kzg_proofs.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ All byte(s) fields are encoded as strings, hexadecimal encoding, prefixed with `

## Condition

The `recover_cells_and_kzg_proofs` handler should recover missing cells and proofs, and the result should match the expected `output`. If any cell is invalid (e.g. incorrect length or one of the 32-byte blocks does not represent a BLS field element), any proof is invalid (e.g. not on the curve or not in the G1 subgroup of the BLS curve), or any `cell_index` is invalid (e.g. greater than the number of cells for an extended blob), it should error, i.e. the output should be `null`.
The `recover_cells_and_kzg_proofs` handler should recover missing cells and proofs, and the result should match the expected `output`. If any cell is invalid (e.g. incorrect length or one of the 32-byte blocks does not represent a BLS field element), or any `cell_index` is invalid (e.g. greater than the number of cells for an extended blob), it should error, i.e. the output should be `null`.
108 changes: 24 additions & 84 deletions tests/generators/kzg_7594/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
from eth2spec.test.utils.kzg_tests import (
CELL_RANDOM_VALID1,
CELL_RANDOM_VALID2,
G1,
INVALID_BLOBS,
INVALID_G1_POINTS,
INVALID_INDIVIDUAL_CELL_BYTES,
Expand Down Expand Up @@ -593,15 +592,14 @@ def case_recover_cells_and_kzg_proofs():
# Valid: No missing cells
cells, proofs = VALID_CELLS_AND_PROOFS[0]
cell_indices = list(range(spec.CELLS_PER_EXT_BLOB))
recovered_cells, recovered_proofs = spec.recover_cells_and_kzg_proofs(cell_indices, cells, proofs)
recovered_cells, recovered_proofs = spec.recover_cells_and_kzg_proofs(cell_indices, cells)
assert recovered_cells == cells
assert recovered_proofs == proofs
identifier = make_id(cell_indices, cells, proofs)
identifier = make_id(cell_indices, cells)
yield f'recover_cells_and_kzg_proofs_case_valid_no_missing_{identifier}', {
'input': {
'cell_indices': cell_indices,
'cells': encode_hex_list(cells),
'proofs': encode_hex_list(proofs),
},
'output': (encode_hex_list(recovered_cells), encode_hex_list(recovered_proofs))
}
Expand All @@ -610,16 +608,14 @@ def case_recover_cells_and_kzg_proofs():
cells, proofs = VALID_CELLS_AND_PROOFS[1]
cell_indices = list(range(0, spec.CELLS_PER_EXT_BLOB, 2))
partial_cells = [cells[cell_index] for cell_index in cell_indices]
partial_proofs = [proofs[cell_index] for cell_index in cell_indices]
recovered_cells, recovered_proofs = spec.recover_cells_and_kzg_proofs(cell_indices, partial_cells, partial_proofs)
recovered_cells, recovered_proofs = spec.recover_cells_and_kzg_proofs(cell_indices, partial_cells)
assert recovered_cells == cells
assert recovered_proofs == proofs
identifier = make_id(cell_indices, partial_cells, partial_proofs)
identifier = make_id(cell_indices, partial_cells)
yield f'recover_cells_and_kzg_proofs_case_valid_half_missing_every_other_cell_{identifier}', {
'input': {
'cell_indices': cell_indices,
'cells': encode_hex_list(partial_cells),
'proofs': encode_hex_list(partial_proofs),
},
'output': (encode_hex_list(recovered_cells), encode_hex_list(recovered_proofs))
}
Expand All @@ -628,16 +624,14 @@ def case_recover_cells_and_kzg_proofs():
cells, proofs = VALID_CELLS_AND_PROOFS[2]
cell_indices = list(range(0, spec.CELLS_PER_EXT_BLOB // 2))
partial_cells = [cells[cell_index] for cell_index in cell_indices]
partial_proofs = [proofs[cell_index] for cell_index in cell_indices]
recovered_cells, recovered_proofs = spec.recover_cells_and_kzg_proofs(cell_indices, partial_cells, partial_proofs)
recovered_cells, recovered_proofs = spec.recover_cells_and_kzg_proofs(cell_indices, partial_cells)
assert recovered_cells == cells
assert recovered_proofs == proofs
identifier = make_id(cell_indices, partial_cells)
yield f'recover_cells_and_kzg_proofs_case_valid_half_missing_first_half_{identifier}', {
'input': {
'cell_indices': cell_indices,
'cells': encode_hex_list(partial_cells),
'proofs': encode_hex_list(partial_proofs),
},
'output': (encode_hex_list(recovered_cells), encode_hex_list(recovered_proofs))
}
Expand All @@ -646,16 +640,14 @@ def case_recover_cells_and_kzg_proofs():
cells, proofs = VALID_CELLS_AND_PROOFS[3]
cell_indices = list(range(spec.CELLS_PER_EXT_BLOB // 2, spec.CELLS_PER_EXT_BLOB))
partial_cells = [cells[cell_index] for cell_index in cell_indices]
partial_proofs = [proofs[cell_index] for cell_index in cell_indices]
recovered_cells, recovered_proofs = spec.recover_cells_and_kzg_proofs(cell_indices, partial_cells, partial_proofs)
recovered_cells, recovered_proofs = spec.recover_cells_and_kzg_proofs(cell_indices, partial_cells)
assert recovered_cells == cells
assert recovered_proofs == proofs
identifier = make_id(cell_indices, partial_cells)
yield f'recover_cells_and_kzg_proofs_case_valid_half_missing_second_half_{identifier}', {
'input': {
'cell_indices': cell_indices,
'cells': encode_hex_list(partial_cells),
'proofs': encode_hex_list(partial_proofs),
},
'output': (encode_hex_list(recovered_cells), encode_hex_list(recovered_proofs))
}
Expand All @@ -668,95 +660,67 @@ def case_recover_cells_and_kzg_proofs():
'input': {
'cell_indices': cell_indices,
'cells': encode_hex_list(partial_cells),
'proofs': encode_hex_list(partial_proofs),
},
'output': None
}

# Edge case: More than half missing
cells, proofs = VALID_CELLS_AND_PROOFS[4]
cells, _ = VALID_CELLS_AND_PROOFS[4]
cell_indices = list(range(spec.CELLS_PER_EXT_BLOB // 2 - 1))
partial_cells = [cells[cell_index] for cell_index in cell_indices]
partial_proofs = [proofs[cell_index] for cell_index in cell_indices]
expect_exception(spec.recover_cells_and_kzg_proofs, cell_indices, partial_cells, partial_proofs)
identifier = make_id(cell_indices, partial_cells, partial_proofs)
expect_exception(spec.recover_cells_and_kzg_proofs, cell_indices, partial_cells)
identifier = make_id(cell_indices, partial_cells)
yield f'recover_cells_and_kzg_proofs_case_invalid_more_than_half_missing_{identifier}', {
'input': {
'cell_indices': cell_indices,
'cells': encode_hex_list(partial_cells),
'proofs': encode_hex_list(partial_proofs),
},
'output': None
}

# Edge case: More cells provided than CELLS_PER_EXT_BLOB
cells, proofs = VALID_CELLS_AND_PROOFS[5]
cells, _ = VALID_CELLS_AND_PROOFS[5]
cell_indices = list(range(spec.CELLS_PER_EXT_BLOB)) + [0]
partial_cells = [cells[cell_index] for cell_index in cell_indices]
partial_proofs = [proofs[cell_index] for cell_index in cell_indices]
expect_exception(spec.recover_cells_and_kzg_proofs, cell_indices, partial_cells, partial_proofs)
identifier = make_id(cell_indices, partial_cells, partial_proofs)
expect_exception(spec.recover_cells_and_kzg_proofs, cell_indices, partial_cells)
identifier = make_id(cell_indices, partial_cells)
yield f'recover_cells_and_kzg_proofs_case_invalid_more_cells_than_cells_per_ext_blob_{identifier}', {
'input': {
'cell_indices': cell_indices,
'cells': encode_hex_list(partial_cells),
'proofs': encode_hex_list(partial_proofs),
},
'output': None
}

# Edge case: Invalid cell_index
cells, proofs = VALID_CELLS_AND_PROOFS[6]
cells, _ = VALID_CELLS_AND_PROOFS[6]
cell_indices = list(range(spec.CELLS_PER_EXT_BLOB // 2))
partial_cells = [cells[cell_index] for cell_index in cell_indices]
partial_proofs = [proofs[cell_index] for cell_index in cell_indices]
# Replace first cell_index with an invalid value
cell_indices[0] = spec.CELLS_PER_EXT_BLOB
expect_exception(spec.recover_cells_and_kzg_proofs, cell_indices, partial_cells, partial_proofs)
identifier = make_id(cell_indices, partial_cells, partial_proofs)
expect_exception(spec.recover_cells_and_kzg_proofs, cell_indices, partial_cells)
identifier = make_id(cell_indices, partial_cells)
yield f'recover_cells_and_kzg_proofs_case_invalid_cell_index_{identifier}', {
'input': {
'cell_indices': cell_indices,
'cells': encode_hex_list(partial_cells),
'proofs': encode_hex_list(partial_proofs),
},
'output': None
}

# Edge case: Invalid cell
for cell in INVALID_INDIVIDUAL_CELL_BYTES:
cells, proofs = VALID_CELLS_AND_PROOFS[6]
cells, _ = VALID_CELLS_AND_PROOFS[6]
cell_indices = list(range(spec.CELLS_PER_EXT_BLOB // 2))
partial_cells = [cells[cell_index] for cell_index in cell_indices]
partial_proofs = [proofs[cell_index] for cell_index in cell_indices]
# Replace first cell with an invalid value
partial_cells[0] = cell
expect_exception(spec.recover_cells_and_kzg_proofs, cell_indices, partial_cells, partial_proofs)
identifier = make_id(cell_indices, partial_cells, partial_proofs)
expect_exception(spec.recover_cells_and_kzg_proofs, cell_indices, partial_cells)
identifier = make_id(cell_indices, partial_cells)
yield f'recover_cells_and_kzg_proofs_case_invalid_cell_{identifier}', {
'input': {
'cell_indices': cell_indices,
'cells': encode_hex_list(partial_cells),
'proofs': encode_hex_list(partial_proofs),
},
'output': None
}

# Edge case: Invalid proof
for proof in INVALID_G1_POINTS:
cells, proofs = VALID_CELLS_AND_PROOFS[0]
cell_indices = list(range(spec.CELLS_PER_EXT_BLOB // 2))
partial_cells = [cells[cell_index] for cell_index in cell_indices]
partial_proofs = [proofs[cell_index] for cell_index in cell_indices]
# Replace first proof with an invalid value
partial_proofs[0] = proof
expect_exception(spec.recover_cells_and_kzg_proofs, cell_indices, partial_cells, partial_proofs)
identifier = make_id(cell_indices, partial_cells, partial_proofs)
yield f'recover_cells_and_kzg_proofs_case_invalid_proof_{identifier}', {
'input': {
'cell_indices': cell_indices,
'cells': encode_hex_list(partial_cells),
'proofs': encode_hex_list(partial_proofs),
},
'output': None
}
Expand All @@ -765,16 +729,14 @@ def case_recover_cells_and_kzg_proofs():
cells, proofs = VALID_CELLS_AND_PROOFS[0]
cell_indices = list(range(0, spec.CELLS_PER_EXT_BLOB, 2))
partial_cells = [cells[cell_index] for cell_index in cell_indices]
partial_proofs = [proofs[cell_index] for cell_index in cell_indices]
# Add another cell_index
cell_indices.append(spec.CELLS_PER_EXT_BLOB - 1)
expect_exception(spec.recover_cells_and_kzg_proofs, cell_indices, partial_cells, partial_proofs)
identifier = make_id(cell_indices, partial_cells, partial_proofs)
expect_exception(spec.recover_cells_and_kzg_proofs, cell_indices, partial_cells)
identifier = make_id(cell_indices, partial_cells)
yield f'recover_cells_and_kzg_proofs_case_invalid_more_cell_indices_than_cells_{identifier}', {
'input': {
'cell_indices': cell_indices,
'cells': encode_hex_list(partial_cells),
'proofs': encode_hex_list(partial_proofs),
},
'output': None
}
Expand All @@ -783,34 +745,14 @@ def case_recover_cells_and_kzg_proofs():
cells, proofs = VALID_CELLS_AND_PROOFS[1]
cell_indices = list(range(0, spec.CELLS_PER_EXT_BLOB, 2))
partial_cells = [cells[cell_index] for cell_index in cell_indices]
partial_proofs = [proofs[cell_index] for cell_index in cell_indices]
# Add another cell
partial_cells.append(CELL_RANDOM_VALID1)
expect_exception(spec.recover_cells_and_kzg_proofs, cell_indices, partial_cells, partial_proofs)
identifier = make_id(cell_indices, partial_cells, partial_proofs)
expect_exception(spec.recover_cells_and_kzg_proofs, cell_indices, partial_cells)
identifier = make_id(cell_indices, partial_cells)
yield f'recover_cells_and_kzg_proofs_case_invalid_more_cells_than_cell_indices_{identifier}', {
'input': {
'cell_indices': cell_indices,
'cells': encode_hex_list(partial_cells),
'proofs': encode_hex_list(partial_proofs),
},
'output': None
}

# Edge case: More proofs than cell_indices
cells, proofs = VALID_CELLS_AND_PROOFS[1]
cell_indices = list(range(0, spec.CELLS_PER_EXT_BLOB, 2))
partial_cells = [cells[cell_index] for cell_index in cell_indices]
partial_proofs = [proofs[cell_index] for cell_index in cell_indices]
# Add another proof
partial_proofs.append(G1)
expect_exception(spec.recover_cells_and_kzg_proofs, cell_indices, partial_cells, partial_proofs)
identifier = make_id(cell_indices, partial_cells, partial_proofs)
yield f'recover_cells_and_kzg_proofs_case_invalid_more_proofs_than_cell_indices_{identifier}', {
'input': {
'cell_indices': cell_indices,
'cells': encode_hex_list(partial_cells),
'proofs': encode_hex_list(partial_proofs),
},
'output': None
}
Expand All @@ -824,16 +766,14 @@ def case_recover_cells_and_kzg_proofs():
# to insufficient cell count, not because of a duplicate cell.
cell_indices = list(range(spec.CELLS_PER_EXT_BLOB // 2 + 1))
partial_cells = [cells[cell_index] for cell_index in cell_indices]
partial_proofs = [proofs[cell_index] for cell_index in cell_indices]
# Replace first cell_index with the second cell_index
cell_indices[0] = cell_indices[1]
expect_exception(spec.recover_cells_and_kzg_proofs, cell_indices, partial_cells, partial_proofs)
identifier = make_id(cell_indices, partial_cells, partial_proofs)
expect_exception(spec.recover_cells_and_kzg_proofs, cell_indices, partial_cells)
identifier = make_id(cell_indices, partial_cells)
yield f'recover_cells_and_kzg_proofs_case_invalid_duplicate_cell_index_{identifier}', {
'input': {
'cell_indices': cell_indices,
'cells': encode_hex_list(partial_cells),
'proofs': encode_hex_list(partial_proofs),
},
'output': None
}
Expand Down