Skip to content

Commit

Permalink
Merge branch 'dev' into remove-merge-bug
Browse files Browse the repository at this point in the history
  • Loading branch information
popzxc authored Oct 20, 2020
2 parents 7f6a2d6 + 7e02186 commit 656aab9
Show file tree
Hide file tree
Showing 33 changed files with 2,150 additions and 2,243 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ target
a.out
.gitconfig
tags
*.orig

zksync_pk.key
dist
Expand Down
37 changes: 1 addition & 36 deletions bin/loadtest
Original file line number Diff line number Diff line change
@@ -1,39 +1,4 @@
#!/bin/bash

USAGE='Usage: zksync loadtest [-h|--help] [SCENARIO] [PATH_TO_CONFIG]
where:
-h | --help show this message
SCENARIO {outgoing,execution,real-life,api-test} (outgoing by default)
PATH_TO_CONFIG path to loadtest config (default is 'core/tests/loadtest/src/loadtest.json'
for outgoing/execution and 'core/tests/loadtest/src/configs/reallife.json'
for real-life scenario)'

if [ -z $ZKSYNC_ENV ];
then
echo "$USAGE"
exit 1
fi

SCENARIO=${1:-outgoing}

case $SCENARIO in
outgoing | execution)
CONFIG=${2:-"$ZKSYNC_HOME/core/tests/loadtest/src/configs/loadtest.json"}
;;
real-life|reallife|real_life)
CONFIG=${2:-"$ZKSYNC_HOME/core/tests/loadtest/src/configs/reallife.json"}
;;
-h | --help)
echo "$USAGE"
exit 0
;;
*)
echo Unknown loadtest scenario
echo "$USAGE"
exit 1
;;
esac

echo "Executing $SCENARIO loadtest scenario (config path $CONFIG)"
cd $ZKSYNC_HOME
cargo run --release --bin loadtest -- --scenario $SCENARIO $CONFIG
cargo run --release --bin loadtest -- "${@}"
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ impl OperationNotifier {
action: ActionType,
sub: Subscriber<TransactionInfoResp>,
) -> Result<(), anyhow::Error> {
let sub_id = self.tx_subs.generate_sub_id(hash.clone(), action);
let sub_id = self.tx_subs.generate_sub_id(hash, action);

let tx_receipt = self.state.get_tx_receipt(&hash).await?;

Expand Down
2 changes: 1 addition & 1 deletion core/lib/types/src/tx/primitives/tx_hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::{convert::TryInto, str::FromStr};

/// Transaction hash.
/// Essentially, a SHA-256 hash of transaction bytes encoded according to the zkSync protocol.
#[derive(Debug, Clone, PartialEq, Default, Eq, Hash, PartialOrd, Ord)]
#[derive(Debug, Copy, Clone, PartialEq, Default, Eq, Hash, PartialOrd, Ord)]
pub struct TxHash {
pub(crate) data: [u8; 32],
}
Expand Down
15 changes: 9 additions & 6 deletions core/tests/loadtest/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,21 @@ zksync = { path = "../../../sdk/zksync-rs", version = "0.1" }
zksync_config = { path = "../../lib/config", version = "1.0" }
zksync_utils = { path = "../../lib/utils", version = "1.0" }

serde = "1.0.90"
serde_json = "1.0.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
toml = "0.5"

async-trait = "0.1"
web3 = "0.13.0"
futures = { version = "0.3" }
tokio = { version = "0.2", features = ["full"] }

hex = "0.4"
anyhow = "1.0"
chrono = "0.4"
colored = "2.0.0"
env_logger = "0.6"
hex = "0.4"
log = "0.4"
num = { version = "0.2", features = ["serde"] }
rand = "0.4"
log = "0.4"
env_logger = "0.6"
structopt = "0.3"
chrono = "0.4"
22 changes: 22 additions & 0 deletions core/tests/loadtest/config/localhost.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[main_wallet]
address = '0x36615cf349d7f6344891b1e7ca7c72883f5dc049'
private_key = '0x7726827caac94a7f9e1b160f7ea819f172f7b6f9d2a97f992c38edeab82d4110'
token_name = 'ETH'

[network]
name = 'localhost'

[[scenarios]]
name = 'transfer'
transfer_size = 1
transfer_rounds = 1
wallets_amount = 100

[[scenarios]]
name = "withdraw"
wallets_amount = 10
withdraw_rounds = 3

[[scenarios]]
name = "full_exit"
wallets_amount = 10
166 changes: 166 additions & 0 deletions core/tests/loadtest/src/api/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
//! Module with different API tests for a `loadtest`.
// Built-in uses
use std::{
collections::BTreeMap,
sync::{
atomic::{AtomicBool, Ordering},
Arc,
},
time::Instant,
};
// External uses
use futures::{future::BoxFuture, Future, FutureExt};
// Workspace uses
use zksync::{types::BlockStatus, Wallet};
use zksync_types::{Address, TxFeeTypes};
// Local uses
use crate::{
journal::{FiveSummaryStats, Sample},
monitor::Monitor,
utils::try_wait_all,
};

#[derive(Debug, Clone)]
pub struct CancellationToken(Arc<AtomicBool>);

impl CancellationToken {
pub fn new() -> Self {
Self(Arc::new(AtomicBool::new(false)))
}

pub fn cancel(&self) {
self.0.store(true, Ordering::SeqCst)
}

pub fn is_canceled(&self) -> bool {
self.0.load(Ordering::SeqCst)
}
}

impl Default for CancellationToken {
fn default() -> Self {
Self::new()
}
}

async fn measure_future<F, Fut>(
cancellation: CancellationToken,
limit: usize,
factory: F,
) -> anyhow::Result<Vec<Sample>>
where
F: Fn() -> Fut,
Fut: Future<Output = anyhow::Result<()>>,
{
let mut samples = Vec::with_capacity(limit);
for _ in 0..limit {
let future = factory();
let started_at = Instant::now();
future.await?;
let finished_at = Instant::now();

samples.push(Sample {
started_at,
finished_at,
});

if cancellation.is_canceled() {
break;
}
}

Ok(samples)
}

struct ApiTestsBuilder<'a> {
cancellation: CancellationToken,
categories: Vec<String>,
tests: Vec<BoxFuture<'a, anyhow::Result<Vec<Sample>>>>,
}

