web3-proxy/web3_proxy/src/config.rs

166 lines
5.3 KiB
Rust
Raw Normal View History

use crate::rpcs::blockchain::BlockHashesCache;
2022-08-26 20:26:17 +03:00
use crate::rpcs::connection::Web3Connection;
2022-09-09 06:53:16 +03:00
use crate::rpcs::request::OpenRequestHandleMetrics;
2022-08-30 23:01:42 +03:00
use crate::{app::AnyhowJoinHandle, rpcs::blockchain::ArcBlock};
2022-05-06 00:25:40 +03:00
use argh::FromArgs;
2022-07-23 02:26:04 +03:00
use derive_more::Constructor;
2022-08-30 23:01:42 +03:00
use ethers::prelude::TxHash;
2022-07-23 02:26:04 +03:00
use hashbrown::HashMap;
2022-09-23 01:10:28 +03:00
use sea_orm::DatabaseConnection;
2022-05-05 22:07:09 +03:00
use serde::Deserialize;
use std::sync::Arc;
2022-06-29 22:15:05 +03:00
use tokio::sync::broadcast;
2022-05-05 22:07:09 +03:00
pub type BlockAndRpc = (Option<ArcBlock>, Arc<Web3Connection>);
2022-08-30 23:01:42 +03:00
pub type TxHashAndRpc = (TxHash, Arc<Web3Connection>);
2022-07-22 08:11:26 +03:00
2022-05-22 02:34:05 +03:00
#[derive(Debug, FromArgs)]
2022-08-06 08:46:33 +03:00
/// Web3_proxy is a fast caching and load balancing proxy for web3 (Ethereum or similar) JsonRPC servers.
2022-05-06 00:25:40 +03:00
pub struct CliConfig {
/// path to a toml of rpc servers
#[argh(option, default = "\"./config/development.toml\".to_string()")]
pub config: String,
2022-05-06 00:25:40 +03:00
/// what port the proxy should listen on
2022-05-06 09:33:29 +03:00
#[argh(option, default = "8544")]
2022-05-18 23:28:00 +03:00
pub port: u16,
2022-05-06 00:25:40 +03:00
/// what port the proxy should expose prometheus stats on
#[argh(option, default = "8543")]
pub prometheus_port: u16,
2022-06-06 01:39:44 +03:00
/// number of worker threads. Defaults to the number of logical processors
2022-05-18 19:35:06 +03:00
#[argh(option, default = "0")]
2022-05-18 23:28:00 +03:00
pub workers: usize,
2022-05-06 00:25:40 +03:00
}
2022-05-22 02:34:05 +03:00
#[derive(Debug, Deserialize)]
2022-08-12 22:07:14 +03:00
pub struct TopConfig {
pub app: AppConfig,
2022-05-13 23:50:11 +03:00
pub balanced_rpcs: HashMap<String, Web3ConnectionConfig>,
2022-05-06 01:21:27 +03:00
pub private_rpcs: Option<HashMap<String, Web3ConnectionConfig>>,
2022-05-05 22:07:09 +03:00
}
2022-05-12 21:49:57 +03:00
/// shared configuration between Web3Connections
2022-09-02 23:16:20 +03:00
#[derive(Debug, Default, Deserialize)]
2022-08-12 22:07:14 +03:00
pub struct AppConfig {
// TODO: better type for chain_id? max of `u64::MAX / 2 - 36` https://github.com/ethereum/EIPs/issues/2294
pub chain_id: u64,
2022-07-26 07:53:38 +03:00
pub db_url: Option<String>,
2022-09-02 23:16:20 +03:00
/// minimum size of the connection pool for the database
2022-09-06 23:50:37 +03:00
/// If none, the number of workers are used
pub db_min_connections: Option<u32>,
2022-09-02 23:16:20 +03:00
/// minimum size of the connection pool for the database
2022-09-06 23:50:37 +03:00
/// If none, the minimum * 2 is used
2022-09-02 23:16:20 +03:00
pub db_max_connections: Option<u32>,
pub influxdb_url: Option<String>,
2022-08-27 08:42:25 +03:00
#[serde(default = "default_default_requests_per_minute")]
pub default_requests_per_minute: u64,
2022-09-02 23:16:20 +03:00
pub invite_code: Option<String>,
2022-08-27 06:11:58 +03:00
#[serde(default = "default_min_sum_soft_limit")]
pub min_sum_soft_limit: u32,
2022-08-27 03:33:45 +03:00
#[serde(default = "default_min_synced_rpcs")]
pub min_synced_rpcs: usize,
2022-09-02 23:16:20 +03:00
/// Set to 0 to block all anonymous requests
2022-07-22 22:30:39 +03:00
#[serde(default = "default_public_rate_limit_per_minute")]
pub public_rate_limit_per_minute: u64,
2022-09-02 23:16:20 +03:00
pub redis_url: Option<String>,
/// maximum size of the connection pool for the cache
2022-09-06 23:50:37 +03:00
/// If none, the minimum * 2 is used
2022-09-14 09:18:13 +03:00
pub redis_max_connections: Option<usize>,
2022-07-22 22:30:39 +03:00
#[serde(default = "default_response_cache_max_bytes")]
pub response_cache_max_bytes: usize,
2022-08-12 22:07:14 +03:00
/// the stats page url for an anonymous user.
pub redirect_public_url: String,
2022-09-05 09:29:27 +03:00
/// the stats page url for a logged in user. it must contain "{user_id}"
2022-08-12 22:07:14 +03:00
pub redirect_user_url: String,
2022-07-22 22:30:39 +03:00
}
/// default to unlimited requests
/// TODO: pick a lower limit so we don't get DOSd
fn default_default_requests_per_minute() -> u64 {
u64::MAX
2022-08-27 08:42:25 +03:00
}
2022-08-27 06:11:58 +03:00
fn default_min_sum_soft_limit() -> u32 {
2022-08-27 03:33:45 +03:00
1
}
fn default_min_synced_rpcs() -> usize {
2022-08-27 06:11:58 +03:00
1
}
/// 0 blocks public requests by default.
fn default_public_rate_limit_per_minute() -> u64 {
2022-07-22 22:30:39 +03:00
0
}
fn default_response_cache_max_bytes() -> usize {
// TODO: default to some percentage of the system?
// 100 megabytes
10_usize.pow(8)
2022-05-12 21:49:57 +03:00
}
2022-07-23 02:26:04 +03:00
#[derive(Debug, Deserialize, Constructor)]
2022-05-05 22:07:09 +03:00
pub struct Web3ConnectionConfig {
url: String,
soft_limit: u32,
hard_limit: Option<u64>,
2022-08-08 22:57:54 +03:00
weight: u32,
2022-09-02 23:16:20 +03:00
subscribe_txs: Option<bool>,
2022-05-05 22:07:09 +03:00
}
impl Web3ConnectionConfig {
2022-05-12 08:54:27 +03:00
/// Create a Web3Connection from config
2022-08-30 23:01:42 +03:00
/// TODO: move this into Web3Connection (just need to make things pub(crate))
2022-08-10 08:56:09 +03:00
#[allow(clippy::too_many_arguments)]
2022-06-14 08:43:28 +03:00
pub async fn spawn(
2022-05-05 22:07:09 +03:00
self,
2022-08-10 08:56:09 +03:00
name: String,
2022-09-15 20:57:24 +03:00
redis_pool: Option<redis_rate_limiter::RedisPool>,
chain_id: u64,
http_client: Option<reqwest::Client>,
2022-06-29 22:15:05 +03:00
http_interval_sender: Option<Arc<broadcast::Sender<()>>>,
block_map: BlockHashesCache,
2022-07-22 08:11:26 +03:00
block_sender: Option<flume::Sender<BlockAndRpc>>,
2022-08-30 23:01:42 +03:00
tx_id_sender: Option<flume::Sender<TxHashAndRpc>>,
2022-09-09 06:53:16 +03:00
open_request_handle_metrics: Arc<OpenRequestHandleMetrics>,
2022-09-23 01:10:28 +03:00
db_conn: Option<DatabaseConnection>,
2022-06-14 08:43:28 +03:00
) -> anyhow::Result<(Arc<Web3Connection>, AnyhowJoinHandle<()>)> {
let hard_limit = match (self.hard_limit, redis_pool) {
2022-07-25 22:03:19 +03:00
(None, None) => None,
(Some(hard_limit), Some(redis_client_pool)) => Some((hard_limit, redis_client_pool)),
(None, Some(_)) => None,
2022-07-26 07:53:38 +03:00
(Some(_hard_limit), None) => {
2022-07-25 22:03:19 +03:00
return Err(anyhow::anyhow!(
"no redis client pool! needed for hard limit"
))
}
};
2022-05-22 02:34:05 +03:00
2022-09-02 23:16:20 +03:00
let tx_id_sender = if self.subscribe_txs.unwrap_or(false) {
tx_id_sender
} else {
None
};
Web3Connection::spawn(
2022-08-10 08:56:09 +03:00
name,
2022-05-12 21:49:57 +03:00
chain_id,
2022-05-05 22:07:09 +03:00
self.url,
http_client,
2022-06-29 22:15:05 +03:00
http_interval_sender,
2022-07-25 22:03:19 +03:00
hard_limit,
2022-05-05 22:07:09 +03:00
self.soft_limit,
2022-08-26 20:26:17 +03:00
block_map,
2022-06-14 08:43:28 +03:00
block_sender,
tx_id_sender,
2022-06-29 22:15:05 +03:00
true,
2022-08-08 22:57:54 +03:00
self.weight,
2022-09-09 06:53:16 +03:00
open_request_handle_metrics,
2022-09-23 01:10:28 +03:00
db_conn,
2022-05-05 22:07:09 +03:00
)
.await
}
}