Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slavas/bm inject tx #12899

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ exclude = ["neard"]
[workspace]
resolver = "2"
members = [
"benchmarks/transactions-generator",
"chain/chain",
"chain/chunks",
"chain/client",
Expand Down Expand Up @@ -270,6 +271,7 @@ near-schema-checker-macro = { path = "core/schema-checker/schema-checker-macro"
near-schema-checker-core = { path = "core/schema-checker/schema-checker-core" }
near-schema-checker-lib = { path = "core/schema-checker/schema-checker-lib" }
near-store = { path = "core/store" }
near-transactions-generator = { path = "benchmarks/transactions-generator"}
near-telemetry = { path = "chain/telemetry" }
near-test-contracts = { path = "runtime/near-test-contracts" }
near-time = { path = "core/time" }
Expand Down
3 changes: 3 additions & 0 deletions benchmarks/transactions-generator/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.near/
neard
user-data/
32 changes: 32 additions & 0 deletions benchmarks/transactions-generator/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
[package]
name = "near-transactions-generator"
version.workspace = true
authors.workspace = true
edition.workspace = true
rust-version.workspace = true
repository.workspace = true
license.workspace = true

[features]
default = ["with_actix"]
with_actix = ["near-async", "near-network", "actix"]

[dependencies]
actix = { workspace = true, optional = true }
anyhow.workspace = true
near-async = {workspace = true, optional = true }
near-crypto = { workspace = true }
near-network = { workspace = true, optional = true }
near-primitives = { workspace = true, features = ["clock", "test_utils"] }
near-client.workspace = true
near-client-primitives.workspace = true

rand.workspace = true
serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
tokio = { workspace = true, features = ["full"] }
tracing = { workspace = true, features = ["std"] }


[lints]
workspace = true
23 changes: 23 additions & 0 deletions benchmarks/transactions-generator/justfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
script_dir := `pwd`
neard := script_dir / "./neard"
near_localnet_home := script_dir / ".near/"
rpc_url := "http://127.0.0.1:3030"

init_localnet:
rm -rf {{near_localnet_home}} && {{neard}} --home {{near_localnet_home}} init --chain-id localnet

run_localnet:
{{neard}} --home {{near_localnet_home}} run

create_sub_accounts:
RUST_LOG=info \
../synth-bm/target/release/near-synth-bm create-sub-accounts \
--rpc-url {{rpc_url}} \
--signer-key-path {{near_localnet_home}}/validator_key.json \
--nonce 1 \
--sub-account-prefix 'a' \
--num-sub-accounts 100 \
--deposit 953060601875000000010000 \
--channel-buffer-size 1200 \
--requests-per-second 1250 \
--user-data-dir user-data
29 changes: 29 additions & 0 deletions benchmarks/transactions-generator/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# How to use

- prepare the localnet
```
just init_localnet
just run_localnet
```
- in another console create the subaccounts

Check warning on line 8 in benchmarks/transactions-generator/readme.md

View workflow job for this annotation

GitHub Actions / spellcheck

Unknown word (subaccounts)
```
just create_sub_accounts
```
- modify the config (`.near/config.json`) to enable the transactions generator
```json
"tx_generator": {
"tps": 200,
"volume": 5000,
"accounts_path": "/home/slavas/proj/nearcore/benchmarks/transactions-generator/user-data"

Check warning on line 17 in benchmarks/transactions-generator/readme.md

View workflow job for this annotation

GitHub Actions / spellcheck

Unknown word (slavas)
},

```
- restart the neard
```
killall neard

Check warning on line 23 in benchmarks/transactions-generator/readme.md

View workflow job for this annotation

GitHub Actions / spellcheck

Unknown word (killall)
just run_localnet
```
- observe the load reported in the logs
```
2025-02-12T16:42:37.351118Z INFO stats: # 1584 6nxZon12xBTmARmUm3ngtgaA2K7V9dX1J13EtPZ2kEhe Validator | 1 validator 0 peers ⬇ 0 B/s ⬆ 0 B/s 1.60 bps 131 Tgas/s CPU: 70%, Mem: 2.98 GB
```
72 changes: 72 additions & 0 deletions benchmarks/transactions-generator/src/account.rs
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will need to be merged/de-duplicated with synth-bm once that makes it into the workspace

Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
use near_primitives::types::AccountId;
use near_crypto::{PublicKey, SecretKey, InMemorySigner, Signer};
use serde::{Deserialize, Serialize};
use std::fs;
use std::path::Path;
use anyhow::Context;


#[derive(Serialize, Deserialize, Clone, Debug) ]
pub struct Account {
#[serde(rename = "account_id")]
pub id: AccountId,
pub public_key: PublicKey,
pub secret_key: SecretKey,
// New transaction must have a nonce bigger than this.
pub nonce: u64,
}

impl Account {
pub fn new(id: AccountId, secret_key: SecretKey, nonce: u64) -> Self {
Self { id, public_key: secret_key.public_key(), secret_key, nonce }
}

pub fn from_file(path: &Path) -> anyhow::Result<Account> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this function not just panic? If it is failing then that means we will probably fail to start the application. I imagine that there isn't much that can be done [from within the application] if this fails. I am not a fan of unnecessary error passing and handling in relatively straightforward cli applications.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

further would extend this comment to the rest of the PR.

Also please do not invest time making changes to address this review yet till we have alignment on the overall approach.

let content = fs::read_to_string(path)?;
let account = serde_json::from_str(&content)
.with_context(|| format!("failed reading file {path:?} as 'Account'"))?;
Ok(account)
}

pub fn write_to_dir(&self, dir: &Path) -> anyhow::Result<()> {
if !dir.exists() {
std::fs::create_dir(dir)?;
}

let json = serde_json::to_string(self)?;
let mut file_name = self.id.to_string();
file_name.push_str(".json");
let file_path = dir.join(file_name);
fs::write(file_path, json)?;
Ok(())
}

pub fn as_signer(&self) -> Signer {
Signer::from(InMemorySigner::from_secret_key(self.id.clone(), self.secret_key.clone()))
}
} // impl Account

/// Tries to deserialize all json files in `dir` as [`Account`].
pub fn accounts_from_dir(dir: &Path) -> anyhow::Result<Vec<Account>> {
if !dir.is_dir() {
anyhow::bail!("{:?} is not a directory", dir);
}

let mut accounts = vec![];
for entry in fs::read_dir(dir)? {
let entry = entry?;
let file_type = entry.file_type()?;
if !file_type.is_file() {
continue;
}
let path = entry.path();
let file_extension = path.extension();
if file_extension.is_none() || file_extension.unwrap() != "json" {
continue;
}
let account = Account::from_file(&path)?;
accounts.push(account);
}

Ok(accounts)
}
51 changes: 51 additions & 0 deletions benchmarks/transactions-generator/src/actix_actor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use crate::{TxGenerator, TxGeneratorConfig, ClientSender, ViewClientSender};

use actix::Actor;
use near_async::actix_wrapper::ActixWrapper;
use near_async::futures::DelayedActionRunner;
use near_async::messaging::{self};


pub type TxGeneratorActor = ActixWrapper<GeneratorActorImpl>;

pub struct GeneratorActorImpl {
tx_generator: TxGenerator,
}

impl messaging::Actor for GeneratorActorImpl {
fn start_actor(&mut self, ctx: &mut dyn DelayedActionRunner<Self>){
self.start(ctx)
}
}

impl GeneratorActorImpl {
pub fn start(&mut self, _ctx: &mut dyn DelayedActionRunner<Self>){
match self.tx_generator.start() {
Err(err) => {
tracing::error!(target: "transaction-generator", "Error: {err}");
},
Ok(_) => {
tracing::info!(target: "transaction-generator",
tps=self.tx_generator.params.tps, "Started");
}
};
}
}

pub fn start_tx_generator(
config: TxGeneratorConfig,
client_sender: ClientSender,
view_client_sender: ViewClientSender,
)-> actix::Addr<TxGeneratorActor>
{
let arbiter = actix::Arbiter::new();
let tx_generator = TxGenerator::new(config, client_sender, view_client_sender).unwrap();
TxGeneratorActor::start_in_arbiter(&arbiter.handle(),
move |_| {
let actor_impl = GeneratorActorImpl {
tx_generator,
};
ActixWrapper::new(actor_impl)
}
)
}
Loading
Loading