Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions signer/core/apitypes/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,12 +231,13 @@ func (args *SendTxArgs) validateTxSidecar() error {
}

// len(blobs) == len(commitments) == len(proofs) == len(hashes)
// Note: proofs can be either 1:1 (Version 0) or 128:1 cell proofs (Version 1)
n := len(args.Blobs)
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)
}
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.Proofs != nil && len(args.Proofs) != n && len(args.Proofs) != n*kzg4844.CellProofsPerBlob {
return fmt.Errorf("number of blobs and proofs mismatch (have=%d, want=%d or %d)", len(args.Proofs), n, n*kzg4844.CellProofsPerBlob)
}
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)
Expand All @@ -261,9 +262,18 @@ func (args *SendTxArgs) validateTxSidecar() error {
args.Commitments = commitments
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)
// Verify proofs: either 1:1 blob proofs (Version 0) or 128:1 cell proofs (Version 1)
if len(args.Proofs) == n*kzg4844.CellProofsPerBlob {
// Version 1: Cell proofs - verify all at once
if err := kzg4844.VerifyCellProofs(args.Blobs, args.Commitments, args.Proofs); err != nil {
return fmt.Errorf("failed to verify cell proofs: %v", err)
}
} else {
// Version 0: Blob proofs - verify individually
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)
}
}
}
}
Expand Down
70 changes: 70 additions & 0 deletions signer/core/apitypes/types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ package apitypes
import (
"crypto/sha256"
"encoding/json"
"math/big"
"testing"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/holiman/uint256"
Expand Down Expand Up @@ -139,6 +141,74 @@ func TestBlobTxs(t *testing.T) {
t.Logf("tx %v", string(data))
}

func TestBlobTxsWithCellProofs(t *testing.T) {
blob := kzg4844.Blob{0x1}
commitment, err := kzg4844.BlobToCommitment(&blob)
if err != nil {
t.Fatal(err)
}

// Generate cell proofs (128 proofs per blob) instead of a single blob proof
cellProofs, err := kzg4844.ComputeCellProofs(&blob)
if err != nil {
t.Fatal(err)
}

// Verify we got the expected number of cell proofs
if len(cellProofs) != kzg4844.CellProofsPerBlob {
t.Fatalf("expected %d cell proofs, got %d", kzg4844.CellProofsPerBlob, len(cellProofs))
}

// Test that SendTxArgs accepts cell proofs and converts to Version 1 sidecar
hash := kzg4844.CalcBlobHashV1(sha256.New(), &commitment)
args := &SendTxArgs{
From: common.MixedcaseAddress{},
To: &common.MixedcaseAddress{},
Gas: 21000,
MaxFeePerGas: (*hexutil.Big)(big.NewInt(600)),
MaxPriorityFeePerGas: (*hexutil.Big)(big.NewInt(500)),
BlobFeeCap: (*hexutil.Big)(big.NewInt(700)),
Value: hexutil.Big(*big.NewInt(100)),
Nonce: 8,
ChainID: (*hexutil.Big)(big.NewInt(6)),
BlobHashes: []common.Hash{hash},
Blobs: []kzg4844.Blob{blob},
Commitments: []kzg4844.Commitment{commitment},
Proofs: cellProofs,
}

// This should succeed with the validation fix
tx, err := args.ToTransaction()
if err != nil {
t.Fatalf("failed to convert args with cell proofs to transaction: %v", err)
}

// Verify the transaction type is BlobTx
if tx.Type() != types.BlobTxType {
t.Fatalf("expected BlobTxType, got %d", tx.Type())
}

// Verify the transaction has a Version 1 sidecar
sidecar := tx.BlobTxSidecar()
if sidecar == nil {
t.Fatal("expected sidecar to be present")
}
if sidecar.Version != types.BlobSidecarVersion1 {
t.Fatalf("expected sidecar version %d, got %d", types.BlobSidecarVersion1, sidecar.Version)
}

// Verify the sidecar has the correct number of proofs
if len(sidecar.Proofs) != len(cellProofs) {
t.Fatalf("expected %d proofs in sidecar, got %d", len(cellProofs), len(sidecar.Proofs))
}

data, err := json.Marshal(tx)
if err != nil {
t.Fatal(err)
}
t.Logf("cell proof tx %v", string(data))
}

func TestType_IsArray(t *testing.T) {
t.Parallel()
// Expected positives
Expand Down
Loading