-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Implement all needed KZG wrappers for peerDAS in the kzg package.
#15186
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
Changes from 4 commits
25613ee
e4544ca
6eeec29
4c677e6
771a859
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,138 @@ | ||
| package kzg | ||
|
|
||
| import ( | ||
| "github.com/pkg/errors" | ||
|
|
||
| ckzg4844 "github.com/ethereum/c-kzg-4844/v2/bindings/go" | ||
| "github.com/ethereum/go-ethereum/crypto/kzg4844" | ||
| ) | ||
|
|
||
| // BytesPerBlob is the number of bytes in a single blob. | ||
| const BytesPerBlob = ckzg4844.BytesPerBlob | ||
|
|
||
| // Blob represents a serialized chunk of data. | ||
| type Blob [BytesPerBlob]byte | ||
|
|
||
| // BytesPerCell is the number of bytes in a single cell. | ||
| const BytesPerCell = ckzg4844.BytesPerCell | ||
|
|
||
| // Cell represents a chunk of an encoded Blob. | ||
| type Cell [BytesPerCell]byte | ||
|
|
||
| // Commitment represent a KZG commitment to a Blob. | ||
| type Commitment [48]byte | ||
|
|
||
| // Proof represents a KZG proof that attests to the validity of a Blob or parts of it. | ||
| type Proof [48]byte | ||
|
|
||
| // Bytes48 is a 48-byte array. | ||
| type Bytes48 = ckzg4844.Bytes48 | ||
|
|
||
| // Bytes32 is a 32-byte array. | ||
| type Bytes32 = ckzg4844.Bytes32 | ||
|
|
||
| // CellsAndProofs represents the Cells and Proofs corresponding to a single blob. | ||
| type CellsAndProofs struct { | ||
| Cells []Cell | ||
| Proofs []Proof | ||
| } | ||
|
|
||
| // BlobToKZGCommitment computes a KZG commitment from a given blob. | ||
| func BlobToKZGCommitment(blob *Blob) (Commitment, error) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I realized we dont have unit tests for functions in this file, should we have them?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I asked myself the same question. For example: // ComputeBlobKZGProof computes the blob KZG proof from a given blob and its commitment.
func ComputeBlobKZGProof(blob *Blob, commitment Commitment) (Proof, error) {
kzgBlob := kzg4844.Blob(*blob)
proof, err := kzg4844.ComputeBlobProof(&kzgBlob, kzg4844.Commitment(commitment))
if err != nil {
return [48]byte{}, err
}
return Proof(proof), nil
}does only:
Testing the wrapper itself does not add a lot of safety. However:
|
||
| kzgBlob := kzg4844.Blob(*blob) | ||
|
||
|
|
||
| commitment, err := kzg4844.BlobToCommitment(&kzgBlob) | ||
| if err != nil { | ||
| return Commitment{}, err | ||
| } | ||
|
|
||
| return Commitment(commitment), nil | ||
| } | ||
|
|
||
| // ComputeCells computes the (extended) cells from a given blob. | ||
| func ComputeCells(blob *Blob) ([]Cell, error) { | ||
| ckzgBlob := (*ckzg4844.Blob)(blob) | ||
|
|
||
| ckzgCells, err := ckzg4844.ComputeCells(ckzgBlob) | ||
| if err != nil { | ||
| return nil, errors.Wrap(err, "compute cells") | ||
| } | ||
|
|
||
| cells := make([]Cell, len(ckzgCells)) | ||
| for i := range ckzgCells { | ||
| cells[i] = Cell(ckzgCells[i]) | ||
| } | ||
|
|
||
| return cells, nil | ||
| } | ||
|
|
||
| // ComputeBlobKZGProof computes the blob KZG proof from a given blob and its commitment. | ||
| func ComputeBlobKZGProof(blob *Blob, commitment Commitment) (Proof, error) { | ||
| kzgBlob := kzg4844.Blob(*blob) | ||
|
|
||
| proof, err := kzg4844.ComputeBlobProof(&kzgBlob, kzg4844.Commitment(commitment)) | ||
| if err != nil { | ||
| return [48]byte{}, err | ||
| } | ||
| return Proof(proof), nil | ||
| } | ||
|
|
||
| // ComputeCellsAndKZGProofs computes the cells and cells KZG proofs from a given blob. | ||
| func ComputeCellsAndKZGProofs(blob *Blob) (CellsAndProofs, error) { | ||
| ckzgBlob := (*ckzg4844.Blob)(blob) | ||
|
|
||
| ckzgCells, ckzgProofs, err := ckzg4844.ComputeCellsAndKZGProofs(ckzgBlob) | ||
| if err != nil { | ||
| return CellsAndProofs{}, err | ||
| } | ||
|
|
||
| return makeCellsAndProofs(ckzgCells[:], ckzgProofs[:]) | ||
| } | ||
|
|
||
| // VerifyBlobKZGProof verifies the KZG proofs for a given slice of commitments, cells indices, cells and proofs. | ||
|
||
| // Note: It is way more efficient to call once this function with big slices than calling it multiple times with small slices. | ||
| func VerifyCellKZGProofBatch(commitmentsBytes []Bytes48, cellIndices []uint64, cells []Cell, proofsBytes []Bytes48) (bool, error) { | ||
| // Convert `Cell` type to `ckzg4844.Cell` | ||
| ckzgCells := make([]ckzg4844.Cell, len(cells)) | ||
|
|
||
| for i := range cells { | ||
| ckzgCells[i] = ckzg4844.Cell(cells[i]) | ||
| } | ||
|
|
||
| return ckzg4844.VerifyCellKZGProofBatch(commitmentsBytes, cellIndices, ckzgCells, proofsBytes) | ||
| } | ||
|
|
||
| // RecoverCellsAndKZGProofs recovers the complete cells and KZG proofs from a given set of cell indices and partial cells. | ||
| func RecoverCellsAndKZGProofs(cellIndices []uint64, partialCells []Cell) (CellsAndProofs, error) { | ||
| // Convert `Cell` type to `ckzg4844.Cell` | ||
| ckzgPartialCells := make([]ckzg4844.Cell, len(partialCells)) | ||
| for i := range partialCells { | ||
| ckzgPartialCells[i] = ckzg4844.Cell(partialCells[i]) | ||
| } | ||
|
|
||
| ckzgCells, ckzgProofs, err := ckzg4844.RecoverCellsAndKZGProofs(cellIndices, ckzgPartialCells) | ||
| if err != nil { | ||
| return CellsAndProofs{}, errors.Wrap(err, "recover cells and KZG proofs") | ||
| } | ||
|
|
||
| return makeCellsAndProofs(ckzgCells[:], ckzgProofs[:]) | ||
| } | ||
|
|
||
| // makeCellsAndProofs converts cells/proofs to the CellsAndProofs type defined in this package. | ||
| func makeCellsAndProofs(ckzgCells []ckzg4844.Cell, ckzgProofs []ckzg4844.KZGProof) (CellsAndProofs, error) { | ||
| if len(ckzgCells) != len(ckzgProofs) { | ||
| return CellsAndProofs{}, errors.New("different number of cells/proofs") | ||
| } | ||
|
|
||
| var cells []Cell | ||
| var proofs []Proof | ||
|
||
| for i := range ckzgCells { | ||
| cells = append(cells, Cell(ckzgCells[i])) | ||
| proofs = append(proofs, Proof(ckzgProofs[i])) | ||
| } | ||
|
|
||
| return CellsAndProofs{ | ||
| Cells: cells, | ||
| Proofs: proofs, | ||
| }, nil | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this package located in
blockchaininstead of a place likeconsensus-types? Curious if there’s any rationale or tradeoff behind that decisionThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new
kzg.gofile has been added here because thekzgpackage was located here.Seems Potuz created this package here.
I'm not opposed to move it elsewhere. I don't have any strong opinion on that.