-
Notifications
You must be signed in to change notification settings - Fork 54
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add benchmark for simple transaction (#577)
* feat: add benchmark for default transaction * refactor: use trace instead of emit, create wrapper for host * refactor: improve cycles print * refactor: add inline comments, change trace ids * chore: ignore the test untill it become a binary * refactor: organise cycles storing, add traces for each note * feat: create a simple cli for benchmark binary package * feat: create cargo-make script for benchmarking, move benchmarks back to the miden-tx * refactor: move TransactionProgress to the TransactionHost * feat: implement bench for P2ID note, add NoteId to the output * refactor: move last note id obtaining to the separate function * refactor: fix no-std build * refactor: update comments in main.masm file to be consistent with api.masm * feat: write benchmark results to the json file * refactor: move benchmarks to their own crate * refactor: add ability to run all benches * refactor: update bin name, dependencies; remove benches except all * chore: fix no-std build * refactor: rework TransactionProgress serialization * refactor: exclude bench-tx from no-std build, update dependencies * refactor: improve imports formatting * refactor: rework writing to json * chore: change visibility of miden-tx MockDataStore * chore: update CHANGELOG, create README for bench-tx
- Loading branch information
Showing
18 changed files
with
887 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
[workspace] | ||
resolver = "2" | ||
members = [ | ||
members = [ | ||
"bench-tx", | ||
"miden-lib", | ||
"miden-tx", | ||
"mock", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
[package] | ||
name = "miden-bench-tx" | ||
version = "0.1.0" | ||
edition.workspace = true | ||
rust-version.workspace = true | ||
license.workspace = true | ||
authors.workspace = true | ||
homepage.workspace = true | ||
repository.workspace = true | ||
exclude.workspace = true | ||
|
||
[[bin]] | ||
name = "bench-tx" | ||
path = "src/main.rs" | ||
|
||
[dependencies] | ||
miden-lib = { package = "miden-lib", path = "../miden-lib", version = "0.3" } | ||
miden-objects = { package = "miden-objects", path = "../objects", version = "0.3" } | ||
miden-tx = { package = "miden-tx", path = "../miden-tx", version = "0.3" } | ||
mock = { package = "miden-mock", path = "../mock" } | ||
serde = { package = "serde", version = "1.0" } | ||
serde_json = { package = "serde_json", version = "1.0", features = ["preserve_order"] } | ||
vm-processor = { workspace = true } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Miden transactions benchmark | ||
|
||
This crate contains an executable used for benchmarking transactions. | ||
|
||
For each transaction, data is collected on the number of cycles required to complete: | ||
- Prologue | ||
- All notes processing | ||
- Each note execution | ||
- Transaction script processing | ||
- Epilogue | ||
|
||
## Usage | ||
|
||
To run the benchmark you can use [cargo-make](https://github.com/sagiegurari/cargo-make) with the following command present in our [Makefile.toml](Makefile.toml): | ||
|
||
```shell | ||
cargo make bench-tx | ||
``` | ||
|
||
Results of the benchmark are stored in the [bench-tx.json](bench-tx.json) file. | ||
|
||
## License | ||
|
||
This project is [MIT licensed](../LICENSE). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
{ | ||
"simple": { | ||
"prologue": 3644, | ||
"notes_processing": 1151, | ||
"note_execution": { | ||
"0x47b2fbff8a3f09e40343238e7b15c8918d7c63e570fd1b3c904ada458c4d74bd": 392, | ||
"0x8a55c3531cdd5725aa805475093ed3006c6773b71a008e8ca840da8364a67cd6": 715 | ||
}, | ||
"tx_script_processing": 32, | ||
"epilogue": 2222 | ||
}, | ||
"p2id": { | ||
"prologue": 2004, | ||
"notes_processing": 920, | ||
"note_execution": { | ||
"0xb9fa30eb43d80d579be02dc004338e06b5ad565e81e0bac11a94ab01abfdd40a": 883 | ||
}, | ||
"tx_script_processing": 88209, | ||
"epilogue": 272 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
use core::fmt; | ||
use std::{ | ||
fs::{read_to_string, write, File}, | ||
io::Write, | ||
path::Path, | ||
}; | ||
|
||
use miden_lib::{ | ||
notes::create_p2id_note, transaction::ToTransactionKernelInputs, utils::Serializable, | ||
}; | ||
use miden_objects::{ | ||
accounts::AccountId, | ||
assembly::ProgramAst, | ||
assets::{Asset, FungibleAsset}, | ||
crypto::{dsa::rpo_falcon512::SecretKey, rand::RpoRandomCoin}, | ||
notes::NoteType, | ||
transaction::TransactionArgs, | ||
Felt, | ||
}; | ||
use miden_tx::{TransactionExecutor, TransactionHost, TransactionProgress}; | ||
use vm_processor::{ExecutionOptions, RecAdviceProvider, Word}; | ||
|
||
mod utils; | ||
use utils::{ | ||
get_account_with_default_account_code, write_bench_results_to_json, MockDataStore, String, | ||
ToString, Vec, ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN, | ||
ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, ACCOUNT_ID_SENDER, DEFAULT_AUTH_SCRIPT, | ||
}; | ||
|
||
pub enum Benchmark { | ||
Simple, | ||
P2ID, | ||
} | ||
|
||
impl fmt::Display for Benchmark { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
match self { | ||
Benchmark::Simple => write!(f, "simple"), | ||
Benchmark::P2ID => write!(f, "p2id"), | ||
} | ||
} | ||
} | ||
|
||
fn main() -> Result<(), String> { | ||
// create a template file for benchmark results | ||
let path = Path::new("bench-tx/bench-tx.json"); | ||
let mut file = File::create(path).map_err(|e| e.to_string())?; | ||
file.write_all(b"{}").map_err(|e| e.to_string())?; | ||
|
||
// run all available benchmarks | ||
let benchmark_results = vec![ | ||
(Benchmark::Simple, benchmark_default_tx()?), | ||
(Benchmark::P2ID, benchmark_p2id()?), | ||
]; | ||
|
||
// store benchmark results in the JSON file | ||
write_bench_results_to_json(path, benchmark_results)?; | ||
|
||
Ok(()) | ||
} | ||
|
||
// BENCHMARKS | ||
// ================================================================================================ | ||
|
||
/// Runs the default transaction with empty transaction script and two default notes. | ||
pub fn benchmark_default_tx() -> Result<TransactionProgress, String> { | ||
let data_store = MockDataStore::default(); | ||
let mut executor = TransactionExecutor::new(data_store.clone()).with_tracing(); | ||
|
||
let account_id = data_store.account.id(); | ||
executor.load_account(account_id).map_err(|e| e.to_string())?; | ||
|
||
let block_ref = data_store.block_header.block_num(); | ||
let note_ids = data_store.notes.iter().map(|note| note.id()).collect::<Vec<_>>(); | ||
|
||
let transaction = executor | ||
.prepare_transaction(account_id, block_ref, ¬e_ids, data_store.tx_args().clone()) | ||
.map_err(|e| e.to_string())?; | ||
|
||
let (stack_inputs, advice_inputs) = transaction.get_kernel_inputs(); | ||
let advice_recorder: RecAdviceProvider = advice_inputs.into(); | ||
let mut host = TransactionHost::new(transaction.account().into(), advice_recorder); | ||
|
||
vm_processor::execute( | ||
transaction.program(), | ||
stack_inputs, | ||
&mut host, | ||
ExecutionOptions::default().with_tracing(), | ||
) | ||
.map_err(|e| e.to_string())?; | ||
|
||
Ok(host.tx_progress().clone()) | ||
} | ||
|
||
/// Runs the transaction which consumes a P2ID note into a basic wallet. | ||
pub fn benchmark_p2id() -> Result<TransactionProgress, String> { | ||
// Create assets | ||
let faucet_id = AccountId::try_from(ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN).unwrap(); | ||
let fungible_asset: Asset = FungibleAsset::new(faucet_id, 100).unwrap().into(); | ||
|
||
// Create sender and target account | ||
let sender_account_id = AccountId::try_from(ACCOUNT_ID_SENDER).unwrap(); | ||
|
||
let target_account_id = | ||
AccountId::try_from(ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN).unwrap(); | ||
let sec_key = SecretKey::new(); | ||
let target_pub_key: Word = sec_key.public_key().into(); | ||
let mut pk_sk_bytes = sec_key.to_bytes(); | ||
pk_sk_bytes.append(&mut target_pub_key.to_bytes()); | ||
let target_sk_pk_felt: Vec<Felt> = | ||
pk_sk_bytes.iter().map(|a| Felt::new(*a as u64)).collect::<Vec<Felt>>(); | ||
let target_account = | ||
get_account_with_default_account_code(target_account_id, target_pub_key, None); | ||
|
||
// Create the note | ||
let note = create_p2id_note( | ||
sender_account_id, | ||
target_account_id, | ||
vec![fungible_asset], | ||
NoteType::Public, | ||
RpoRandomCoin::new([Felt::new(1), Felt::new(2), Felt::new(3), Felt::new(4)]), | ||
) | ||
.unwrap(); | ||
|
||
let data_store = | ||
MockDataStore::with_existing(Some(target_account.clone()), Some(vec![note.clone()])); | ||
|
||
let mut executor = TransactionExecutor::new(data_store.clone()).with_tracing(); | ||
executor.load_account(target_account_id).unwrap(); | ||
|
||
let block_ref = data_store.block_header.block_num(); | ||
let note_ids = data_store.notes.iter().map(|note| note.id()).collect::<Vec<_>>(); | ||
|
||
let tx_script_code = ProgramAst::parse(DEFAULT_AUTH_SCRIPT).unwrap(); | ||
|
||
let tx_script_target = executor | ||
.compile_tx_script( | ||
tx_script_code.clone(), | ||
vec![(target_pub_key, target_sk_pk_felt)], | ||
vec![], | ||
) | ||
.unwrap(); | ||
let tx_args_target = TransactionArgs::with_tx_script(tx_script_target); | ||
|
||
// execute transaction | ||
let transaction = executor | ||
.prepare_transaction(target_account_id, block_ref, ¬e_ids, tx_args_target) | ||
.map_err(|e| e.to_string())?; | ||
|
||
let (stack_inputs, advice_inputs) = transaction.get_kernel_inputs(); | ||
let advice_recorder: RecAdviceProvider = advice_inputs.into(); | ||
let mut host = TransactionHost::new(transaction.account().into(), advice_recorder); | ||
|
||
vm_processor::execute( | ||
transaction.program(), | ||
stack_inputs, | ||
&mut host, | ||
ExecutionOptions::default().with_tracing(), | ||
) | ||
.map_err(|e| e.to_string())?; | ||
|
||
Ok(host.tx_progress().clone()) | ||
} |
Oops, something went wrong.