Skip to content

Commit ff6e518

Browse files
crypto/kzg4844: verify cell proofs (#31815)
1 parent f203dfc commit ff6e518

File tree

6 files changed

+136
-8
lines changed

6 files changed

+136
-8
lines changed

core/txpool/validation.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,9 @@ func validateBlobSidecarOsaka(hashes []common.Hash, sidecar *types.BlobTxSidecar
202202
if len(sidecar.Blobs) != len(hashes) {
203203
return fmt.Errorf("invalid number of %d blobs compared to %d blob hashes", len(sidecar.Blobs), len(hashes))
204204
}
205+
if len(sidecar.Commitments) != len(hashes) {
206+
return fmt.Errorf("invalid number of %d commitments compared to %d blob hashes", len(sidecar.Commitments), len(hashes))
207+
}
205208
if len(sidecar.Proofs) != len(hashes)*kzg4844.CellProofsPerBlob {
206209
return fmt.Errorf("invalid number of %d blob proofs expected %d", len(sidecar.Proofs), len(hashes)*kzg4844.CellProofsPerBlob)
207210
}
@@ -210,14 +213,13 @@ func validateBlobSidecarOsaka(hashes []common.Hash, sidecar *types.BlobTxSidecar
210213
}
211214
// Blob commitments match with the hashes in the transaction, verify the
212215
// blobs themselves via KZG
213-
for i := range sidecar.Blobs {
214-
// TODO verify the cell proof here
215-
_ = i
216-
/*
217-
if err := kzg4844.VerifyBlobProof(&sidecar.Blobs[i], sidecar.Commitments[i], sidecar.Proofs[i]); err != nil {
218-
return fmt.Errorf("invalid blob %d: %v", i, err)
219-
}
220-
*/
216+
var blobs []*kzg4844.Blob
217+
for _, blob := range sidecar.Blobs {
218+
blobs = append(blobs, &blob)
219+
}
220+
221+
if err := kzg4844.VerifyCellProofs(blobs, sidecar.Commitments, sidecar.Proofs); err != nil {
222+
return err
221223
}
222224
return nil
223225
}

crypto/kzg4844/kzg4844.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,16 @@ func VerifyBlobProof(blob *Blob, commitment Commitment, proof Proof) error {
155155
return gokzgVerifyBlobProof(blob, commitment, proof)
156156
}
157157

158+
// VerifyCellProofs verifies a batch of proofs corresponding to the blobs and commitments.
159+
// Expects length of blobs and commitments to be equal.
160+
// Expects length of proofs be 128 * length of blobs.
161+
func VerifyCellProofs(blobs []*Blob, commitments []Commitment, proofs []Proof) error {
162+
if useCKZG.Load() {
163+
return ckzgVerifyCellProofBatch(blobs, commitments, proofs)
164+
}
165+
return gokzgVerifyCellProofBatch(blobs, commitments, proofs)
166+
}
167+
158168
// ComputeCellProofs returns the KZG cell proofs that are used to verify the blob against
159169
// the commitment.
160170
//

crypto/kzg4844/kzg4844_ckzg_cgo.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,3 +149,44 @@ func ckzgComputeCellProofs(blob *Blob) ([]Proof, error) {
149149
}
150150
return p, nil
151151
}
152+
153+
// ckzgVerifyCellProofs verifies that the blob data corresponds to the provided commitment.
154+
func ckzgVerifyCellProofBatch(blobs []*Blob, commitments []Commitment, cellProofs []Proof) error {
155+
ckzgIniter.Do(ckzgInit)
156+
var (
157+
proofs = make([]ckzg4844.Bytes48, len(cellProofs))
158+
commits = make([]ckzg4844.Bytes48, 0, len(cellProofs))
159+
cellIndices = make([]uint64, 0, len(cellProofs))
160+
cells = make([]ckzg4844.Cell, 0, len(cellProofs))
161+
)
162+
// Copy over the cell proofs
163+
for i, proof := range cellProofs {
164+
proofs[i] = (ckzg4844.Bytes48)(proof)
165+
}
166+
// Blow up the commitments to be the same length as the proofs
167+
for _, commitment := range commitments {
168+
for range gokzg4844.CellsPerExtBlob {
169+
commits = append(commits, (ckzg4844.Bytes48)(commitment))
170+
}
171+
}
172+
// Compute the cells and cell indices
173+
for _, blob := range blobs {
174+
cellsI, err := ckzg4844.ComputeCells((*ckzg4844.Blob)(blob))
175+
if err != nil {
176+
return err
177+
}
178+
cells = append(cells, cellsI[:]...)
179+
for idx := range len(cellsI) {
180+
cellIndices = append(cellIndices, uint64(idx))
181+
}
182+
}
183+
184+
valid, err := ckzg4844.VerifyCellKZGProofBatch(commits, cellIndices, cells, proofs)
185+
if err != nil {
186+
return err
187+
}
188+
if !valid {
189+
return errors.New("invalid proof")
190+
}
191+
return nil
192+
}

crypto/kzg4844/kzg4844_ckzg_nocgo.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ func ckzgVerifyBlobProof(blob *Blob, commitment Commitment, proof Proof) error {
6161
panic("unsupported platform")
6262
}
6363

64+
// ckzgVerifyCellProofBatch verifies that the blob data corresponds to the provided commitment.
65+
func ckzgVerifyCellProofBatch(blobs []*Blob, commitments []Commitment, proof []Proof) error {
66+
panic("unsupported platform")
67+
}
68+
6469
// ckzgComputeCellProofs returns the KZG cell proofs that are used to verify the blob against
6570
// the commitment.
6671
//

crypto/kzg4844/kzg4844_gokzg.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,37 @@ func gokzgComputeCellProofs(blob *Blob) ([]Proof, error) {
114114
}
115115
return p, nil
116116
}
117+
118+
// gokzgVerifyCellProofs verifies that the blob data corresponds to the provided commitment.
119+
func gokzgVerifyCellProofBatch(blobs []*Blob, commitments []Commitment, cellProofs []Proof) error {
120+
gokzgIniter.Do(gokzgInit)
121+
122+
var (
123+
proofs = make([]gokzg4844.KZGProof, len(cellProofs))
124+
commits = make([]gokzg4844.KZGCommitment, 0, len(cellProofs))
125+
cellIndices = make([]uint64, 0, len(cellProofs))
126+
cells = make([]*gokzg4844.Cell, 0, len(cellProofs))
127+
)
128+
// Copy over the cell proofs
129+
for i, proof := range cellProofs {
130+
proofs[i] = gokzg4844.KZGProof(proof)
131+
}
132+
// Blow up the commitments to be the same length as the proofs
133+
for _, commitment := range commitments {
134+
for range gokzg4844.CellsPerExtBlob {
135+
commits = append(commits, gokzg4844.KZGCommitment(commitment))
136+
}
137+
}
138+
// Compute the cell and cell indices
139+
for _, blob := range blobs {
140+
cellsI, err := context.ComputeCells((*gokzg4844.Blob)(blob), 2)
141+
if err != nil {
142+
return err
143+
}
144+
cells = append(cells, cellsI[:]...)
145+
for idx := range len(cellsI) {
146+
cellIndices = append(cellIndices, uint64(idx))
147+
}
148+
}
149+
return context.VerifyCellKZGProofBatch(commits, cellIndices, cells[:], proofs)
150+
}

