1
- use alloy_consensus:: TxEip1559 ;
2
- use alloy_eips:: { eip7623:: TOTAL_COST_FLOOR_PER_TOKEN , Encodable2718 } ;
3
1
use alloy_evm:: Database ;
4
2
use alloy_primitives:: {
5
3
map:: foldhash:: { HashSet , HashSetExt } ,
6
- Address , TxKind ,
4
+ Address ,
7
5
} ;
8
6
use core:: fmt:: Debug ;
9
- use op_alloy_consensus:: OpTypedTransaction ;
10
7
use op_revm:: OpTransactionError ;
11
8
use reth_evm:: { eth:: receipt_builder:: ReceiptBuilderCtx , ConfigureEvm , Evm } ;
12
9
use reth_node_api:: PayloadBuilderError ;
13
10
use reth_optimism_primitives:: OpTransactionSigned ;
14
11
use reth_primitives:: Recovered ;
15
12
use reth_provider:: { ProviderError , StateProvider } ;
16
- use reth_revm:: State ;
13
+ use reth_revm:: {
14
+ database:: StateProviderDatabase , db:: states:: bundle_state:: BundleRetention , State ,
15
+ } ;
17
16
use revm:: {
18
17
context:: result:: { EVMError , ResultAndState } ,
19
18
DatabaseCommit ,
20
19
} ;
21
20
use tracing:: { debug, warn} ;
22
21
23
- use crate :: {
24
- builders:: context:: OpPayloadBuilderCtx , primitives:: reth:: ExecutionInfo , tx_signer:: Signer ,
25
- } ;
22
+ use crate :: { builders:: context:: OpPayloadBuilderCtx , primitives:: reth:: ExecutionInfo } ;
26
23
24
+ #[ derive( Debug , Clone ) ]
27
25
pub struct BuilderTransactionCtx {
28
26
pub gas_used : u64 ,
29
27
pub da_size : u64 ,
@@ -70,20 +68,20 @@ impl From<BuilderTransactionError> for PayloadBuilderError {
70
68
}
71
69
}
72
70
73
- pub trait BuilderTransactions : Debug {
71
+ pub trait BuilderTransactions < ExtraCtx : Debug + Default = ( ) > : Debug {
74
72
fn simulate_builder_txs < Extra : Debug + Default > (
75
73
& self ,
76
74
state_provider : impl StateProvider + Clone ,
77
75
info : & mut ExecutionInfo < Extra > ,
78
- ctx : & OpPayloadBuilderCtx ,
76
+ ctx : & OpPayloadBuilderCtx < ExtraCtx > ,
79
77
db : & mut State < impl Database > ,
80
78
) -> Result < Vec < BuilderTransactionCtx > , BuilderTransactionError > ;
81
79
82
80
fn add_builder_txs < Extra : Debug + Default > (
83
81
& self ,
84
82
state_provider : impl StateProvider + Clone ,
85
83
info : & mut ExecutionInfo < Extra > ,
86
- builder_ctx : & OpPayloadBuilderCtx ,
84
+ builder_ctx : & OpPayloadBuilderCtx < ExtraCtx > ,
87
85
db : & mut State < impl Database > ,
88
86
) -> Result < ( ) , BuilderTransactionError > {
89
87
{
@@ -92,7 +90,7 @@ pub trait BuilderTransactions: Debug {
92
90
. evm_with_env ( & mut * db, builder_ctx. evm_env . clone ( ) ) ;
93
91
94
92
let mut invalid: HashSet < Address > = HashSet :: new ( ) ;
95
- // simulate builder txs on the top of block state
93
+
96
94
let builder_txs =
97
95
self . simulate_builder_txs ( state_provider, info, builder_ctx, evm. db_mut ( ) ) ?;
98
96
for builder_tx in builder_txs {
@@ -139,108 +137,33 @@ pub trait BuilderTransactions: Debug {
139
137
Ok ( ( ) )
140
138
}
141
139
}
142
- }
143
-
144
- // Scaffolding for how to construct the end of block builder transaction
145
- // This will be the regular end of block transaction without the TEE key
146
- #[ derive( Debug , Clone ) ]
147
- pub struct StandardBuilderTx {
148
- #[ allow( dead_code) ]
149
- pub signer : Option < Signer > ,
150
- }
151
-
152
- impl StandardBuilderTx {
153
- pub fn new ( signer : Option < Signer > ) -> Self {
154
- Self { signer }
155
- }
156
140
157
- pub fn simulate_builder_tx (
141
+ fn simulate_builder_txs_state < Extra : Debug + Default > (
158
142
& self ,
159
- ctx : & OpPayloadBuilderCtx ,
143
+ state_provider : impl StateProvider + Clone ,
144
+ builder_txs : Vec < & BuilderTransactionCtx > ,
145
+ ctx : & OpPayloadBuilderCtx < ExtraCtx > ,
160
146
db : & mut State < impl Database > ,
161
- ) -> Result < Option < BuilderTransactionCtx > , BuilderTransactionError > {
162
- match self . signer {
163
- Some ( signer) => {
164
- let message: Vec < u8 > = format ! ( "Block Number: {}" , ctx. block_number( ) ) . into_bytes ( ) ;
165
- let gas_used = self . estimate_builder_tx_gas ( & message) ;
166
- let signed_tx = self . signed_builder_tx ( ctx, db, signer, gas_used, message) ?;
167
- let da_size = op_alloy_flz:: tx_estimated_size_fjord_bytes (
168
- signed_tx. encoded_2718 ( ) . as_slice ( ) ,
169
- ) ;
170
- Ok ( Some ( BuilderTransactionCtx {
171
- gas_used,
172
- da_size,
173
- signed_tx,
174
- } ) )
175
- }
176
- None => Ok ( None ) ,
147
+ ) -> Result < State < StateProviderDatabase < impl StateProvider > > , BuilderTransactionError > {
148
+ let state = StateProviderDatabase :: new ( state_provider. clone ( ) ) ;
149
+ let mut simulation_state = State :: builder ( )
150
+ . with_database ( state)
151
+ . with_bundle_prestate ( db. bundle_state . clone ( ) )
152
+ . with_bundle_update ( )
153
+ . build ( ) ;
154
+ let mut evm = ctx
155
+ . evm_config
156
+ . evm_with_env ( & mut simulation_state, ctx. evm_env . clone ( ) ) ;
157
+
158
+ for builder_tx in builder_txs {
159
+ let ResultAndState { state, .. } = evm
160
+ . transact ( & builder_tx. signed_tx )
161
+ . map_err ( |err| BuilderTransactionError :: EvmExecutionError ( Box :: new ( err) ) ) ?;
162
+
163
+ evm. db_mut ( ) . commit ( state) ;
164
+ evm. db_mut ( ) . merge_transitions ( BundleRetention :: Reverts ) ;
177
165
}
178
- }
179
166
180
- fn estimate_builder_tx_gas ( & self , input : & [ u8 ] ) -> u64 {
181
- // Count zero and non-zero bytes
182
- let ( zero_bytes, nonzero_bytes) = input. iter ( ) . fold ( ( 0 , 0 ) , |( zeros, nonzeros) , & byte| {
183
- if byte == 0 {
184
- ( zeros + 1 , nonzeros)
185
- } else {
186
- ( zeros, nonzeros + 1 )
187
- }
188
- } ) ;
189
-
190
- // Calculate gas cost (4 gas per zero byte, 16 gas per non-zero byte)
191
- let zero_cost = zero_bytes * 4 ;
192
- let nonzero_cost = nonzero_bytes * 16 ;
193
-
194
- // Tx gas should be not less than floor gas https://eips.ethereum.org/EIPS/eip-7623
195
- let tokens_in_calldata = zero_bytes + nonzero_bytes * 4 ;
196
- let floor_gas = 21_000 + tokens_in_calldata * TOTAL_COST_FLOOR_PER_TOKEN ;
197
-
198
- std:: cmp:: max ( zero_cost + nonzero_cost + 21_000 , floor_gas)
199
- }
200
-
201
- fn signed_builder_tx (
202
- & self ,
203
- ctx : & OpPayloadBuilderCtx ,
204
- db : & mut State < impl Database > ,
205
- signer : Signer ,
206
- gas_used : u64 ,
207
- message : Vec < u8 > ,
208
- ) -> Result < Recovered < OpTransactionSigned > , BuilderTransactionError > {
209
- let nonce = db
210
- . load_cache_account ( signer. address )
211
- . map ( |acc| acc. account_info ( ) . unwrap_or_default ( ) . nonce )
212
- . map_err ( |_| BuilderTransactionError :: AccountLoadFailed ( signer. address ) ) ?;
213
-
214
- // Create the EIP-1559 transaction
215
- let tx = OpTypedTransaction :: Eip1559 ( TxEip1559 {
216
- chain_id : ctx. chain_id ( ) ,
217
- nonce,
218
- gas_limit : gas_used,
219
- max_fee_per_gas : ctx. base_fee ( ) . into ( ) ,
220
- max_priority_fee_per_gas : 0 ,
221
- to : TxKind :: Call ( Address :: ZERO ) ,
222
- // Include the message as part of the transaction data
223
- input : message. into ( ) ,
224
- ..Default :: default ( )
225
- } ) ;
226
- // Sign the transaction
227
- let builder_tx = signer
228
- . sign_tx ( tx)
229
- . map_err ( BuilderTransactionError :: SigningError ) ?;
230
-
231
- Ok ( builder_tx)
232
- }
233
- }
234
-
235
- impl BuilderTransactions for StandardBuilderTx {
236
- fn simulate_builder_txs < Extra : Debug + Default > (
237
- & self ,
238
- _state_provider : impl StateProvider + Clone ,
239
- _info : & mut ExecutionInfo < Extra > ,
240
- ctx : & OpPayloadBuilderCtx ,
241
- db : & mut State < impl Database > ,
242
- ) -> Result < Vec < BuilderTransactionCtx > , BuilderTransactionError > {
243
- let builder_tx = self . simulate_builder_tx ( ctx, db) ?;
244
- Ok ( builder_tx. into_iter ( ) . collect ( ) )
167
+ Ok ( simulation_state)
245
168
}
246
169
}
0 commit comments