impl<'a> ApiTestsBuilder<'a> {
const LIMIT: usize = 10_000_000;

fn new(cancellation: CancellationToken) -> Self {
Self {
cancellation,
tests: Vec::new(),
categories: Vec::new(),
}
}

fn append<F, Fut>(mut self, category: impl Into<String>, factory: F) -> Self
where
F: Fn() -> Fut + Send + 'a,
Fut: Future<Output = anyhow::Result<()>> + Send + 'a,
{
let category = category.into();
let future = measure_future(self.cancellation.clone(), Self::LIMIT, factory).boxed();

self.categories.push(category);
self.tests.push(future);

self
}

async fn run(self) -> anyhow::Result<BTreeMap<String, FiveSummaryStats>> {
let results = try_wait_all(self.tests.into_iter()).await?;

Ok(self
.categories
.into_iter()
.zip(results)
.map(|(category, data)| (category, FiveSummaryStats::from_samples(&data)))
.collect())
}
}

pub fn run(
monitor: Monitor,
wallet: Wallet,
) -> (
impl Future<Output = anyhow::Result<BTreeMap<String, FiveSummaryStats>>>,
CancellationToken,
) {
let cancellation = CancellationToken::default();

let token = cancellation.clone();
let future = async move {
log::info!("API tests starting...");

let stats = ApiTestsBuilder::new(token.clone())
.append("monitor/tokens", || async {
monitor.provider.tokens().await.ok();
Ok(())
})
.append("monitor/contract_address", || async {
monitor.provider.contract_address().await.ok();
Ok(())
})
.append("monitor/account_info", || async {
monitor.provider.account_info(wallet.address()).await.ok();
Ok(())
})
.append("monitor/get_tx_fee", || async {
monitor
.provider
.get_tx_fee(TxFeeTypes::FastWithdraw, Address::default(), "ETH")
.await
.ok();
Ok(())
})
.append("wallet/balance", || async {
wallet.get_balance(BlockStatus::Verified, "ETH").await.ok();
Ok(())
})
.run()
.await?;

log::info!("API tests finished");

Ok(stats)
};

(future, cancellation)
}
21 changes: 0 additions & 21 deletions core/tests/loadtest/src/cli.rs

This file was deleted.

57 changes: 57 additions & 0 deletions core/tests/loadtest/src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//! This module contains different config structures for different types of
//! load tests.
//!
//! Currently, there are two main types of configs:
//! - loadtest config, intended for tests measuring the performance of the
//! server under the pressure;
//! - real-life config, intended for tests ensuring the durability of the
//! server in real-life conditions.
// Built-in imports
use std::{fs, path::Path};
// External uses
use serde::{Deserialize, Serialize};
use web3::types::H256;
// Workspace uses
use zksync::Network;
use zksync_types::{Address, TokenLike};
// Local uses
use crate::scenarios::ScenarioConfig;

/// Information about Ethereum account.
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
pub struct AccountInfo {
pub address: Address,
pub private_key: H256,
pub token_name: TokenLike,
}

#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
pub struct NetworkConfig {
pub name: Network,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct Config {
pub main_wallet: AccountInfo,
pub network: NetworkConfig,
pub scenarios: Vec<ScenarioConfig>,
}

impl Default for Config {
fn default() -> Self {
let config_str = include_str!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/config/localhost.toml"
));
toml::from_str(config_str).unwrap()
}
}

impl Config {
/// Reads config from the given TOML file.
pub fn from_toml(path: impl AsRef<Path>) -> anyhow::Result<Self> {
let content = fs::read_to_string(path)?;
toml::from_str(&content).map_err(From::from)
}
}
Loading

0 comments on commit 656aab9

Please sign in to comment.