11use std:: ops:: AddAssign ;
22
33use crate :: serde_utils;
4+ #[ cfg( feature = "c-kzg" ) ]
5+ use crate :: types:: Fork ;
46use crate :: types:: constants:: VERSIONED_HASH_VERSION_KZG ;
57use crate :: { Bytes , H256 } ;
68
@@ -80,23 +82,34 @@ impl BlobsBundle {
8082
8183 // In the future we might want to provide a new method that calculates the commitments and proofs using the following.
8284 #[ cfg( feature = "c-kzg" ) ]
83- pub fn create_from_blobs ( blobs : & Vec < Blob > ) -> Result < Self , BlobsBundleError > {
84- use ethrex_crypto:: kzg:: blob_to_kzg_commitment_and_proof;
85+ pub fn create_from_blobs (
86+ blobs : & Vec < Blob > ,
87+ wrapper_version : Option < u8 > ,
88+ ) -> Result < Self , BlobsBundleError > {
89+ use ethrex_crypto:: kzg:: {
90+ blob_to_commitment_and_cell_proofs, blob_to_kzg_commitment_and_proof,
91+ } ;
8592 let mut commitments = Vec :: new ( ) ;
8693 let mut proofs = Vec :: new ( ) ;
8794
8895 // Populate the commitments and proofs
8996 for blob in blobs {
90- let ( commitment, proof) = blob_to_kzg_commitment_and_proof ( blob) ?;
91- commitments. push ( commitment) ;
92- proofs. push ( proof) ;
97+ if wrapper_version. unwrap_or ( 0 ) == 0 {
98+ let ( commitment, proof) = blob_to_kzg_commitment_and_proof ( blob) ?;
99+ commitments. push ( commitment) ;
100+ proofs. push ( proof) ;
101+ } else {
102+ let ( commitment, cell_proofs) = blob_to_commitment_and_cell_proofs ( blob) ?;
103+ commitments. push ( commitment) ;
104+ proofs. extend ( cell_proofs) ;
105+ }
93106 }
94107
95108 Ok ( Self {
96109 blobs : blobs. clone ( ) ,
97110 commitments,
98111 proofs,
99- version : 0 ,
112+ version : wrapper_version . unwrap_or ( 0 ) ,
100113 } )
101114 }
102115
@@ -127,6 +140,10 @@ impl BlobsBundle {
127140 return Err ( BlobsBundleError :: BlobBundleEmptyError ) ;
128141 }
129142
143+ if self . version == 0 && fork >= Fork :: Osaka || self . version != 0 && fork < Fork :: Osaka {
144+ return Err ( BlobsBundleError :: InvalidBlobVersionForFork ) ;
145+ }
146+
130147 // Check if the blob versioned hashes and blobs bundle content length mismatch
131148 if blob_count != self . commitments . len ( )
132149 || ( self . version == 0 && blob_count != self . proofs . len ( ) )
@@ -231,6 +248,8 @@ pub enum BlobsBundleError {
231248 BlobToCommitmentAndProofError ,
232249 #[ error( "Max blobs per block exceeded" ) ]
233250 MaxBlobsExceeded ,
251+ #[ error( "Invalid blob version for the current fork" ) ]
252+ InvalidBlobVersionForFork ,
234253 #[ cfg( feature = "c-kzg" ) ]
235254 #[ error( "KZG related error: {0}" ) ]
236255 Kzg ( #[ from] ethrex_crypto:: kzg:: KzgError ) ,
@@ -259,7 +278,7 @@ mod tests {
259278 } )
260279 . collect ( ) ;
261280
262- let blobs_bundle = crate :: types:: BlobsBundle :: create_from_blobs ( & blobs)
281+ let blobs_bundle = crate :: types:: BlobsBundle :: create_from_blobs ( & blobs, None )
263282 . expect ( "Failed to create blobs bundle" ) ;
264283
265284 let blob_versioned_hashes = blobs_bundle. generate_versioned_hashes ( ) ;
@@ -284,6 +303,78 @@ mod tests {
284303 ) ) ;
285304 }
286305
306+ #[ test]
307+ #[ cfg( feature = "c-kzg" ) ]
308+ fn transaction_with_valid_blobs_should_pass_on_osaka ( ) {
309+ let blobs = vec ! [ "Hello, world!" . as_bytes( ) , "Goodbye, world!" . as_bytes( ) ]
310+ . into_iter ( )
311+ . map ( |data| {
312+ crate :: types:: blobs_bundle:: blob_from_bytes ( data. into ( ) )
313+ . expect ( "Failed to create blob" )
314+ } )
315+ . collect ( ) ;
316+
317+ let blobs_bundle = crate :: types:: BlobsBundle :: create_from_blobs ( & blobs, Some ( 1 ) )
318+ . expect ( "Failed to create blobs bundle" ) ;
319+
320+ let blob_versioned_hashes = blobs_bundle. generate_versioned_hashes ( ) ;
321+
322+ let tx = crate :: types:: transaction:: EIP4844Transaction {
323+ nonce : 3 ,
324+ max_priority_fee_per_gas : 0 ,
325+ max_fee_per_gas : 0 ,
326+ max_fee_per_blob_gas : 0 . into ( ) ,
327+ gas : 15_000_000 ,
328+ to : crate :: Address :: from_low_u64_be ( 1 ) , // Normal tx
329+ value : crate :: U256 :: zero ( ) , // Value zero
330+ data : crate :: Bytes :: default ( ) , // No data
331+ access_list : Default :: default ( ) , // No access list
332+ blob_versioned_hashes,
333+ ..Default :: default ( )
334+ } ;
335+
336+ assert ! ( matches!(
337+ blobs_bundle. validate( & tx, crate :: types:: Fork :: Osaka ) ,
338+ Ok ( ( ) )
339+ ) ) ;
340+ }
341+
342+ #[ test]
343+ #[ cfg( feature = "c-kzg" ) ]
344+ fn transaction_with_invalid_fork_should_fail ( ) {
345+ let blobs = vec ! [ "Hello, world!" . as_bytes( ) , "Goodbye, world!" . as_bytes( ) ]
346+ . into_iter ( )
347+ . map ( |data| {
348+ crate :: types:: blobs_bundle:: blob_from_bytes ( data. into ( ) )
349+ . expect ( "Failed to create blob" )
350+ } )
351+ . collect ( ) ;
352+
353+ let blobs_bundle = crate :: types:: BlobsBundle :: create_from_blobs ( & blobs, Some ( 1 ) )
354+ . expect ( "Failed to create blobs bundle" ) ;
355+
356+ let blob_versioned_hashes = blobs_bundle. generate_versioned_hashes ( ) ;
357+
358+ let tx = crate :: types:: transaction:: EIP4844Transaction {
359+ nonce : 3 ,
360+ max_priority_fee_per_gas : 0 ,
361+ max_fee_per_gas : 0 ,
362+ max_fee_per_blob_gas : 0 . into ( ) ,
363+ gas : 15_000_000 ,
364+ to : crate :: Address :: from_low_u64_be ( 1 ) , // Normal tx
365+ value : crate :: U256 :: zero ( ) , // Value zero
366+ data : crate :: Bytes :: default ( ) , // No data
367+ access_list : Default :: default ( ) , // No access list
368+ blob_versioned_hashes,
369+ ..Default :: default ( )
370+ } ;
371+
372+ assert ! ( !matches!(
373+ blobs_bundle. validate( & tx, crate :: types:: Fork :: Prague ) ,
374+ Ok ( ( ) )
375+ ) ) ;
376+ }
377+
287378 #[ test]
288379 #[ cfg( feature = "c-kzg" ) ]
289380 fn transaction_with_invalid_proofs_should_fail ( ) {
@@ -396,7 +487,7 @@ mod tests {
396487 let blobs =
397488 std:: iter:: repeat_n ( blob, super :: MAX_BLOB_COUNT_ELECTRA + 1 ) . collect :: < Vec < _ > > ( ) ;
398489
399- let blobs_bundle = crate :: types:: BlobsBundle :: create_from_blobs ( & blobs)
490+ let blobs_bundle = crate :: types:: BlobsBundle :: create_from_blobs ( & blobs, None )
400491 . expect ( "Failed to create blobs bundle" ) ;
401492
402493 let blob_versioned_hashes = blobs_bundle. generate_versioned_hashes ( ) ;
0 commit comments