@@ -10,7 +10,6 @@ import (
1010 "github.com/ethereum/go-ethereum/common/hexutil"
1111 "github.com/ethereum/go-ethereum/crypto/kzg"
1212 "github.com/ethereum/go-ethereum/params"
13- "github.com/protolambda/go-kzg/bls"
1413 "github.com/protolambda/ztyp/codec"
1514 "github.com/protolambda/ztyp/tree"
1615)
@@ -103,6 +102,7 @@ func (p *KZGProof) UnmarshalText(text []byte) error {
103102 return hexutil .UnmarshalFixedText ("KZGProof" , text , p [:])
104103}
105104
105+ // BLSFieldElement is the raw bytes representation of a field element
106106type BLSFieldElement [32 ]byte
107107
108108func (p BLSFieldElement ) MarshalText () ([]byte , error ) {
@@ -120,6 +120,16 @@ func (p *BLSFieldElement) UnmarshalText(text []byte) error {
120120// Blob data
121121type Blob [params .FieldElementsPerBlob ]BLSFieldElement
122122
123+ // kzg.Blob interface
124+ func (blob Blob ) Len () int {
125+ return len (blob )
126+ }
127+
128+ // kzg.Blob interface
129+ func (blob Blob ) At (i int ) [32 ]byte {
130+ return [32 ]byte (blob [i ])
131+ }
132+
123133func (blob * Blob ) Deserialize (dr * codec.DecodingReader ) error {
124134 if blob == nil {
125135 return errors .New ("cannot decode ssz into nil Blob" )
@@ -156,17 +166,6 @@ func (blob *Blob) HashTreeRoot(hFn tree.HashFn) tree.Root {
156166 }, params .FieldElementsPerBlob )
157167}
158168
159- // Convert a blob to kzg.Blob
160- func (blob * Blob ) ToKZGBlob () (kzg.Blob , bool ) {
161- frs := make ([]bls.Fr , len (blob ))
162- for i , elem := range blob {
163- if ! bls .FrFrom32 (& frs [i ], elem ) {
164- return []bls.Fr {}, false
165- }
166- }
167- return kzg .Blob (frs ), true
168- }
169-
170169func (blob * Blob ) MarshalText () ([]byte , error ) {
171170 out := make ([]byte , 2 + params .FieldElementsPerBlob * 32 * 2 )
172171 copy (out [:2 ], "0x" )
@@ -209,6 +208,15 @@ func (blob *Blob) UnmarshalText(text []byte) error {
209208
210209type BlobKzgs []KZGCommitment
211210
211+ // kzg.KZGCommitmentSequence interface
212+ func (bk BlobKzgs ) Len () int {
213+ return len (bk )
214+ }
215+
216+ func (bk BlobKzgs ) At (i int ) kzg.KZGCommitment {
217+ return kzg .KZGCommitment (bk [i ])
218+ }
219+
212220func (li * BlobKzgs ) Deserialize (dr * codec.DecodingReader ) error {
213221 return dr .List (func () codec.Deserializable {
214222 i := len (* li )
@@ -227,7 +235,7 @@ func (li BlobKzgs) ByteLength() uint64 {
227235 return uint64 (len (li )) * 48
228236}
229237
230- func (li * BlobKzgs ) FixedLength () uint64 {
238+ func (li BlobKzgs ) FixedLength () uint64 {
231239 return 0
232240}
233241
@@ -245,17 +253,14 @@ func (li BlobKzgs) copy() BlobKzgs {
245253
246254type Blobs []Blob
247255
248- // Extract the crypto material underlying these blobs
249- func (blobs Blobs ) toKZGBlobSequence () ([][]bls.Fr , bool ) {
250- out := make ([][]bls.Fr , len (blobs ))
251- for i , b := range blobs {
252- blob , ok := b .ToKZGBlob ()
253- if ! ok {
254- return nil , false
255- }
256- out [i ] = blob
257- }
258- return out , true
256+ // kzg.BlobSequence interface
257+ func (blobs Blobs ) Len () int {
258+ return len (blobs )
259+ }
260+
261+ // kzg.BlobSequence interface
262+ func (blobs Blobs ) At (i int ) kzg.Blob {
263+ return blobs [i ]
259264}
260265
261266func (a * Blobs ) Deserialize (dr * codec.DecodingReader ) error {
@@ -301,42 +306,21 @@ func (blobs Blobs) ComputeCommitmentsAndAggregatedProof() (commitments []KZGComm
301306 commitments = make ([]KZGCommitment , len (blobs ))
302307 versionedHashes = make ([]common.Hash , len (blobs ))
303308 for i , blob := range blobs {
304- frs , ok := blob . ToKZGBlob ( )
309+ c , ok := kzg . BlobToKZGCommitment ( blob )
305310 if ! ok {
306- return nil , nil , KZGProof {}, errors .New ("invalid blob for commitment" )
311+ return nil , nil , KZGProof {}, errors .New ("could not convert blob to commitment" )
307312 }
308- commitments [i ] = KZGCommitment (kzg . BlobToKZGCommitment ( frs ) )
309- versionedHashes [i ] = common .Hash (kzg .KZGToVersionedHash (kzg . KZGCommitment ( commitments [ i ]) ))
313+ commitments [i ] = KZGCommitment (c )
314+ versionedHashes [i ] = common .Hash (kzg .KZGToVersionedHash (c ))
310315 }
311316
312317 var kzgProof KZGProof
313318 if len (blobs ) != 0 {
314- aggregatePoly , aggregateCommitmentG1 , err := computeAggregateKzgCommitment (blobs , commitments )
319+ proof , err := kzg . ComputeAggregateKZGProof (blobs )
315320 if err != nil {
316321 return nil , nil , KZGProof {}, err
317322 }
318-
319- var aggregateCommitment KZGCommitment
320- copy (aggregateCommitment [:], bls .ToCompressedG1 (aggregateCommitmentG1 ))
321-
322- var aggregateBlob Blob
323- for i := range aggregatePoly {
324- aggregateBlob [i ] = bls .FrTo32 (& aggregatePoly [i ])
325- }
326- sum , err := sszHash (& PolynomialAndCommitment {aggregateBlob , aggregateCommitment })
327- if err != nil {
328- return nil , nil , KZGProof {}, err
329- }
330- z := kzg .BytesToBLSField (sum )
331-
332- var y bls.Fr
333- kzg .EvaluatePolyInEvaluationForm (& y , aggregatePoly [:], z )
334-
335- aggProofG1 , err := kzg .ComputeProof (aggregatePoly , z )
336- if err != nil {
337- return nil , nil , KZGProof {}, err
338- }
339- copy (kzgProof [:], bls .ToCompressedG1 (aggProofG1 ))
323+ kzgProof = KZGProof (proof )
340324 }
341325
342326 return commitments , versionedHashes , kzgProof , nil
@@ -363,27 +347,6 @@ func (b *BlobsAndCommitments) FixedLength() uint64 {
363347 return 0
364348}
365349
366- type PolynomialAndCommitment struct {
367- b Blob
368- c KZGCommitment
369- }
370-
371- func (p * PolynomialAndCommitment ) HashTreeRoot (hFn tree.HashFn ) tree.Root {
372- return hFn .HashTreeRoot (& p .b , & p .c )
373- }
374-
375- func (p * PolynomialAndCommitment ) Serialize (w * codec.EncodingWriter ) error {
376- return w .Container (& p .b , & p .c )
377- }
378-
379- func (p * PolynomialAndCommitment ) ByteLength () uint64 {
380- return codec .ContainerLength (& p .b , & p .c )
381- }
382-
383- func (p * PolynomialAndCommitment ) FixedLength () uint64 {
384- return 0
385- }
386-
387350type BlobTxWrapper struct {
388351 Tx SignedBlobTx
389352 BlobKzgs BlobKzgs
@@ -421,19 +384,30 @@ func (b *BlobTxWrapData) sizeWrapData() common.StorageSize {
421384 return common .StorageSize (4 + 4 + b .BlobKzgs .ByteLength () + b .Blobs .ByteLength () + b .KzgAggregatedProof .ByteLength ())
422385}
423386
424- func (b * BlobTxWrapData ) verifyVersionedHash (inner TxData ) error {
387+ // validateBlobTransactionWrapper implements validate_blob_transaction_wrapper from EIP-4844
388+ func (b * BlobTxWrapData ) validateBlobTransactionWrapper (inner TxData ) error {
425389 blobTx , ok := inner .(* SignedBlobTx )
426390 if ! ok {
427391 return fmt .Errorf ("expected signed blob tx, got %T" , inner )
428392 }
429- if a , b := len (blobTx .Message .BlobVersionedHashes ), params .MaxBlobsPerBlock ; a > b {
430- return fmt .Errorf ("too many blobs in blob tx, got %d, expected no more than %d" , a , b )
393+ l1 := len (b .BlobKzgs )
394+ l2 := len (blobTx .Message .BlobVersionedHashes )
395+ l3 := len (b .Blobs )
396+ if l1 != l2 || l2 != l3 {
397+ return fmt .Errorf ("lengths don't match %v %v %v" , l1 , l2 , l3 )
431398 }
432- if a , b := len (b .BlobKzgs ), len (b .Blobs ); a != b {
433- return fmt .Errorf ("expected equal amount but got %d kzgs and %d blobs" , a , b )
399+ // the following check isn't strictly necessary as it would be caught by data gas processing
400+ // (and hence it is not explicitly in the spec for this function), but it doesn't hurt to fail
401+ // early in case we are getting spammed with too many blobs or there is a bug somewhere:
402+ if l1 > params .MaxBlobsPerBlock {
403+ return fmt .Errorf ("number of blobs exceeds max: %v" , l1 )
434404 }
435- if a , b := len (b .BlobKzgs ), len (blobTx .Message .BlobVersionedHashes ); a != b {
436- return fmt .Errorf ("expected equal amount but got %d kzgs and %d versioned hashes" , a , b )
405+ ok , err := kzg .VerifyAggregateKZGProof (b .Blobs , b .BlobKzgs , kzg .KZGProof (b .KzgAggregatedProof ))
406+ if err != nil {
407+ return fmt .Errorf ("error during proof verification: %v" , err )
408+ }
409+ if ! ok {
410+ return errors .New ("failed to verify kzg" )
437411 }
438412 for i , h := range blobTx .Message .BlobVersionedHashes {
439413 if computed := b .BlobKzgs [i ].ComputeVersionedHash (); computed != h {
@@ -443,41 +417,6 @@ func (b *BlobTxWrapData) verifyVersionedHash(inner TxData) error {
443417 return nil
444418}
445419
446- // Blob verification using KZG proofs
447- func (b * BlobTxWrapData ) verifyBlobs (inner TxData ) error {
448- if err := b .verifyVersionedHash (inner ); err != nil {
449- return err
450- }
451-
452- aggregatePoly , aggregateCommitmentG1 , err := computeAggregateKzgCommitment (b .Blobs , b .BlobKzgs )
453- if err != nil {
454- return fmt .Errorf ("failed to compute aggregate commitment: %v" , err )
455- }
456- var aggregateBlob Blob
457- for i := range aggregatePoly {
458- aggregateBlob [i ] = bls .FrTo32 (& aggregatePoly [i ])
459- }
460- var aggregateCommitment KZGCommitment
461- copy (aggregateCommitment [:], bls .ToCompressedG1 (aggregateCommitmentG1 ))
462- sum , err := sszHash (& PolynomialAndCommitment {aggregateBlob , aggregateCommitment })
463- if err != nil {
464- return err
465- }
466- z := kzg .BytesToBLSField (sum )
467-
468- var y bls.Fr
469- kzg .EvaluatePolyInEvaluationForm (& y , aggregatePoly [:], z )
470-
471- aggregateProofG1 , err := bls .FromCompressedG1 (b .KzgAggregatedProof [:])
472- if err != nil {
473- return fmt .Errorf ("aggregate proof parse error: %v" , err )
474- }
475- if ! kzg .VerifyKZGProofFromPoints (aggregateCommitmentG1 , z , & y , aggregateProofG1 ) {
476- return errors .New ("failed to verify kzg" )
477- }
478- return nil
479- }
480-
481420func (b * BlobTxWrapData ) copy () TxWrapData {
482421 return & BlobTxWrapData {
483422 BlobKzgs : b .BlobKzgs .copy (),
@@ -514,33 +453,3 @@ func (b *BlobTxWrapData) encodeTyped(w io.Writer, txdata TxData) error {
514453 }
515454 return EncodeSSZ (w , & wrapped )
516455}
517-
518- func computeAggregateKzgCommitment (blobs Blobs , commitments []KZGCommitment ) ([]bls.Fr , * bls.G1Point , error ) {
519- // create challenges
520- sum , err := sszHash (& BlobsAndCommitments {blobs , commitments })
521- if err != nil {
522- return nil , nil , err
523- }
524- r := kzg .BytesToBLSField (sum )
525-
526- powers := kzg .ComputePowers (r , len (blobs ))
527-
528- commitmentsG1 := make ([]bls.G1Point , len (commitments ))
529- for i := 0 ; i < len (commitmentsG1 ); i ++ {
530- p , _ := bls .FromCompressedG1 (commitments [i ][:])
531- bls .CopyG1 (& commitmentsG1 [i ], p )
532- }
533- aggregateCommitmentG1 := bls .LinCombG1 (commitmentsG1 , powers )
534- var aggregateCommitment KZGCommitment
535- copy (aggregateCommitment [:], bls .ToCompressedG1 (aggregateCommitmentG1 ))
536-
537- polys , ok := blobs .toKZGBlobSequence ()
538- if ! ok {
539- return nil , nil , err
540- }
541- aggregatePoly , err := bls .PolyLinComb (polys , powers )
542- if err != nil {
543- return nil , nil , err
544- }
545- return aggregatePoly , aggregateCommitmentG1 , nil
546- }
0 commit comments