Skip to content

Commit 3159c3f

Browse files
authored
Generic provider (#218)
Closes #216 Replaces all concrete usage of `ProviderFactory` and `ProviderFactoryReopener` with generics bounded by [reth provider traits](https://github.com/paradigmxyz/reth/blob/661b260f6172c047e8530e2331b2c84141e03c2b/crates/storage/provider/src/traits/full.rs#L14-L24). This allows running rbuilder in-process using a node provider and eases swapping to a more modern provider like `BlockchainProvider` in the future. Note that not all trait methods can be implemented because `ProviderFactoryReopener` has no access to the blockchain tree (pending state etc.). ## DB Consistency Checks Consistency checks have been moved out of the rbuilder core into the trait implementation for `ProviderFactoryReopener`. Inside the trait implementation, the current head block number is not known, so the reopener cannot assume that the state of the block given - 256 blocks will be available. To not redundantly re-check the consistency of the same block, `ProviderFactoryReopener` tracks the last block verified to have consistent state and will only re-check it when it changes. This adds 1 additional read per provider call to get the head of the chain, however I believe the cost will be insignificant.
1 parent d96e721 commit 3159c3f

File tree

31 files changed

+827
-471
lines changed

31 files changed

+827
-471
lines changed

crates/rbuilder/src/backtest/backtest_build_block.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@
88
use ahash::HashMap;
99
use alloy_primitives::utils::format_ether;
1010

11-
use crate::backtest::restore_landed_orders::{
12-
restore_landed_orders, sim_historical_block, ExecutedBlockTx, ExecutedTxs, SimplifiedOrder,
13-
};
14-
use crate::backtest::OrdersWithTimestamp;
1511
use crate::{
1612
backtest::{
1713
execute::{backtest_prepare_ctx_for_block, BacktestBlockInput},
18-
BlockData, HistoricalDataStorage,
14+
restore_landed_orders::{
15+
restore_landed_orders, sim_historical_block, ExecutedBlockTx, ExecutedTxs,
16+
SimplifiedOrder,
17+
},
18+
BlockData, HistoricalDataStorage, OrdersWithTimestamp,
1919
},
2020
building::builders::BacktestSimulateBlockInput,
2121
live_builder::{base_config::load_config_toml_and_env, cli::LiveBuilderConfig},
@@ -58,7 +58,10 @@ struct Cli {
5858
block: u64,
5959
}
6060

61-
pub async fn run_backtest_build_block<ConfigType: LiveBuilderConfig>() -> eyre::Result<()> {
61+
pub async fn run_backtest_build_block<ConfigType>() -> eyre::Result<()>
62+
where
63+
ConfigType: LiveBuilderConfig,
64+
{
6265
let cli = Cli::parse();
6366

6467
let config: ConfigType = load_config_toml_and_env(cli.config)?;
@@ -85,10 +88,7 @@ pub async fn run_backtest_build_block<ConfigType: LiveBuilderConfig>() -> eyre::
8588
print_order_and_timestamp(&block_data.available_orders, &block_data);
8689
}
8790

88-
let provider_factory = config
89-
.base_config()
90-
.provider_factory()?
91-
.provider_factory_unchecked();
91+
let provider_factory = config.base_config().create_provider_factory()?;
9292
let chain_spec = config.base_config().chain_spec()?;
9393
let sbundle_mergeabe_signers = config.base_config().sbundle_mergeabe_signers();
9494

@@ -126,7 +126,7 @@ pub async fn run_backtest_build_block<ConfigType: LiveBuilderConfig>() -> eyre::
126126
builder_name: builder_name.clone(),
127127
sbundle_mergeabe_signers: sbundle_mergeabe_signers.clone(),
128128
sim_orders: &sim_orders,
129-
provider_factory: provider_factory.clone(),
129+
provider: provider_factory.clone(),
130130
cached_reads: None,
131131
};
132132
let build_res = config.build_backtest_block(builder_name, input);

crates/rbuilder/src/backtest/backtest_build_range.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ use clap::Parser;
2424
use rayon::prelude::*;
2525
use std::{
2626
fs::File,
27-
io,
28-
io::Write,
27+
io::{self, Write},
2928
path::{Path, PathBuf},
3029
};
3130
use time::format_description::well_known::Rfc3339;
@@ -63,8 +62,10 @@ struct Cli {
6362
blocks: Vec<u64>,
6463
}
6564

66-
pub async fn run_backtest_build_range<ConfigType: LiveBuilderConfig + Send + Sync>(
67-
) -> eyre::Result<()> {
65+
pub async fn run_backtest_build_range<ConfigType>() -> eyre::Result<()>
66+
where
67+
ConfigType: LiveBuilderConfig,
68+
{
6869
let cli = Cli::parse();
6970

7071
if cli.store_backtest && cli.compare_backtest {
@@ -110,10 +111,7 @@ pub async fn run_backtest_build_range<ConfigType: LiveBuilderConfig + Send + Syn
110111
result
111112
};
112113

113-
let provider_factory = config
114-
.base_config()
115-
.provider_factory()?
116-
.provider_factory_unchecked();
114+
let provider_factory = config.base_config().create_provider_factory()?;
117115
let chain_spec = config.base_config().chain_spec()?;
118116

119117
let mut profits = Vec::new();

crates/rbuilder/src/backtest/execute.rs

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,19 @@
1-
use crate::primitives::OrderId;
2-
use crate::utils::Signer;
31
use crate::{
42
backtest::BlockData,
53
building::{
64
builders::BacktestSimulateBlockInput, sim::simulate_all_orders_with_sim_tree,
75
BlockBuildingContext, BundleErr, OrderErr, TransactionErr,
86
},
97
live_builder::cli::LiveBuilderConfig,
10-
primitives::SimulatedOrder,
11-
utils::clean_extradata,
8+
primitives::{OrderId, SimulatedOrder},
9+
utils::{clean_extradata, Signer},
1210
};
1311
use ahash::HashSet;
1412
use alloy_primitives::{Address, U256};
15-
use reth::providers::ProviderFactory;
1613
use reth_chainspec::ChainSpec;
17-
use reth_db::{database::Database, DatabaseEnv};
14+
use reth_db::Database;
1815
use reth_payload_builder::database::CachedReads;
16+
use reth_provider::{DatabaseProviderFactory, HeaderProvider, StateProviderFactory};
1917
use serde::{Deserialize, Serialize};
2018
use std::sync::Arc;
2119

@@ -57,14 +55,17 @@ pub struct BacktestBlockInput {
5755
pub sim_errors: Vec<OrderErr>,
5856
}
5957

60-
pub fn backtest_prepare_ctx_for_block<DB: Database + Clone>(
58+
pub fn backtest_prepare_ctx_for_block<P>(
6159
block_data: BlockData,
62-
provider_factory: ProviderFactory<DB>,
60+
provider: P,
6361
chain_spec: Arc<ChainSpec>,
6462
build_block_lag_ms: i64,
6563
blocklist: HashSet<Address>,
6664
builder_signer: Signer,
67-
) -> eyre::Result<BacktestBlockInput> {
65+
) -> eyre::Result<BacktestBlockInput>
66+
where
67+
P: StateProviderFactory + Clone + 'static,
68+
{
6869
let orders = block_data
6970
.available_orders
7071
.iter()
@@ -87,7 +88,7 @@ pub fn backtest_prepare_ctx_for_block<DB: Database + Clone>(
8788
Some(builder_signer),
8889
);
8990
let (sim_orders, sim_errors) =
90-
simulate_all_orders_with_sim_tree(provider_factory.clone(), &ctx, &orders, false)?;
91+
simulate_all_orders_with_sim_tree(provider.clone(), &ctx, &orders, false)?;
9192
Ok(BacktestBlockInput {
9293
ctx,
9394
sim_orders,
@@ -96,23 +97,28 @@ pub fn backtest_prepare_ctx_for_block<DB: Database + Clone>(
9697
}
9798

9899
#[allow(clippy::too_many_arguments)]
99-
pub fn backtest_simulate_block<ConfigType: LiveBuilderConfig>(
100+
pub fn backtest_simulate_block<P, DB, ConfigType>(
100101
block_data: BlockData,
101-
provider_factory: ProviderFactory<Arc<DatabaseEnv>>,
102+
provider: P,
102103
chain_spec: Arc<ChainSpec>,
103104
build_block_lag_ms: i64,
104105
builders_names: Vec<String>,
105106
config: &ConfigType,
106107
blocklist: HashSet<Address>,
107108
sbundle_mergeabe_signers: &[Address],
108-
) -> eyre::Result<BlockBacktestValue> {
109+
) -> eyre::Result<BlockBacktestValue>
110+
where
111+
DB: Database + Clone + 'static,
112+
P: DatabaseProviderFactory<DB> + StateProviderFactory + HeaderProvider + Clone + 'static,
113+
ConfigType: LiveBuilderConfig,
114+
{
109115
let BacktestBlockInput {
110116
ctx,
111117
sim_orders,
112118
sim_errors,
113119
} = backtest_prepare_ctx_for_block(
114120
block_data.clone(),
115-
provider_factory.clone(),
121+
provider.clone(),
116122
chain_spec.clone(),
117123
build_block_lag_ms,
118124
blocklist,
@@ -158,7 +164,7 @@ pub fn backtest_simulate_block<ConfigType: LiveBuilderConfig>(
158164
builder_name: building_algorithm_name.clone(),
159165
sbundle_mergeabe_signers: sbundle_mergeabe_signers.to_vec(),
160166
sim_orders: &sim_orders,
161-
provider_factory: provider_factory.clone(),
167+
provider: provider.clone(),
162168
cached_reads,
163169
};
164170

crates/rbuilder/src/backtest/redistribute/cli/mod.rs

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
mod csv_output;
22

3-
use crate::backtest::redistribute::{calc_redistributions, RedistributionBlockOutput};
4-
use crate::backtest::BlockData;
5-
use crate::live_builder::base_config::load_config_toml_and_env;
6-
use crate::live_builder::cli::LiveBuilderConfig;
7-
use crate::{backtest::HistoricalDataStorage, live_builder::config::Config};
3+
use crate::{
4+
backtest::{
5+
redistribute::{calc_redistributions, RedistributionBlockOutput},
6+
BlockData, HistoricalDataStorage,
7+
},
8+
live_builder::{base_config::load_config_toml_and_env, cli::LiveBuilderConfig},
9+
};
810
use alloy_primitives::utils::format_ether;
911
use clap::Parser;
1012
use csv_output::{CSVOutputRow, CSVResultWriter};
11-
use reth_db::DatabaseEnv;
12-
use reth_provider::ProviderFactory;
13-
use std::io;
14-
use std::path::PathBuf;
15-
use std::sync::Arc;
13+
use reth_db::Database;
14+
use reth_provider::{DatabaseProviderFactory, HeaderProvider, StateProviderFactory};
15+
use std::{io, path::PathBuf};
1616
use tracing::info;
1717

1818
#[derive(Parser, Debug)]
@@ -45,19 +45,19 @@ enum Commands {
4545
},
4646
}
4747

48-
pub async fn run_backtest_redistribute<ConfigType: LiveBuilderConfig>() -> eyre::Result<()> {
48+
pub async fn run_backtest_redistribute<ConfigType>() -> eyre::Result<()>
49+
where
50+
ConfigType: LiveBuilderConfig,
51+
{
4952
let cli = Cli::parse();
5053

51-
let config: Config = load_config_toml_and_env(cli.config)?;
52-
config.base_config.setup_tracing_subsriber()?;
54+
let config: ConfigType = load_config_toml_and_env(cli.config)?;
55+
config.base_config().setup_tracing_subsriber()?;
5356

5457
let mut historical_data_storage =
55-
HistoricalDataStorage::new_from_path(&config.base_config.backtest_fetch_output_file)
58+
HistoricalDataStorage::new_from_path(&config.base_config().backtest_fetch_output_file)
5659
.await?;
57-
let provider_factory = config
58-
.base_config
59-
.provider_factory()?
60-
.provider_factory_unchecked();
60+
let provider = config.base_config().create_provider_factory()?;
6161
let mut csv_writer = cli
6262
.csv
6363
.map(|path| -> io::Result<_> { CSVResultWriter::new(path) })
@@ -74,7 +74,7 @@ pub async fn run_backtest_redistribute<ConfigType: LiveBuilderConfig>() -> eyre:
7474
block_data,
7575
csv_writer.as_mut(),
7676
json_accum.as_mut(),
77-
provider_factory.clone(),
77+
provider.clone(),
7878
&config,
7979
cli.distribute_to_mempool_txs,
8080
)?;
@@ -91,7 +91,7 @@ pub async fn run_backtest_redistribute<ConfigType: LiveBuilderConfig>() -> eyre:
9191
block_data,
9292
csv_writer.as_mut(),
9393
json_accum.as_mut(),
94-
provider_factory.clone(),
94+
provider.clone(),
9595
&config,
9696
cli.distribute_to_mempool_txs,
9797
)?;
@@ -107,19 +107,24 @@ pub async fn run_backtest_redistribute<ConfigType: LiveBuilderConfig>() -> eyre:
107107
Ok(())
108108
}
109109

110-
fn process_redisribution<ConfigType: LiveBuilderConfig + Send + Sync>(
110+
fn process_redisribution<P, DB, ConfigType>(
111111
block_data: BlockData,
112112
csv_writer: Option<&mut CSVResultWriter>,
113113
json_accum: Option<&mut Vec<RedistributionBlockOutput>>,
114-
provider_factory: ProviderFactory<Arc<DatabaseEnv>>,
114+
provider: P,
115115
config: &ConfigType,
116116
distribute_to_mempool_txs: bool,
117-
) -> eyre::Result<()> {
117+
) -> eyre::Result<()>
118+
where
119+
DB: Database + Clone + 'static,
120+
P: DatabaseProviderFactory<DB> + StateProviderFactory + HeaderProvider + Clone + 'static,
121+
ConfigType: LiveBuilderConfig,
122+
{
118123
let block_number = block_data.block_number;
119124
let block_hash = block_data.onchain_block.header.hash;
120125
info!(block_number, "Calculating redistribution for a block");
121126
let redistribution_values = match calc_redistributions(
122-
provider_factory.clone(),
127+
provider.clone(),
123128
config,
124129
block_data,
125130
distribute_to_mempool_txs,

0 commit comments

Comments
 (0)