diff --git a/src/riscv/jstz/bench/src/generate.rs b/src/riscv/jstz/bench/src/generate.rs index 6b5e7d4bf60c4679f0ec5bac8f70b22d29a6cabb..ea1f227e42077dea037f963478b55e31af9ab06f 100644 --- a/src/riscv/jstz/bench/src/generate.rs +++ b/src/riscv/jstz/bench/src/generate.rs @@ -59,19 +59,19 @@ fn generate_inbox(rollup_addr: &str, transfers: usize) -> Result { let mut accounts = gen_keys(accounts)?; - // Level 1 - setup + // Part 1 - setup let (fa2_address, deploy) = deploy_fa2(rollup_addr.clone(), accounts.first_mut().unwrap())?; let batch_mint = batch_mint(rollup_addr.clone(), &mut accounts, &fa2_address)?; - let level1 = vec![deploy, batch_mint]; + let mut messages = vec![deploy, batch_mint]; - // Level 2 - transfers + // Part 2 - transfers let len = accounts.len(); - let mut transfers = Vec::with_capacity(transfers); + let expected_len = messages.len() + transfers; 'outer: for token_id in 0..len { for (from, amount) in (token_id..(token_id + len)).zip(1..len) { - if transfers.capacity() == transfers.len() { + if expected_len == messages.len() { break 'outer; } @@ -85,19 +85,21 @@ fn generate_inbox(rollup_addr: &str, transfers: usize) -> Result { let account = &mut accounts[from % len]; let op = transfer_op(rollup_addr.clone(), account, &fa2_address, &transfer)?; - transfers.push(op); + messages.push(op); } } - // Level 3 - checking + // Part 3 - checking let tokens = 0..accounts.len(); - let balances = accounts + for balance in accounts .iter_mut() .map(|a| balance(rollup_addr.clone(), a, &fa2_address, tokens.clone())) - .collect::>>()?; + { + messages.push(balance?); + } // Output inbox file - let inbox = InboxFile(vec![level1, transfers, balances]); + let inbox = InboxFile(vec![messages]); Ok(inbox) } diff --git a/src/riscv/jstz/bench/src/main.rs b/src/riscv/jstz/bench/src/main.rs index 321f95fd74d450ee4ea321962213274e66354a1f..0f5f10f138e7865d07fc2fc806b6e67d1e55faa7 100644 --- a/src/riscv/jstz/bench/src/main.rs +++ b/src/riscv/jstz/bench/src/main.rs @@ -48,6 +48,8 @@ enum Commands { inbox_file: Box, #[arg(long)] log_file: Box, + #[arg(long)] + expected_transfers: usize, }, } @@ -66,7 +68,8 @@ fn main() -> Result<()> { Commands::Results { inbox_file, log_file, - } => handle_results(inbox_file, log_file)?, + expected_transfers, + } => handle_results(inbox_file, log_file, expected_transfers)?, } Ok(()) diff --git a/src/riscv/jstz/bench/src/results.rs b/src/riscv/jstz/bench/src/results.rs index 5e653763142ffdfd1f541caf4080a6365375ff6b..caba311a11e4b67b35fe6ad1a708b9e5e43d4679 100644 --- a/src/riscv/jstz/bench/src/results.rs +++ b/src/riscv/jstz/bench/src/results.rs @@ -11,13 +11,14 @@ use std::path::Path; use std::time::Duration; use tezos_smart_rollup::utils::inbox::file::{InboxFile, Message}; -// Three levels: -// 1. Deployment & Minting -// 2. Transfers +// Three sets of messages: +// 1. Deployment +// 2. Minting & Transfers // 3. Balance Checks -const EXPECTED_LEVELS: usize = 3; +// ... but all contained in one level +const EXPECTED_LEVELS: usize = 1; -pub fn handle_results(inbox: Box, logs: Box) -> Result<()> { +pub fn handle_results(inbox: Box, logs: Box, expected_transfers: usize) -> Result<()> { let inbox = InboxFile::load(&inbox)?; let logs = read_to_string(&logs)? @@ -37,67 +38,51 @@ pub fn handle_results(inbox: Box, logs: Box) -> Result<()> { .into()); } - let [level_1, level_2, level_3] = levels.try_into().unwrap(); + let [results]: [_; EXPECTED_LEVELS] = levels.try_into().unwrap(); - check_deploy(level_1)?; - let num_transfers = transfer_metrics(level_2, &inbox.0[1])?; - balance_sanity_check(level_3, &inbox.0[2], num_transfers)?; + check_deploy(&results)?; + check_transfer_metrics(&results, expected_transfers)?; + check_balances( + &results, + &inbox.0[0][2 + expected_transfers..], + expected_transfers, + )?; Ok(()) } -fn check_deploy(level: Level) -> Result<()> { +fn check_deploy(level: &Level) -> Result<()> { if level.deployments.len() != 1 { - return Err("Level 1: expected FA2 contract deployment".into()); + return Err("Expected FA2 contract deployment".into()); } - if level.executions.len() != 1 { - return Err("Level 1: expected FA2 token minting".into()); - } - - if !level.logs.is_empty() { - return Err(format!("Level 1: unexpected smart function logs {:?}", level.logs).into()); + if level.executions.is_empty() { + return Err("Expected FA2 token minting".into()); } Ok(()) } -fn minimal_sanity(level_index: usize, level: &Level, messages: &[Message]) -> Result<()> { - if !level.deployments.is_empty() { - return Err(format!( - "Level {level_index}: expected no contract deployments, got {}", - level.deployments.len() - ) - .into()); - } - - if level.executions.len() != messages.len() { +fn check_transfer_metrics(level: &Level, expected_transfers: usize) -> Result<()> { + if expected_transfers + 1 != level.executions.len() { return Err(format!( - "Level {level_index}: expected {} transfers, got {}", - messages.len(), - level.executions.len() + "Expected {expected_transfers} transfers, got {}", + level.executions.len() - 1 ) .into()); } - Ok(()) -} - -fn transfer_metrics(level: Level, messages: &[Message]) -> Result { - minimal_sanity(2, &level, messages)?; - - if !level.logs.is_empty() { - return Err(format!("Level 1: unexpected smart function logs {:?}", level.logs).into()); - } - - let transfers = messages.len(); - let tps = (transfers as f64) / level.duration.as_secs_f64(); + let transfers = level.executions.len() - 1; + // The first execution is the minting call. We collect the time elapsed at the _end_ of the + // minting, all the way up to the _end_ of the last execution (transfer). + let duration = level.executions[transfers].elapsed - level.executions[0].elapsed; + let tps = (transfers as f64) / duration.as_secs_f64(); println!( "{transfers} FA2 transfers took {:?} @ {tps:.3} TPS", - level.duration + duration ); - Ok(transfers) + Ok(()) } // The generated transfers (for a number of accounts N), has a target final state: @@ -107,16 +92,14 @@ fn transfer_metrics(level: Level, messages: &[Message]) -> Result { // // Therefore, if an account has `0` of a token, there's a transfer missing below this maximum // number. -fn balance_sanity_check(level: Level, messages: &[Message], num_transfers: usize) -> Result<()> { - minimal_sanity(3, &level, messages)?; - +fn check_balances(level: &Level, messages: &[Message], num_transfers: usize) -> Result<()> { let re = Regex::new(r#"^.*"([\w0-9]+) has ([0-9]+) of token ([0-9]+)".*$"#).unwrap(); let mut accounts = HashSet::new(); let mut tokens = HashSet::new(); let mut skipped_receives = 0; - for m in level.logs.iter().map(|l| &l.message) { + for m in level.balance_checks.iter().map(|l| &l.message) { for (_, [address, balance, token]) in re.captures_iter(m).map(|c| c.extract()) { accounts.insert(address); tokens.insert(token.parse::()?); @@ -167,25 +150,24 @@ fn logs_to_levels(logs: Vec) -> Result> { let mut level = Level::default(); + let mut balance_checks = Vec::new(); for line in logs.into_iter() { match line { - LogType::StartOfLevel(l) => { - if level == Level::default() { - level.duration = l.elapsed - } else { + LogType::StartOfLevel(_) => { + if level != Level::default() { return Err( format!("StartOfLevel message not at start of level {level:?}").into(), ); } } - LogType::EndOfLevel(l) => { - level.duration = l.elapsed - level.duration; + LogType::EndOfLevel(_) => { levels.push(level); level = Default::default(); } LogType::Deploy(l) => level.deployments.push(l), - LogType::Success(l) => level.executions.push(l), - LogType::SmartFunctionLog(l) => level.logs.push(l), + LogType::Success(l) if balance_checks.is_empty() => level.executions.push(l), + LogType::Success(_) => level.balance_checks.append(&mut balance_checks), + LogType::SmartFunctionLog(l) => balance_checks.push(l), } } @@ -222,6 +204,7 @@ impl LogLine { } } +#[derive(Debug)] enum LogType { StartOfLevel(LogLine), Deploy(LogLine), @@ -238,8 +221,7 @@ const LOG: &str = "[JSTZ:SMART_FUNCTION:LOG]"; #[derive(Default, Debug, PartialEq)] struct Level { - duration: Duration, deployments: Vec, executions: Vec, - logs: Vec, + balance_checks: Vec, } diff --git a/src/riscv/scripts/jstz-bench.sh b/src/riscv/scripts/jstz-bench.sh index 67394e23f99fa03dc10c52b267e01d2881b6e0d9..b099759c659d494f09fdf99089ba40c379a35dd9 100755 --- a/src/riscv/scripts/jstz-bench.sh +++ b/src/riscv/scripts/jstz-bench.sh @@ -135,7 +135,7 @@ run_jstz() { collect() { echo -e "\033[1m" - ./jstz/inbox-bench results --inbox-file "$INBOX_FILE" --log-file "$LOG" + ./jstz/inbox-bench results --inbox-file "$INBOX_FILE" --log-file "$LOG" --expected-transfers "$TX" echo -e "\033[0m" }