Skip to content

Commit

Permalink
Update python bindings
Browse files Browse the repository at this point in the history
  • Loading branch information
jtraglia committed Feb 12, 2025
1 parent 2d8c7f5 commit 2ce319a
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 0 deletions.
67 changes: 67 additions & 0 deletions bindings/python/ckzg_wrap.c
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,71 @@ static PyObject *verify_blob_kzg_proof_batch_wrap(PyObject *self,
Py_RETURN_FALSE;
}

static PyObject *compute_cells_wrap(PyObject *self, PyObject *args) {
PyObject *input_blob, *s;
PyObject *ret = NULL;
Cell *cells = NULL;

/* Ensure inputs are the right types */
if (!PyArg_UnpackTuple(args, "compute_cells", 2, 2, &input_blob, &s) ||
!PyBytes_Check(input_blob) || !PyCapsule_IsValid(s, "KZGSettings")) {
ret = PyErr_Format(PyExc_ValueError, "expected bytes and trusted setup");
goto out;
}

/* Ensure blob is the right size */
if (PyBytes_Size(input_blob) != BYTES_PER_BLOB) {
ret = PyErr_Format(PyExc_ValueError,
"expected blob to be BYTES_PER_BLOB bytes");
goto out;
}

/* Allocate space for the cells */
cells = calloc(CELLS_PER_EXT_BLOB, BYTES_PER_CELL);
if (cells == NULL) {
ret =
PyErr_Format(PyExc_MemoryError, "Failed to allocate memory for cells");
goto out;
}

/* Call our C function with our inputs */
const Blob *blob = (Blob *)PyBytes_AsString(input_blob);
if (compute_cells_and_kzg_proofs(cells, NULL, blob,
PyCapsule_GetPointer(s, "KZGSettings")) !=
C_KZG_OK) {
ret = PyErr_Format(PyExc_RuntimeError, "compute_cells failed");
goto out;
}

/* Convert our cells result to a list of bytes objects */
PyObject *output_cells = PyList_New(CELLS_PER_EXT_BLOB);
if (output_cells == NULL) {
ret = PyErr_Format(PyExc_MemoryError,
"Failed to allocate memory for output cells");
goto out;
}
for (size_t i = 0; i < CELLS_PER_EXT_BLOB; i++) {
/* Convert cell to a bytes object */
PyObject *cell_bytes =
PyBytes_FromStringAndSize((const char *)&cells[i], BYTES_PER_CELL);
if (cell_bytes == NULL) {
Py_DECREF(cell_bytes);
ret = PyErr_Format(PyExc_MemoryError,
"Failed to allocate memory for cell bytes");
goto out;
}
/* Add it to our list */
PyList_SetItem(output_cells, i, cell_bytes);
}

/* Success! */
ret = output_cells;

out:
free(cells);
return ret;
}

static PyObject *compute_cells_and_kzg_proofs_wrap(PyObject *self,
PyObject *args) {
PyObject *input_blob, *s;
Expand Down Expand Up @@ -728,6 +793,8 @@ static PyMethodDef ckzgmethods[] = {
"Verify a blob/commitment/proof combo"},
{"verify_blob_kzg_proof_batch", verify_blob_kzg_proof_batch_wrap,
METH_VARARGS, "Verify multiple blob/commitment/proof combos"},
{"compute_cells", compute_cells_wrap, METH_VARARGS,
"Compute cells for a blob"},
{"compute_cells_and_kzg_proofs", compute_cells_and_kzg_proofs_wrap,
METH_VARARGS, "Compute cells and proofs for a blob"},
{"recover_cells_and_kzg_proofs", recover_cells_and_kzg_proofs_wrap,
Expand Down
21 changes: 21 additions & 0 deletions bindings/python/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
VERIFY_BLOB_KZG_PROOF_BATCH_TESTS = "../../tests/verify_blob_kzg_proof_batch/*/*/data.yaml"

# EIP-7594
COMPUTE_CELLS_TESTS = "../../tests/compute_cells/*/*/data.yaml"
COMPUTE_CELLS_AND_KZG_PROOFS_TESTS = "../../tests/compute_cells_and_kzg_proofs/*/*/data.yaml"
RECOVER_CELLS_AND_KZG_PROOFS_TESTS = "../../tests/recover_cells_and_kzg_proofs/*/*/data.yaml"
VERIFY_CELL_KZG_PROOF_BATCH_TESTS = "../../tests/verify_cell_kzg_proof_batch/*/*/data.yaml"
Expand Down Expand Up @@ -164,6 +165,26 @@ def test_verify_blob_kzg_proof_batch(ts):
assert valid == expected_valid, f"{test_file}\n{valid=}\n{expected_valid=}"


def test_compute_cells(ts):
test_files = glob.glob(COMPUTE_CELLS_TESTS)
assert len(test_files) > 0

for test_file in test_files:
with open(test_file, "r") as f:
test = yaml.safe_load(f)

blob = bytes_from_hex(test["input"]["blob"])

try:
cells = ckzg.compute_cells(blob, ts)
except:
assert test["output"] is None
continue

expected_cells = list(map(bytes_from_hex, test["output"]))
assert cells == expected_cells, f"{test_file}\n{cells=}\n{expected_cells=}"


def test_compute_cells_and_kzg_proofs(ts):
test_files = glob.glob(COMPUTE_CELLS_AND_KZG_PROOFS_TESTS)
assert len(test_files) > 0
Expand Down

0 comments on commit 2ce319a

Please sign in to comment.