test fixture
This commit is contained in:
parent
8cfbbfe1b3
commit
a440d51377
|
@ -1457,6 +1457,17 @@ dependencies = [
|
||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "derivative"
|
||||||
|
version = "2.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "derive_more"
|
name = "derive_more"
|
||||||
version = "0.99.17"
|
version = "0.99.17"
|
||||||
|
@ -6919,6 +6930,7 @@ dependencies = [
|
||||||
"console-subscriber",
|
"console-subscriber",
|
||||||
"counter",
|
"counter",
|
||||||
"deferred-rate-limiter",
|
"deferred-rate-limiter",
|
||||||
|
"derivative",
|
||||||
"derive_more",
|
"derive_more",
|
||||||
"entities",
|
"entities",
|
||||||
"ethbloom",
|
"ethbloom",
|
||||||
|
|
|
@ -41,6 +41,12 @@ Start the server with the defaults (listen on `http://localhost:8544` and use `.
|
||||||
cargo run --release -- proxyd
|
cargo run --release -- proxyd
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Quickly run tests:
|
||||||
|
|
||||||
|
```
|
||||||
|
RUST_LOG=web3_proxy=trace,info cargo nextest run
|
||||||
|
```
|
||||||
|
|
||||||
## Common commands
|
## Common commands
|
||||||
|
|
||||||
Create a user:
|
Create a user:
|
||||||
|
|
|
@ -103,6 +103,7 @@ tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||||
ulid = { version = "1.0.0", features = ["rand", "uuid", "serde"] }
|
ulid = { version = "1.0.0", features = ["rand", "uuid", "serde"] }
|
||||||
url = { version = "2.4.0", features = ["serde"] }
|
url = { version = "2.4.0", features = ["serde"] }
|
||||||
uuid = { version = "1.3.4", default-features = false, features = ["fast-rng", "serde", "v4", "zerocopy"] }
|
uuid = { version = "1.3.4", default-features = false, features = ["fast-rng", "serde", "v4", "zerocopy"] }
|
||||||
|
derivative = "2.2.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
test-log = { version = "0.2.12", default-features = false, features = ["trace"] }
|
test-log = { version = "0.2.12", default-features = false, features = ["trace"] }
|
||||||
|
|
|
@ -258,7 +258,7 @@ mod tests {
|
||||||
use ethers::{
|
use ethers::{
|
||||||
prelude::{Http, Provider, U256},
|
prelude::{Http, Provider, U256},
|
||||||
types::Address,
|
types::Address,
|
||||||
utils::Anvil,
|
utils::{Anvil, AnvilInstance},
|
||||||
};
|
};
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
@ -269,7 +269,7 @@ mod tests {
|
||||||
};
|
};
|
||||||
use tokio::{
|
use tokio::{
|
||||||
sync::broadcast::error::SendError,
|
sync::broadcast::error::SendError,
|
||||||
task::JoinHandle,
|
task::{yield_now, JoinHandle},
|
||||||
time::{sleep, Instant},
|
time::{sleep, Instant},
|
||||||
};
|
};
|
||||||
use web3_proxy::{
|
use web3_proxy::{
|
||||||
|
@ -280,6 +280,7 @@ mod tests {
|
||||||
// TODO: put it in a thread?
|
// TODO: put it in a thread?
|
||||||
struct TestApp {
|
struct TestApp {
|
||||||
handle: Mutex<Option<JoinHandle<anyhow::Result<()>>>>,
|
handle: Mutex<Option<JoinHandle<anyhow::Result<()>>>>,
|
||||||
|
anvil: AnvilInstance,
|
||||||
anvil_provider: Provider<Http>,
|
anvil_provider: Provider<Http>,
|
||||||
proxy_provider: Provider<Http>,
|
proxy_provider: Provider<Http>,
|
||||||
shutdown_sender: broadcast::Sender<()>,
|
shutdown_sender: broadcast::Sender<()>,
|
||||||
|
@ -301,14 +302,11 @@ mod tests {
|
||||||
|
|
||||||
let anvil_provider = Provider::<Http>::try_from(anvil.endpoint()).unwrap();
|
let anvil_provider = Provider::<Http>::try_from(anvil.endpoint()).unwrap();
|
||||||
|
|
||||||
// mine a block to test the provider
|
|
||||||
let _: U256 = anvil_provider.request("evm_mine", ()).await.unwrap();
|
|
||||||
|
|
||||||
// make a test TopConfig
|
// make a test TopConfig
|
||||||
// TODO: load TopConfig from a file? CliConfig could have `cli_config.load_top_config`. would need to inject our endpoint ports
|
// TODO: load TopConfig from a file? CliConfig could have `cli_config.load_top_config`. would need to inject our endpoint ports
|
||||||
let top_config = TopConfig {
|
let top_config = TopConfig {
|
||||||
app: AppConfig {
|
app: AppConfig {
|
||||||
chain_id: 137,
|
chain_id: 31337,
|
||||||
default_user_max_requests_per_period: Some(6_000_000),
|
default_user_max_requests_per_period: Some(6_000_000),
|
||||||
deposit_factory_contract: Address::from_str(
|
deposit_factory_contract: Address::from_str(
|
||||||
"4e3BC2054788De923A04936C6ADdB99A05B0Ea36",
|
"4e3BC2054788De923A04936C6ADdB99A05B0Ea36",
|
||||||
|
@ -368,6 +366,7 @@ mod tests {
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
handle: Mutex::new(Some(handle)),
|
handle: Mutex::new(Some(handle)),
|
||||||
|
anvil,
|
||||||
anvil_provider,
|
anvil_provider,
|
||||||
proxy_provider,
|
proxy_provider,
|
||||||
shutdown_sender,
|
shutdown_sender,
|
||||||
|
@ -383,6 +382,8 @@ mod tests {
|
||||||
let handle = self.handle.lock().take();
|
let handle = self.handle.lock().take();
|
||||||
|
|
||||||
if let Some(handle) = handle {
|
if let Some(handle) = handle {
|
||||||
|
let _ = self.stop();
|
||||||
|
|
||||||
info!("waiting for the app to stop...");
|
info!("waiting for the app to stop...");
|
||||||
handle.await.unwrap().unwrap();
|
handle.await.unwrap().unwrap();
|
||||||
}
|
}
|
||||||
|
@ -418,11 +419,13 @@ mod tests {
|
||||||
|
|
||||||
let first_block_num = anvil_result.number.unwrap();
|
let first_block_num = anvil_result.number.unwrap();
|
||||||
|
|
||||||
|
// mine a block
|
||||||
let _: U256 = anvil_provider
|
let _: U256 = anvil_provider
|
||||||
.request("evm_mine", None::<()>)
|
.request("evm_mine", None::<()>)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
// make sure the block advanced
|
||||||
let anvil_result = anvil_provider
|
let anvil_result = anvil_provider
|
||||||
.request::<_, Option<ArcBlock>>("eth_getBlockByNumber", ("latest", false))
|
.request::<_, Option<ArcBlock>>("eth_getBlockByNumber", ("latest", false))
|
||||||
.await
|
.await
|
||||||
|
@ -440,7 +443,6 @@ mod tests {
|
||||||
|
|
||||||
assert_eq!(first_block_num, second_block_num - 1);
|
assert_eq!(first_block_num, second_block_num - 1);
|
||||||
|
|
||||||
// x.stop();
|
x.wait().await;
|
||||||
// x.wait().await;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ use crate::app::Web3ProxyJoinHandle;
|
||||||
use crate::rpcs::blockchain::{BlocksByHashCache, Web3ProxyBlock};
|
use crate::rpcs::blockchain::{BlocksByHashCache, Web3ProxyBlock};
|
||||||
use crate::rpcs::one::Web3Rpc;
|
use crate::rpcs::one::Web3Rpc;
|
||||||
use argh::FromArgs;
|
use argh::FromArgs;
|
||||||
|
use derivative::Derivative;
|
||||||
use ethers::prelude::{Address, TxHash};
|
use ethers::prelude::{Address, TxHash};
|
||||||
use ethers::types::{U256, U64};
|
use ethers::types::{U256, U64};
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
|
@ -256,15 +257,14 @@ pub fn average_block_interval(chain_id: u64) -> Duration {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configuration for a backend web3 RPC server
|
/// Configuration for a backend web3 RPC server
|
||||||
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq)]
|
#[derive(Clone, Debug, Derivative, Deserialize, PartialEq, Eq)]
|
||||||
|
#[derivative(Default)]
|
||||||
pub struct Web3RpcConfig {
|
pub struct Web3RpcConfig {
|
||||||
/// simple way to disable a connection without deleting the row
|
/// simple way to disable a connection without deleting the row
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub disabled: bool,
|
pub disabled: bool,
|
||||||
/// a name used in /status and other user facing messages
|
/// a name used in /status and other user facing messages
|
||||||
pub display_name: Option<String>,
|
pub display_name: Option<String>,
|
||||||
/// (deprecated) rpc url
|
|
||||||
pub url: Option<String>,
|
|
||||||
/// while not absolutely required, a ws:// or wss:// connection will be able to subscribe to head blocks
|
/// while not absolutely required, a ws:// or wss:// connection will be able to subscribe to head blocks
|
||||||
pub ws_url: Option<String>,
|
pub ws_url: Option<String>,
|
||||||
/// while not absolutely required, a http:// or https:// connection will allow erigon to stream JSON
|
/// while not absolutely required, a http:// or https:// connection will allow erigon to stream JSON
|
||||||
|
@ -272,7 +272,8 @@ pub struct Web3RpcConfig {
|
||||||
/// block data limit. If None, will be queried
|
/// block data limit. If None, will be queried
|
||||||
pub block_data_limit: Option<u64>,
|
pub block_data_limit: Option<u64>,
|
||||||
/// the requests per second at which the server starts slowing down
|
/// the requests per second at which the server starts slowing down
|
||||||
#[serde(default = "default_soft_limit")]
|
#[serde(default)]
|
||||||
|
#[derivative(Default(value = "1"))]
|
||||||
pub soft_limit: u32,
|
pub soft_limit: u32,
|
||||||
/// the requests per second at which the server throws errors (rate limit or otherwise)
|
/// the requests per second at which the server throws errors (rate limit or otherwise)
|
||||||
pub hard_limit: Option<u64>,
|
pub hard_limit: Option<u64>,
|
||||||
|
@ -288,10 +289,6 @@ pub struct Web3RpcConfig {
|
||||||
pub extra: HashMap<String, serde_json::Value>,
|
pub extra: HashMap<String, serde_json::Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_soft_limit() -> u32 {
|
|
||||||
10
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Web3RpcConfig {
|
impl Web3RpcConfig {
|
||||||
/// Create a Web3Rpc from config
|
/// Create a Web3Rpc from config
|
||||||
/// TODO: move this into Web3Rpc? (just need to make things pub(crate))
|
/// TODO: move this into Web3Rpc? (just need to make things pub(crate))
|
||||||
|
|
|
@ -817,8 +817,9 @@ impl ConsensusFinder {
|
||||||
|
|
||||||
// we used to specify rpc on this, but it shouldn't be necessary
|
// we used to specify rpc on this, but it shouldn't be necessary
|
||||||
let parent_hash = block_to_check.parent_hash();
|
let parent_hash = block_to_check.parent_hash();
|
||||||
|
// TODO: i flip flop on passing rpc to this or not
|
||||||
match web3_rpcs
|
match web3_rpcs
|
||||||
.block(authorization, parent_hash, None, None)
|
.block(authorization, parent_hash, Some(rpc), None)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(parent_block) => block_to_check = parent_block,
|
Ok(parent_block) => block_to_check = parent_block,
|
||||||
|
|
|
@ -89,7 +89,7 @@ impl Web3Rpc {
|
||||||
// TODO: have this take a builder (which will have channels attached). or maybe just take the config and give the config public fields
|
// TODO: have this take a builder (which will have channels attached). or maybe just take the config and give the config public fields
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub async fn spawn(
|
pub async fn spawn(
|
||||||
mut config: Web3RpcConfig,
|
config: Web3RpcConfig,
|
||||||
name: String,
|
name: String,
|
||||||
chain_id: u64,
|
chain_id: u64,
|
||||||
db_conn: Option<DatabaseConnection>,
|
db_conn: Option<DatabaseConnection>,
|
||||||
|
@ -142,19 +142,9 @@ impl Web3Rpc {
|
||||||
let (hard_limit_until, _) = watch::channel(Instant::now());
|
let (hard_limit_until, _) = watch::channel(Instant::now());
|
||||||
|
|
||||||
if config.ws_url.is_none() && config.http_url.is_none() {
|
if config.ws_url.is_none() && config.http_url.is_none() {
|
||||||
if let Some(url) = config.url {
|
return Err(anyhow!(
|
||||||
if url.starts_with("ws") {
|
"either ws_url or http_url are required. it is best to set both. they must both point to the same server!"
|
||||||
config.ws_url = Some(url);
|
));
|
||||||
} else if url.starts_with("http") {
|
|
||||||
config.http_url = Some(url);
|
|
||||||
} else {
|
|
||||||
return Err(anyhow!("only ws or http urls are supported"));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return Err(anyhow!(
|
|
||||||
"either ws_url or http_url are required. it is best to set both"
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let (head_block, _) = watch::channel(None);
|
let (head_block, _) = watch::channel(None);
|
||||||
|
|
Loading…
Reference in New Issue