crypto/kzg4844/kzg4844_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,3 +193,39 @@ func benchmarkVerifyBlobProof(b *testing.B, ckzg bool) {
193193
VerifyBlobProof(blob, commitment, proof)
194194
}
195195
}
196+
197+
func TestCKZGCells(t *testing.T) { testKZGCells(t, true) }
198+
func TestGoKZGCells(t *testing.T) { testKZGCells(t, false) }
199+
func testKZGCells(t *testing.T, ckzg bool) {
200+
if ckzg && !ckzgAvailable {
201+
t.Skip("CKZG unavailable in this test build")
202+
}
203+
defer func(old bool) { useCKZG.Store(old) }(useCKZG.Load())
204+
useCKZG.Store(ckzg)
205+
206+
blob1 := randBlob()
207+
blob2 := randBlob()
208+
209+
commitment1, err := BlobToCommitment(blob1)
210+
if err != nil {
211+
t.Fatalf("failed to create KZG commitment from blob: %v", err)
212+
}
213+
commitment2, err := BlobToCommitment(blob2)
214+
if err != nil {
215+
t.Fatalf("failed to create KZG commitment from blob: %v", err)
216+
}
217+
218+
proofs1, err := ComputeCellProofs(blob1)
219+
if err != nil {
220+
t.Fatalf("failed to create KZG proof at point: %v", err)
221+
}
222+
223+
proofs2, err := ComputeCellProofs(blob2)
224+
if err != nil {
225+
t.Fatalf("failed to create KZG proof at point: %v", err)
226+
}
227+
proofs := append(proofs1, proofs2...)
228+
if err := VerifyCellProofs([]*Blob{blob1, blob2}, []Commitment{commitment1, commitment2}, proofs); err != nil {
229+
t.Fatalf("failed to verify KZG proof at point: %v", err)
230+
}
231+
}

0 commit comments

Comments
 (0)