Skip to content

Commit a0aa50b

Browse files
ManagedMap benchmark sc + interactor
1 parent 3c74a99 commit a0aa50b

27 files changed

+1626
-308
lines changed

Cargo.lock

Lines changed: 604 additions & 308 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ members = [
5353
"contracts/benchmarks/mappers/vec-repeat/meta",
5454
"contracts/benchmarks/large-storage",
5555
"contracts/benchmarks/large-storage/meta",
56+
"contracts/benchmarks/managed-map-benchmark",
57+
"contracts/benchmarks/managed-map-benchmark/meta",
58+
"contracts/benchmarks/managed-map-benchmark/interactor",
5659
"contracts/benchmarks/str-repeat",
5760
"contracts/benchmarks/str-repeat/meta",
5861
"contracts/benchmarks/send-tx-repeat",
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Generated by Cargo
2+
# will have compiled files and executables
3+
/target/
4+
*/target/
5+
6+
# The mxpy output
7+
output
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[package]
2+
name = "managed-map-benchmark"
3+
version = "0.0.0"
4+
authors = ["Andrei Marinica <andrei.marinica@multiversx.com>"]
5+
edition = "2021"
6+
publish = false
7+
8+
[lib]
9+
path = "src/mmap_benchmark.rs"
10+
11+
[dependencies.multiversx-sc]
12+
version = "0.65.1"
13+
path = "../../../framework/base"
14+
15+
[dev-dependencies.multiversx-sc-scenario]
16+
version = "0.65.1"
17+
path = "../../../framework/scenario"
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Pem files are used for interactions, but shouldn't be committed
2+
*.pem
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
[package]
2+
name = "rust-interact"
3+
version = "0.0.0"
4+
authors = ["you"]
5+
edition = "2021"
6+
publish = false
7+
8+
[[bin]]
9+
name = "rust-interact"
10+
path = "src/interactor_main.rs"
11+
12+
[lib]
13+
path = "src/mm_interactor.rs"
14+
15+
[dependencies.managed-map-benchmark]
16+
path = ".."
17+
18+
[dependencies.multiversx-sc-snippets]
19+
version = "0.65.1"
20+
21+
[dependencies.multiversx-sc]
22+
version = "0.65.1"
23+
24+
[dependencies]
25+
clap = { version = "4.4.7", features = ["derive"] }
26+
serde = { version = "1.0", features = ["derive"] }
27+
toml = "0.8.6"
28+
29+
[features]
30+
chain-simulator-tests = []
31+
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
chain_type = 'simulator'
3+
gateway_uri = 'http://localhost:8085'
4+
5+
# chain_type = 'real'
6+
# gateway_uri = 'https://testnet-gateway.multiversx.com'
7+
8+
# chain_type = 'real'
9+
# gateway_uri = 'https://testnet-alb-fra.internal-gateway.multiversx.com'
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#![allow(unused)]
2+
3+
use serde::Deserialize;
4+
use std::io::Read;
5+
6+
/// Config file
7+
const CONFIG_FILE: &str = "config.toml";
8+
9+
#[derive(Debug, Deserialize)]
10+
#[serde(rename_all = "lowercase")]
11+
pub enum ChainType {
12+
Real,
13+
Simulator,
14+
}
15+
16+
/// Contract Interact configuration
17+
#[derive(Debug, Deserialize)]
18+
pub struct Config {
19+
pub gateway_uri: String,
20+
pub chain_type: ChainType,
21+
}
22+
23+
impl Config {
24+
// Deserializes config from file
25+
pub fn new() -> Self {
26+
let mut file = std::fs::File::open(CONFIG_FILE).unwrap();
27+
let mut content = String::new();
28+
file.read_to_string(&mut content).unwrap();
29+
toml::from_str(&content).unwrap()
30+
}
31+
32+
pub fn chain_simulator_config() -> Self {
33+
Config {
34+
gateway_uri: "http://localhost:8085".to_owned(),
35+
chain_type: ChainType::Simulator,
36+
}
37+
}
38+
39+
// Returns the gateway URI
40+
pub fn gateway_uri(&self) -> &str {
41+
&self.gateway_uri
42+
}
43+
44+
// Returns if chain type is chain simulator
45+
pub fn use_chain_simulator(&self) -> bool {
46+
match self.chain_type {
47+
ChainType::Real => false,
48+
ChainType::Simulator => true,
49+
}
50+
}
51+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
use multiversx_sc_snippets::imports::*;
2+
use rust_interact::managed_map_benchmark_cli;
3+
4+
#[tokio::main]
5+
async fn main() {
6+
managed_map_benchmark_cli().await;
7+
}
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
#![allow(non_snake_case)]
2+
3+
pub mod config;
4+
mod proxy;
5+
6+
use config::Config;
7+
use multiversx_sc_snippets::imports::*;
8+
use serde::{Deserialize, Serialize};
9+
use std::{
10+
io::{Read, Write},
11+
path::Path,
12+
};
13+
14+
const STATE_FILE: &str = "state.toml";
15+
16+
pub async fn managed_map_benchmark_cli() {
17+
env_logger::init();
18+
19+
let mut args = std::env::args();
20+
let _ = args.next();
21+
let cmd = args.next().expect("at least one argument required");
22+
let config = Config::new();
23+
let mut interact = ContractInteract::new(config).await;
24+
match cmd.as_str() {
25+
"deploy" => interact.deploy().await,
26+
"mm_get" => interact.mm_get().await,
27+
"mm_contains" => interact.mm_contains().await,
28+
"mm_remove" => interact.mm_remove().await,
29+
_ => panic!("unknown command: {}", &cmd),
30+
}
31+
}
32+
33+
#[derive(Debug, Default, Serialize, Deserialize)]
34+
pub struct State {
35+
contract_address: Option<Bech32Address>,
36+
repeats: usize,
37+
}
38+
39+
impl State {
40+
// Deserializes state from file
41+
pub fn load_state() -> Self {
42+
if Path::new(STATE_FILE).exists() {
43+
let mut file = std::fs::File::open(STATE_FILE).unwrap();
44+
let mut content = String::new();
45+
file.read_to_string(&mut content).unwrap();
46+
toml::from_str(&content).unwrap()
47+
} else {
48+
Self::default()
49+
}
50+
}
51+
52+
/// Sets the contract address
53+
pub fn set_address(&mut self, address: Bech32Address) {
54+
self.contract_address = Some(address);
55+
}
56+
57+
/// Returns the contract address
58+
pub fn current_address(&self) -> &Bech32Address {
59+
self.contract_address
60+
.as_ref()
61+
.expect("no known contract, deploy first")
62+
}
63+
}
64+
65+
impl Drop for State {
66+
// Serializes state to file
67+
fn drop(&mut self) {
68+
let mut file = std::fs::File::create(STATE_FILE).unwrap();
69+
file.write_all(toml::to_string(self).unwrap().as_bytes())
70+
.unwrap();
71+
}
72+
}
73+
74+
pub struct ContractInteract {
75+
interactor: Interactor,
76+
wallet_address: Address,
77+
contract_code: BytesValue,
78+
state: State,
79+
}
80+
81+
impl ContractInteract {
82+
pub async fn new(config: Config) -> Self {
83+
let mut interactor = Interactor::new(config.gateway_uri())
84+
.await
85+
.use_chain_simulator(config.use_chain_simulator());
86+
87+
interactor.set_current_dir_from_workspace("managed-map-benchmark");
88+
let wallet_address = interactor.register_wallet(test_wallets::alice()).await;
89+
90+
// Useful in the chain simulator setting
91+
// generate blocks until ESDTSystemSCAddress is enabled
92+
interactor.generate_blocks_until_epoch(1).await.unwrap();
93+
94+
let contract_code = BytesValue::interpret_from(
95+
"mxsc:../output/managed-map-benchmark.mxsc.json",
96+
&InterpreterContext::default(),
97+
);
98+
99+
ContractInteract {
100+
interactor,
101+
wallet_address,
102+
contract_code,
103+
state: State::load_state(),
104+
}
105+
}
106+
107+
pub async fn deploy(&mut self) {
108+
let new_address = self
109+
.interactor
110+
.tx()
111+
.from(&self.wallet_address)
112+
.gas(30_000_000u64)
113+
.typed(proxy::ManagedMapBenchmarkProxy)
114+
.init()
115+
.code(&self.contract_code)
116+
.returns(ReturnsNewBech32Address)
117+
.run()
118+
.await;
119+
self.state.set_address(new_address.clone());
120+
println!("new address: {new_address}");
121+
}
122+
123+
pub async fn mm_get(&mut self) {
124+
let (result_value, gas_used) = self
125+
.interactor
126+
.tx()
127+
.from(&self.wallet_address)
128+
.to(self.state.current_address())
129+
.typed(proxy::ManagedMapBenchmarkProxy)
130+
.mm_get("key0", self.state.repeats)
131+
.returns(ReturnsResultAs::<String>::new())
132+
.returns(ReturnsGasUsed)
133+
.run()
134+
.await;
135+
136+
println!("Result: {result_value}");
137+
println!("Gas used: {gas_used}");
138+
}
139+
140+
pub async fn mm_contains(&mut self) {
141+
let (result_value, gas_used) = self
142+
.interactor
143+
.tx()
144+
.from(&self.wallet_address)
145+
.to(self.state.current_address())
146+
.typed(proxy::ManagedMapBenchmarkProxy)
147+
.mm_contains("key0", self.state.repeats)
148+
.returns(ReturnsResultUnmanaged)
149+
.returns(ReturnsGasUsed)
150+
.run()
151+
.await;
152+
153+
println!("Result: {result_value}");
154+
println!("Gas used: {gas_used}");
155+
}
156+
157+
pub async fn mm_remove(&mut self) {
158+
let gas_used = self
159+
.interactor
160+
.tx()
161+
.from(&self.wallet_address)
162+
.to(self.state.current_address())
163+
.gas(150_000_000u64)
164+
.typed(proxy::ManagedMapBenchmarkProxy)
165+
.mm_remove("key0", self.state.repeats)
166+
.returns(ReturnsGasUsed)
167+
.run()
168+
.await;
169+
170+
println!("Gas used: {gas_used}");
171+
}
172+
}

0 commit comments

Comments
 (0)