From da8a2045178bfe4ac62d9bdb12f4c5729d886351 Mon Sep 17 00:00:00 2001 From: healthykim Date: Thu, 4 Sep 2025 19:27:54 +0900 Subject: [PATCH] fix: fix errors in cell level kzg functions --- crypto/kzg4844/kzg4844.go | 8 ++--- crypto/kzg4844/kzg4844_ckzg_cgo.go | 50 +++++++++++++++++--------- crypto/kzg4844/kzg4844_ckzg_nocgo.go | 2 +- crypto/kzg4844/kzg4844_gokzg.go | 52 +++++++++++++++++++--------- crypto/kzg4844/kzg4844_test.go | 50 +++++++++++++++++--------- 5 files changed, 107 insertions(+), 55 deletions(-) diff --git a/crypto/kzg4844/kzg4844.go b/crypto/kzg4844/kzg4844.go index 26ea6ff53b..22e888218e 100644 --- a/crypto/kzg4844/kzg4844.go +++ b/crypto/kzg4844/kzg4844.go @@ -206,7 +206,7 @@ func IsValidVersionedHash(h []byte) bool { } // VerifyCellProof verifies a batch of proofs corresponding to the cells and commitments. -// Expects length of proofs, cells and cellIndices, flattened +// Expects equal length of proofs and cells, flattened func VerifyCells(cells []Cell, commitments []Commitment, proofs []Proof, cellIndices []uint64) error { if useCKZG.Load() { return ckzgVerifyCells(cells, commitments, proofs, cellIndices) @@ -221,10 +221,10 @@ func ComputeCells(blobs []Blob) ([]Cell, error) { return gokzgComputeCells(blobs) } -func RecoverBlob(cells []Cell, cellIndices []uint64) (Blob, error) { +func RecoverBlobs(cells []Cell, cellIndices []uint64) ([]Blob, error) { if useCKZG.Load() { - return ckzgRecoverBlob(cells, cellIndices) + return ckzgRecoverBlobs(cells, cellIndices) } - return gokzgRecoverBlob(cells, cellIndices) + return gokzgRecoverBlobs(cells, cellIndices) } diff --git a/crypto/kzg4844/kzg4844_ckzg_cgo.go b/crypto/kzg4844/kzg4844_ckzg_cgo.go index e539692de8..dd2320fe0d 100644 --- a/crypto/kzg4844/kzg4844_ckzg_cgo.go +++ b/crypto/kzg4844/kzg4844_ckzg_cgo.go @@ -150,7 +150,7 @@ func ckzgComputeCellProofs(blob *Blob) ([]Proof, error) { return p, nil } -// ckzgVerifyCellProofBatch verifies that the blob data corresponds to the provided commitment. +// ckzgVerifyCellProofs verifies that the blob data corresponds to the provided commitment. func ckzgVerifyCellProofBatch(blobs []Blob, commitments []Commitment, cellProofs []Proof) error { ckzgIniter.Do(ckzgInit) var ( @@ -196,6 +196,7 @@ func ckzgVerifyCells(cells []Cell, commitments []Commitment, cellProofs []Proof, var ( proofs = make([]ckzg4844.Bytes48, len(cellProofs)) commits = make([]ckzg4844.Bytes48, 0, len(cellProofs)) + indices = make([]uint64, 0, len(cellProofs)) kzgcells = make([]ckzg4844.Cell, 0, len(cellProofs)) ) // Copy over the cell proofs and cells @@ -213,6 +214,11 @@ func ckzgVerifyCells(cells []Cell, commitments []Commitment, cellProofs []Proof, commits = append(commits, (ckzg4844.Bytes48)(commitment)) } } + blobCounts := len(cellProofs) / len(cellIndices) + for j := 0; j < blobCounts; j++ { + indices = append(indices, cellIndices...) + } + valid, err := ckzg4844.VerifyCellKZGProofBatch(commits, cellIndices, kzgcells, proofs) if err != nil { return err @@ -230,7 +236,7 @@ func ckzgComputeCells(blobs []Blob) ([]Cell, error) { for i := range blobs { cellsI, err := ckzg4844.ComputeCells((*ckzg4844.Blob)(&blobs[i])) if err != nil { - return nil, err + return []Cell{}, err } for _, c := range cellsI { cells = append(cells, Cell(c)) @@ -239,25 +245,37 @@ func ckzgComputeCells(blobs []Blob) ([]Cell, error) { return cells, nil } -func ckzgRecoverBlob(cells []Cell, cellIndices []uint64) (Blob, error) { +func ckzgRecoverBlobs(cells []Cell, cellIndices []uint64) ([]Blob, error) { ckzgIniter.Do(ckzgInit) - var kzgcells = make([]ckzg4844.Cell, 0, len(cells)) - - for _, cell := range cells { - kzgcells = append(kzgcells, ckzg4844.Cell(cell)) + if len(cells)%len(cellIndices) != 0 { + return []Blob{}, errors.New("cells with wrong length") } - extCells, _, err := ckzg4844.RecoverCellsAndKZGProofs(cellIndices, kzgcells) - if err != nil { - return Blob{}, err - } + blobCount := len(cells) / len(cellIndices) + var blobs = make([]Blob, 0, blobCount) - var result Blob offset := 0 - for _, cell := range extCells[:64] { - copy(result[offset:], cell[:]) - offset += len(cell) + for range blobCount { + var kzgcells = make([]ckzg4844.Cell, 0, len(cellIndices)) + + for _, cell := range cells[offset : offset+len(cellIndices)] { + kzgcells = append(kzgcells, ckzg4844.Cell(cell)) + } + + extCells, _, err := ckzg4844.RecoverCellsAndKZGProofs(cellIndices, kzgcells) + if err != nil { + return []Blob{}, err + } + + var blob Blob + for i, cell := range extCells[:64] { + copy(blob[i*len(cell):], cell[:]) + } + blobs = append(blobs, blob) + + offset = offset + len(cellIndices) } - return result, nil + + return blobs, nil } diff --git a/crypto/kzg4844/kzg4844_ckzg_nocgo.go b/crypto/kzg4844/kzg4844_ckzg_nocgo.go index 965817adcb..e1a3c0af1e 100644 --- a/crypto/kzg4844/kzg4844_ckzg_nocgo.go +++ b/crypto/kzg4844/kzg4844_ckzg_nocgo.go @@ -82,6 +82,6 @@ func ckzgComputeCells(blobs []Blob) ([]Cell, error) { panic("unsupported platform") } -func ckzgRecoverBlob(cells []Cell, cellIndices []uint64) (Blob, error) { +func ckzgRecoverBlobs(cells []Cell, cellIndices []uint64) ([]Blob, error) { panic("unsupported platform") } diff --git a/crypto/kzg4844/kzg4844_gokzg.go b/crypto/kzg4844/kzg4844_gokzg.go index 22471ebcf4..7ae6421349 100644 --- a/crypto/kzg4844/kzg4844_gokzg.go +++ b/crypto/kzg4844/kzg4844_gokzg.go @@ -156,6 +156,7 @@ func gokzgVerifyCells(cells []Cell, commitments []Commitment, cellProofs []Proof var ( proofs = make([]gokzg4844.KZGProof, len(cellProofs)) commits = make([]gokzg4844.KZGCommitment, 0, len(cellProofs)) + indices = make([]uint64, 0, len(cellProofs)) kzgcells = make([]*gokzg4844.Cell, 0, len(cellProofs)) ) // Copy over the cell proofs and cells @@ -174,7 +175,12 @@ func gokzgVerifyCells(cells []Cell, commitments []Commitment, cellProofs []Proof commits = append(commits, gokzg4844.KZGCommitment(commitment)) } } - return context.VerifyCellKZGProofBatch(commits, cellIndices, kzgcells, proofs) + blobCounts := len(cellProofs) / len(cellIndices) + for j := 0; j < blobCounts; j++ { + indices = append(indices, cellIndices...) + } + + return context.VerifyCellKZGProofBatch(commits, indices, kzgcells, proofs) } // gokzgComputeCells computes cells from blobs. @@ -186,7 +192,7 @@ func gokzgComputeCells(blobs []Blob) ([]Cell, error) { for i := range blobs { cellsI, err := context.ComputeCells((*gokzg4844.Blob)(&blobs[i]), 2) if err != nil { - return nil, err + return []Cell{}, err } for _, c := range cellsI { if c != nil { @@ -197,26 +203,38 @@ func gokzgComputeCells(blobs []Blob) ([]Cell, error) { return cells, nil } -func gokzgRecoverBlob(cells []Cell, cellIndices []uint64) (Blob, error) { +func gokzgRecoverBlobs(cells []Cell, cellIndices []uint64) ([]Blob, error) { gokzgIniter.Do(gokzgInit) - var kzgcells = make([]*gokzg4844.Cell, 0, len(cells)) - - for _, cell := range cells { - gc := gokzg4844.Cell(cell) - kzgcells = append(kzgcells, &gc) + if len(cells)%len(cellIndices) != 0 { + return []Blob{}, errors.New("cells with wrong length") } - extCells, _, err := context.RecoverCellsAndComputeKZGProofs(cellIndices, kzgcells, 2) // todo - if err != nil { - return Blob{}, err - } + blobCount := len(cells) / len(cellIndices) + var blobs = make([]Blob, 0, blobCount) - var result Blob offset := 0 - for _, cell := range extCells[:64] { - copy(result[offset:], cell[:]) - offset += len(cell) + for range blobCount { + var kzgcells = make([]*gokzg4844.Cell, 0, len(cellIndices)) + + for _, cell := range cells[offset : offset+len(cellIndices)] { + gc := gokzg4844.Cell(cell) + kzgcells = append(kzgcells, &gc) + } + + extCells, _, err := context.RecoverCellsAndComputeKZGProofs(cellIndices, kzgcells, 2) // todo + if err != nil { + return []Blob{}, err + } + + var blob Blob + for i, cell := range extCells[:64] { + copy(blob[i*len(cell):], cell[:]) + } + blobs = append(blobs, blob) + + offset = offset + len(cellIndices) } - return result, nil + + return blobs, nil } diff --git a/crypto/kzg4844/kzg4844_test.go b/crypto/kzg4844/kzg4844_test.go index f0fde35c6e..c658a600ab 100644 --- a/crypto/kzg4844/kzg4844_test.go +++ b/crypto/kzg4844/kzg4844_test.go @@ -269,18 +269,18 @@ func testVerifyPartialCells(t *testing.T, ckzg bool) { if err != nil { t.Fatalf("failed to compute cells: %v", err) } + commits = append(commits, commitments[bi]) // sample 0, 31, 63, 95 cells step := len(cells) / 4 - sampleIdx := []int{0, step - 1, 2*step - 1, 3*step - 1} - for _, idx := range sampleIdx { + indices = []uint64{0, uint64(step - 1), uint64(2*step - 1), uint64(3*step - 1)} + for _, idx := range indices { partialCells = append(partialCells, cells[idx]) partialProofs = append(partialProofs, proofs[idx]) - commits = append(commits, commitments[bi]) - indices = append(indices, uint64(idx)) } } + // t.Fatalf("length: %d %d %d %d", len(partialCells), len(commits), len(partialProofs), len(indices)) if err := VerifyCells(partialCells, commits, partialProofs, indices); err != nil { t.Fatalf("failed to verify partial cell proofs: %v", err) @@ -297,18 +297,29 @@ func testRecoverBlob(t *testing.T, ckzg bool) { defer func(old bool) { useCKZG.Store(old) }(useCKZG.Load()) useCKZG.Store(ckzg) - var blob = randBlob() - cells, err := ComputeCells([]Blob{*blob}) + blobs := []Blob{} + blobs = append(blobs, *randBlob()) + blobs = append(blobs, *randBlob()) + blobs = append(blobs, *randBlob()) + + cells, err := ComputeCells(blobs) if err != nil { t.Fatalf("failed to compute cells: %v", err) } - proof, err := ComputeCellProofs(blob) - if err != nil { - t.Fatalf("failed to compute proof: %v", err) - } - commitment, err := BlobToCommitment(blob) - if err != nil { - t.Fatalf("failed to compute commitment: %v", err) + proofs := make([]Proof, 0) + commitments := make([]Commitment, len(blobs)) + for i, blob := range blobs { + proof, err := ComputeCellProofs(&blob) + if err != nil { + t.Fatalf("failed to compute proof: %v", err) + } + proofs = append(proofs, proof...) + + commitment, err := BlobToCommitment(&blob) + if err != nil { + t.Fatalf("failed to compute commitment: %v", err) + } + commitments[i] = commitment } var ( @@ -316,18 +327,23 @@ func testRecoverBlob(t *testing.T, ckzg bool) { indices []uint64 ) - for ci, cell := range cells { - partialCells = append(partialCells, cell) + for ci := 64; ci < 128; ci++ { indices = append(indices, uint64(ci)) } - recoverBlob, err := RecoverBlob(partialCells, indices) + for i := 0; i < len(cells); i += 128 { + start := i + 64 + end := i + 128 + partialCells = append(partialCells, cells[start:end]...) + } + + recoverBlobs, err := RecoverBlobs(partialCells, indices) if err != nil { t.Fatalf("failed to recover blob: %v", err) } - if err := VerifyCellProofs([]Blob{recoverBlob}, []Commitment{commitment}, proof); err != nil { + if err := VerifyCellProofs(recoverBlobs, commitments, proofs); err != nil { t.Fatalf("failed to verify recovered blob: %v", err) } }