mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-05-01 22:02:55 +00:00
signer/core/apitypes: add cell proofs (#32910)
Adds support for cell proofs in blob transactions in the signer --------- Co-authored-by: Gary Rong <garyrong0905@gmail.com>
This commit is contained in:
parent
cb97c48cb6
commit
a5e6a157e5
2 changed files with 218 additions and 15 deletions
|
|
@ -108,6 +108,7 @@ type SendTxArgs struct {
|
||||||
BlobHashes []common.Hash `json:"blobVersionedHashes,omitempty"`
|
BlobHashes []common.Hash `json:"blobVersionedHashes,omitempty"`
|
||||||
|
|
||||||
// For BlobTxType transactions with blob sidecar
|
// For BlobTxType transactions with blob sidecar
|
||||||
|
BlobVersion byte `json:"blobVersion,omitempty"`
|
||||||
Blobs []kzg4844.Blob `json:"blobs,omitempty"`
|
Blobs []kzg4844.Blob `json:"blobs,omitempty"`
|
||||||
Commitments []kzg4844.Commitment `json:"commitments,omitempty"`
|
Commitments []kzg4844.Commitment `json:"commitments,omitempty"`
|
||||||
Proofs []kzg4844.Proof `json:"proofs,omitempty"`
|
Proofs []kzg4844.Proof `json:"proofs,omitempty"`
|
||||||
|
|
@ -235,37 +236,58 @@ func (args *SendTxArgs) validateTxSidecar() error {
|
||||||
if args.Commitments != nil && len(args.Commitments) != n {
|
if args.Commitments != nil && len(args.Commitments) != n {
|
||||||
return fmt.Errorf("number of blobs and commitments mismatch (have=%d, want=%d)", len(args.Commitments), n)
|
return fmt.Errorf("number of blobs and commitments mismatch (have=%d, want=%d)", len(args.Commitments), n)
|
||||||
}
|
}
|
||||||
if args.Proofs != nil && len(args.Proofs) != n {
|
|
||||||
return fmt.Errorf("number of blobs and proofs mismatch (have=%d, want=%d)", len(args.Proofs), n)
|
|
||||||
}
|
|
||||||
if args.BlobHashes != nil && len(args.BlobHashes) != n {
|
if args.BlobHashes != nil && len(args.BlobHashes) != n {
|
||||||
return fmt.Errorf("number of blobs and hashes mismatch (have=%d, want=%d)", len(args.BlobHashes), n)
|
return fmt.Errorf("number of blobs and hashes mismatch (have=%d, want=%d)", len(args.BlobHashes), n)
|
||||||
}
|
}
|
||||||
|
if args.Proofs != nil {
|
||||||
|
if len(args.Proofs) == n {
|
||||||
|
// v1 transaction
|
||||||
|
for i, b := range args.Blobs {
|
||||||
|
if err := kzg4844.VerifyBlobProof(&b, args.Commitments[i], args.Proofs[i]); err != nil {
|
||||||
|
return fmt.Errorf("failed to verify blob proof: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if len(args.Proofs) == n*kzg4844.CellProofsPerBlob {
|
||||||
|
// v2 transaction
|
||||||
|
if err := kzg4844.VerifyCellProofs(args.Blobs, args.Commitments, args.Proofs); err != nil {
|
||||||
|
return fmt.Errorf("failed to verify blob proof: %v", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("number of proofs and blobs mismatch (have=%d, want=%d or %d)", len(args.Proofs), n, n*kzg4844.CellProofsPerBlob)
|
||||||
|
}
|
||||||
|
}
|
||||||
if args.Commitments == nil {
|
if args.Commitments == nil {
|
||||||
// Generate commitment and proof.
|
// Generate commitment and proof.
|
||||||
commitments := make([]kzg4844.Commitment, n)
|
commitments := make([]kzg4844.Commitment, n)
|
||||||
proofs := make([]kzg4844.Proof, n)
|
|
||||||
for i, b := range args.Blobs {
|
for i, b := range args.Blobs {
|
||||||
c, err := kzg4844.BlobToCommitment(&b)
|
c, err := kzg4844.BlobToCommitment(&b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("blobs[%d]: error computing commitment: %v", i, err)
|
return fmt.Errorf("blobs[%d]: error computing commitment: %v", i, err)
|
||||||
}
|
}
|
||||||
commitments[i] = c
|
commitments[i] = c
|
||||||
p, err := kzg4844.ComputeBlobProof(&b, c)
|
}
|
||||||
if err != nil {
|
var proofs []kzg4844.Proof
|
||||||
return fmt.Errorf("blobs[%d]: error computing proof: %v", i, err)
|
if args.BlobVersion == types.BlobSidecarVersion1 {
|
||||||
|
proofs = make([]kzg4844.Proof, 0, n*kzg4844.CellProofsPerBlob)
|
||||||
|
for i, b := range args.Blobs {
|
||||||
|
p, err := kzg4844.ComputeCellProofs(&b)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("blobs[%d]: error computing cell proof: %v", i, err)
|
||||||
|
}
|
||||||
|
proofs = append(proofs, p...)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
proofs = make([]kzg4844.Proof, 0, n)
|
||||||
|
for i, b := range args.Blobs {
|
||||||
|
p, err := kzg4844.ComputeBlobProof(&b, commitments[i])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("blobs[%d]: error computing proof: %v", i, err)
|
||||||
|
}
|
||||||
|
proofs = append(proofs, p)
|
||||||
}
|
}
|
||||||
proofs[i] = p
|
|
||||||
}
|
}
|
||||||
args.Commitments = commitments
|
args.Commitments = commitments
|
||||||
args.Proofs = proofs
|
args.Proofs = proofs
|
||||||
} else {
|
|
||||||
for i, b := range args.Blobs {
|
|
||||||
if err := kzg4844.VerifyBlobProof(&b, args.Commitments[i], args.Proofs[i]); err != nil {
|
|
||||||
return fmt.Errorf("failed to verify blob proof: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hashes := make([]common.Hash, n)
|
hashes := make([]common.Hash, n)
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
package apitypes
|
package apitypes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/rand"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
@ -229,3 +230,183 @@ func TestType_TypeName(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestValidateTxSidecar(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
// Helper function to create a test blob and its commitment/proof
|
||||||
|
createTestBlob := func() (kzg4844.Blob, kzg4844.Commitment, kzg4844.Proof, common.Hash) {
|
||||||
|
b := make([]byte, 31)
|
||||||
|
rand.Read(b)
|
||||||
|
var blob kzg4844.Blob
|
||||||
|
for i := range b {
|
||||||
|
blob[i+1] = b[i]
|
||||||
|
}
|
||||||
|
commitment, err := kzg4844.BlobToCommitment(&blob)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
proof, err := kzg4844.ComputeBlobProof(&blob, commitment)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
hash := kzg4844.CalcBlobHashV1(sha256.New(), &commitment)
|
||||||
|
return blob, commitment, proof, hash
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to create test cell proofs for v1 transactions
|
||||||
|
createTestCellProofs := func(blob kzg4844.Blob) []kzg4844.Proof {
|
||||||
|
cellProofs, err := kzg4844.ComputeCellProofs(&blob)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
return cellProofs
|
||||||
|
}
|
||||||
|
|
||||||
|
blob1, commitment1, proof1, hash1 := createTestBlob()
|
||||||
|
blob2, commitment2, proof2, hash2 := createTestBlob()
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args SendTxArgs
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "no blobs - should pass",
|
||||||
|
args: SendTxArgs{},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "valid blobs with commitments and proofs",
|
||||||
|
args: SendTxArgs{
|
||||||
|
Blobs: []kzg4844.Blob{blob1, blob2},
|
||||||
|
Commitments: []kzg4844.Commitment{commitment1, commitment2},
|
||||||
|
Proofs: []kzg4844.Proof{proof1, proof2},
|
||||||
|
BlobHashes: []common.Hash{hash1, hash2},
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "valid blobs without commitments/proofs - should generate them",
|
||||||
|
args: SendTxArgs{
|
||||||
|
Blobs: []kzg4844.Blob{blob1},
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "valid blobs with v1 cell proofs",
|
||||||
|
args: SendTxArgs{
|
||||||
|
Blobs: []kzg4844.Blob{blob1},
|
||||||
|
Commitments: []kzg4844.Commitment{commitment1},
|
||||||
|
Proofs: createTestCellProofs(blob1),
|
||||||
|
BlobHashes: []common.Hash{hash1},
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "blobs with v1 version flag - should generate cell proofs",
|
||||||
|
args: SendTxArgs{
|
||||||
|
Blobs: []kzg4844.Blob{blob1},
|
||||||
|
BlobVersion: types.BlobSidecarVersion1,
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "proofs provided but commitments not",
|
||||||
|
args: SendTxArgs{
|
||||||
|
Blobs: []kzg4844.Blob{blob1},
|
||||||
|
Proofs: []kzg4844.Proof{proof1},
|
||||||
|
},
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "commitments provided but proofs not",
|
||||||
|
args: SendTxArgs{
|
||||||
|
Blobs: []kzg4844.Blob{blob1},
|
||||||
|
Commitments: []kzg4844.Commitment{commitment1},
|
||||||
|
},
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "mismatch between blobs and commitments",
|
||||||
|
args: SendTxArgs{
|
||||||
|
Blobs: []kzg4844.Blob{blob1, blob2},
|
||||||
|
Commitments: []kzg4844.Commitment{commitment1}, // Only one commitment for two blobs
|
||||||
|
Proofs: []kzg4844.Proof{proof1},
|
||||||
|
},
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "mismatch between blobs and hashes",
|
||||||
|
args: SendTxArgs{
|
||||||
|
Blobs: []kzg4844.Blob{blob1, blob2},
|
||||||
|
Commitments: []kzg4844.Commitment{commitment1, commitment2},
|
||||||
|
Proofs: []kzg4844.Proof{proof1, proof2},
|
||||||
|
BlobHashes: []common.Hash{hash1}, // Only one hash for two blobs
|
||||||
|
},
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "wrong number of proofs",
|
||||||
|
args: SendTxArgs{
|
||||||
|
Blobs: []kzg4844.Blob{blob1, blob2},
|
||||||
|
Commitments: []kzg4844.Commitment{commitment1, commitment2},
|
||||||
|
Proofs: []kzg4844.Proof{proof1, proof2, proof1}, // 3 proofs for 2 blobs
|
||||||
|
},
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid blob hash",
|
||||||
|
args: SendTxArgs{
|
||||||
|
Blobs: []kzg4844.Blob{blob1},
|
||||||
|
Commitments: []kzg4844.Commitment{commitment1},
|
||||||
|
Proofs: []kzg4844.Proof{proof1},
|
||||||
|
BlobHashes: []common.Hash{hash2}, // Wrong hash
|
||||||
|
},
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid proof",
|
||||||
|
args: SendTxArgs{
|
||||||
|
BlobVersion: types.BlobSidecarVersion1,
|
||||||
|
Blobs: []kzg4844.Blob{blob1},
|
||||||
|
Commitments: []kzg4844.Commitment{commitment1},
|
||||||
|
Proofs: []kzg4844.Proof{proof1, proof2}, // wrong proof
|
||||||
|
BlobHashes: []common.Hash{hash1},
|
||||||
|
},
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
// Make a copy to avoid modifying the original test case
|
||||||
|
args := tt.args
|
||||||
|
err := args.validateTxSidecar()
|
||||||
|
|
||||||
|
if tt.wantErr {
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("validateTxSidecar() expected error but got none")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("validateTxSidecar() unexpected error = %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// For successful cases, verify that commitments and proofs were generated if they weren't provided
|
||||||
|
if len(args.Blobs) > 0 {
|
||||||
|
if args.Commitments == nil || len(args.Commitments) != len(args.Blobs) {
|
||||||
|
t.Errorf("validateTxSidecar() should have generated commitments")
|
||||||
|
}
|
||||||
|
if args.Proofs == nil || (len(args.Proofs) != len(args.Blobs) && len(args.Proofs) != len(args.Blobs)*kzg4844.CellProofsPerBlob) {
|
||||||
|
t.Errorf("validateTxSidecar() should have generated proofs")
|
||||||
|
}
|
||||||
|
if args.BlobHashes == nil || len(args.BlobHashes) != len(args.Blobs) {
|
||||||
|
t.Errorf("validateTxSidecar() should have generated blob hashes")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue