1
1
//! App to benchmark/test the tx block execution.
2
2
//! This only works when reth node is stopped and the chain moved forward from its synced state
3
3
//! It downloads block after the last one synced and re-executes all the txs in it.
4
+ use alloy_consensus:: TxEnvelope ;
5
+ use alloy_eips:: Decodable2718 ;
4
6
use alloy_provider:: Provider ;
5
7
use clap:: Parser ;
6
8
use eyre:: Context ;
@@ -11,9 +13,11 @@ use rbuilder::{
11
13
PartialBlock , PartialBlockFork , ThreadBlockBuildingContext ,
12
14
} ,
13
15
live_builder:: { base_config:: load_config_toml_and_env, cli:: LiveBuilderConfig , config:: Config } ,
16
+ mev_boost:: submission:: SubmitBlockRequest ,
14
17
provider:: StateProviderFactory ,
15
18
utils:: { extract_onchain_block_txs, find_suggested_fee_recipient, http_provider, Signer } ,
16
19
} ;
20
+ use reth_primitives_traits:: SignerRecoverable ;
17
21
use reth_provider:: StateProvider ;
18
22
use std:: { path:: PathBuf , sync:: Arc , time:: Instant } ;
19
23
use tracing:: { debug, info} ;
@@ -31,6 +35,11 @@ struct Cli {
31
35
rpc_url : String ,
32
36
#[ clap( long, help = "Config file path" , env = "RBUILDER_CONFIG" ) ]
33
37
config : PathBuf ,
38
+ #[ clap(
39
+ long,
40
+ help = "Path to submit block request to replay to use instead of the onchain block"
41
+ ) ]
42
+ submit_block_request_json : Option < PathBuf > ,
34
43
}
35
44
36
45
#[ tokio:: main]
@@ -54,6 +63,15 @@ async fn main() -> eyre::Result<()> {
54
63
. await ?
55
64
. ok_or_else ( || eyre:: eyre!( "block not found on rpc" ) ) ?;
56
65
66
+ let onchain_block = if let Some ( submit_block_request_json) = cli. submit_block_request_json {
67
+ let mut block = read_execution_payload_from_json ( submit_block_request_json) ?;
68
+ // without parent_beacon_block_root we can't build block and its not available in submit_block_request_json
69
+ block. header . parent_beacon_block_root = onchain_block. header . parent_beacon_block_root ;
70
+ block
71
+ } else {
72
+ onchain_block
73
+ } ;
74
+
57
75
let txs = extract_onchain_block_txs ( & onchain_block) ?;
58
76
let suggested_fee_recipient = find_suggested_fee_recipient ( & onchain_block, & txs) ;
59
77
info ! (
@@ -99,15 +117,19 @@ async fn main() -> eyre::Result<()> {
99
117
100
118
let build_time = Instant :: now ( ) ;
101
119
120
+ partial_block. pre_block_call ( & ctx, & mut local_ctx, & mut state) ?;
121
+
102
122
let mut space_state = BlockBuildingSpaceState :: ZERO ;
103
123
for ( idx, tx) in txs. into_iter ( ) . enumerate ( ) {
104
124
let result = {
105
125
let mut fork = PartialBlockFork :: new ( & mut state, & ctx, & mut local_ctx) ;
126
+
106
127
fork. commit_tx ( & tx, space_state) ?. with_context ( || {
107
128
format ! ( "Failed to commit tx: {} {:?}" , idx, tx. hash( ) )
108
129
} ) ?
109
130
} ;
110
131
space_state. use_space ( result. space_used ( ) ) ;
132
+ partial_block. executed_tx_infos . push ( result. tx_info ) ;
111
133
}
112
134
113
135
let build_time = build_time. elapsed ( ) ;
@@ -140,6 +162,27 @@ async fn main() -> eyre::Result<()> {
140
162
Ok ( ( ) )
141
163
}
142
164
165
+ fn read_execution_payload_from_json ( path : PathBuf ) -> eyre:: Result < alloy_rpc_types:: Block > {
166
+ let req = std:: fs:: read_to_string ( & path) ?;
167
+ let req: SubmitBlockRequest = serde_json:: from_str ( & req) ?;
168
+ let block_raw = match req {
169
+ SubmitBlockRequest :: Capella ( req) => req. execution_payload . clone ( ) . into_block_raw ( ) ?,
170
+ SubmitBlockRequest :: Fulu ( req) => req. execution_payload . clone ( ) . into_block_raw ( ) ?,
171
+ SubmitBlockRequest :: Deneb ( req) => req. execution_payload . clone ( ) . into_block_raw ( ) ?,
172
+ SubmitBlockRequest :: Electra ( req) => req. execution_payload . clone ( ) . into_block_raw ( ) ?,
173
+ } ;
174
+ let rpc_block = alloy_rpc_types:: Block :: from_consensus ( block_raw, None ) ;
175
+ let rpc_block = rpc_block. try_map_transactions ( |bytes| -> eyre:: Result < _ > {
176
+ let envelope = TxEnvelope :: decode_2718 ( & mut bytes. as_ref ( ) ) ?;
177
+ let recovered = envelope. try_into_recovered ( ) ?;
178
+ Ok ( alloy_rpc_types:: Transaction :: from_transaction (
179
+ recovered,
180
+ alloy_rpc_types:: TransactionInfo :: default ( ) ,
181
+ ) )
182
+ } ) ?;
183
+ Ok ( rpc_block)
184
+ }
185
+
143
186
fn report_time_data ( action : & str , data : & [ u128 ] ) {
144
187
let mean = data. iter ( ) . sum :: < u128 > ( ) as f64 / data. len ( ) as f64 ;
145
188
let median = * data. iter ( ) . sorted ( ) . nth ( data. len ( ) / 2 ) . unwrap ( ) ;
0 commit comments