@@ -8,9 +8,10 @@ use crate::eth::{
8
8
} ;
9
9
use jsonrpsee:: core:: RpcResult ;
10
10
use reth_primitives:: {
11
+ constants:: eip4844:: MAINNET_KZG_TRUSTED_SETUP ,
11
12
keccak256,
12
13
revm_primitives:: db:: { DatabaseCommit , DatabaseRef } ,
13
- U256 ,
14
+ PooledTransactionsElement , U256 ,
14
15
} ;
15
16
use reth_revm:: database:: StateProviderDatabase ;
16
17
use reth_rpc_api:: EthCallBundleApiServer ;
@@ -20,7 +21,7 @@ use revm::{
20
21
db:: CacheDB ,
21
22
primitives:: { ResultAndState , TxEnv } ,
22
23
} ;
23
- use revm_primitives:: EnvWithHandlerCfg ;
24
+ use revm_primitives:: { EnvWithHandlerCfg , MAX_BLOB_GAS_PER_BLOCK } ;
24
25
use std:: sync:: Arc ;
25
26
26
27
/// `Eth` bundle implementation.
57
58
) )
58
59
}
59
60
60
- let transactions =
61
- txs. into_iter ( ) . map ( recover_raw_transaction) . collect :: < Result < Vec < _ > , _ > > ( ) ?;
61
+ let transactions = txs
62
+ . into_iter ( )
63
+ . map ( recover_raw_transaction)
64
+ . collect :: < Result < Vec < _ > , _ > > ( ) ?
65
+ . into_iter ( )
66
+ . map ( |tx| tx. into_components ( ) )
67
+ . collect :: < Vec < _ > > ( ) ;
68
+
69
+ // Validate that the bundle does not contain more than MAX_BLOB_NUMBER_PER_BLOCK blob
70
+ // transactions.
71
+ if transactions
72
+ . iter ( )
73
+ . filter_map ( |( tx, _) | {
74
+ if let PooledTransactionsElement :: BlobTransaction ( tx) = tx {
75
+ Some ( tx. transaction . blob_gas ( ) )
76
+ } else {
77
+ None
78
+ }
79
+ } )
80
+ . sum :: < u64 > ( ) >
81
+ MAX_BLOB_GAS_PER_BLOCK
82
+ {
83
+ return Err ( EthApiError :: InvalidParams (
84
+ EthBundleError :: Eip4844BlobGasExceeded . to_string ( ) ,
85
+ ) ) ;
86
+ }
87
+
62
88
let block_id: reth_rpc_types:: BlockId = state_block_number. into ( ) ;
63
89
let ( cfg, mut block_env, at) = self . inner . eth_api . evm_env_at ( block_id) . await ?;
64
90
@@ -96,8 +122,16 @@ where
96
122
let mut results = Vec :: with_capacity ( transactions. len ( ) ) ;
97
123
let mut transactions = transactions. into_iter ( ) . peekable ( ) ;
98
124
99
- while let Some ( tx) = transactions. next ( ) {
100
- let tx = tx. into_ecrecovered_transaction ( ) ;
125
+ while let Some ( ( tx, signer) ) = transactions. next ( ) {
126
+ // Verify that the given blob data, commitments, and proofs are all valid for
127
+ // this transaction.
128
+ if let PooledTransactionsElement :: BlobTransaction ( ref tx) = tx {
129
+ tx. validate ( MAINNET_KZG_TRUSTED_SETUP . as_ref ( ) )
130
+ . map_err ( |e| EthApiError :: InvalidParams ( e. to_string ( ) ) ) ?;
131
+ }
132
+
133
+ let tx = tx. into_ecrecovered_transaction ( signer) ;
134
+
101
135
hash_bytes. extend_from_slice ( tx. hash ( ) . as_slice ( ) ) ;
102
136
let gas_price = tx
103
137
. effective_tip_per_gas ( basefee)
@@ -217,4 +251,8 @@ pub enum EthBundleError {
217
251
/// Thrown if the bundle does not contain a block number, or block number is 0.
218
252
#[ error( "bundle missing blockNumber" ) ]
219
253
BundleMissingBlockNumber ,
254
+ /// Thrown when the blob gas usage of the blob transactions in a bundle exceed
255
+ /// [MAX_BLOB_GAS_PER_BLOCK].
256
+ #[ error( "blob gas usage exceeds the limit of {MAX_BLOB_GAS_PER_BLOCK} gas per block." ) ]
257
+ Eip4844BlobGasExceeded ,
220
258
}
0 commit comments