diff --git a/.cargo/config.toml b/.cargo/config.toml index 1267bf2728..2c1f069b58 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,6 +1,9 @@ +[alias] +benchmark = "bench --package benchmarks" + [target.aarch64-unknown-linux-gnu] linker = "aarch64-linux-gnu-gcc" [target.aarch64-unknown-linux-musl] linker = "aarch64-linux-musl-gcc" -rustflags = ["-C", "target-feature=-crt-static"] \ No newline at end of file +rustflags = ["-C", "target-feature=-crt-static"] diff --git a/.github/workflows/rust_ci.yml b/.github/workflows/rust_ci.yml index 38077511bc..a73ab329d5 100644 --- a/.github/workflows/rust_ci.yml +++ b/.github/workflows/rust_ci.yml @@ -1,6 +1,7 @@ on: pull_request: paths: + - "benchmarks/**" - "ironfish-mpc/**" - "ironfish-phase2/**" - "ironfish-rust/**" @@ -14,6 +15,7 @@ on: branches: - master paths: + - "benchmarks/**" - "ironfish-mpc/**" - "ironfish-phase2/**" - "ironfish-rust/**" @@ -45,7 +47,7 @@ jobs: - name: Check that cargo lockfile is up to date run: | - cargo check --locked + cargo check --locked --all-targets # Note: ironfish-zkp is does not need this due to different licensing - name: Check for license headers for ironfish-rust diff --git a/Cargo.lock b/Cargo.lock index 76b30d3532..ee09e59eab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -33,6 +33,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + [[package]] name = "anyhow" version = "1.0.68" @@ -51,6 +57,17 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -89,6 +106,14 @@ dependencies = [ "subtle", ] +[[package]] +name = "benchmarks" +version = "0.1.0" +dependencies = [ + "criterion", + "ironfish_rust", +] + [[package]] name = "bip0039" version = "0.9.0" @@ -225,6 +250,12 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + [[package]] name = "cc" version = "1.0.78" @@ -262,6 +293,33 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ciborium" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c137568cc60b904a7724001b35ce2630fd00d5d84805fbb608ab89509d788f" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346de753af073cc87b52b2083a506b38ac176a44cfb05497b622e27be899b369" + +[[package]] +name = "ciborium-ll" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213030a2b5a4e0c0892b6652260cf6ccac84827b83a85a534e178e3906c4cf1b" +dependencies = [ + "ciborium-io", + "half", +] + [[package]] name = "cipher" version = "0.3.0" @@ -271,6 +329,27 @@ dependencies = [ "generic-array", ] +[[package]] +name = "clap" +version = "3.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" +dependencies = [ + "bitflags", + "clap_lex", + "indexmap", + "textwrap", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + [[package]] name = "constant_time_eq" version = "0.1.5" @@ -298,6 +377,42 @@ dependencies = [ "libc", ] +[[package]] +name = "criterion" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c76e09c1aae2bc52b3d2f29e13c6572553b30c4aa1b8a49fd70de6412654cb" +dependencies = [ + "anes", + "atty", + "cast", + "ciborium", + "clap", + "criterion-plot", + "itertools", + "lazy_static", + "num-traits", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +dependencies = [ + "cast", + "itertools", +] + [[package]] name = "crossbeam-channel" version = "0.5.6" @@ -568,6 +683,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "half" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" + [[package]] name = "halo2_gadgets" version = "0.2.0" @@ -601,6 +722,21 @@ dependencies = [ "tracing", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + [[package]] name = "hermit-abi" version = "0.2.6" @@ -664,6 +800,16 @@ dependencies = [ "serde", ] +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown", +] + [[package]] name = "ironfish-phase2" version = "0.2.2" @@ -748,11 +894,26 @@ dependencies = [ "zcash_proofs", ] +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" + [[package]] name = "js-sys" -version = "0.3.60" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" dependencies = [ "wasm-bindgen", ] @@ -929,7 +1090,7 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" dependencies = [ - "hermit-abi", + "hermit-abi 0.2.6", "libc", ] @@ -939,6 +1100,12 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" +[[package]] +name = "oorandom" +version = "11.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" + [[package]] name = "opaque-debug" version = "0.3.0" @@ -973,6 +1140,12 @@ dependencies = [ "zcash_note_encryption", ] +[[package]] +name = "os_str_bytes" +version = "6.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ceedf44fb00f2d1984b0bc98102627ce622e083e49a5bacdb3e514fa4238e267" + [[package]] name = "pairing" version = "0.22.0" @@ -1042,6 +1215,34 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +[[package]] +name = "plotters" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" + +[[package]] +name = "plotters-svg" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f" +dependencies = [ + "plotters-backend", +] + [[package]] name = "poly1305" version = "0.7.2" @@ -1276,6 +1477,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "ryu" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" + [[package]] name = "salsa20" version = "0.9.0" @@ -1286,6 +1493,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "scopeguard" version = "1.1.0" @@ -1312,6 +1528,17 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_json" +version = "1.0.96" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +dependencies = [ + "itoa", + "ryu", + "serde", +] + [[package]] name = "sha2" version = "0.9.9" @@ -1366,6 +1593,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +[[package]] +name = "textwrap" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" + [[package]] name = "thiserror" version = "1.0.38" @@ -1414,6 +1647,16 @@ dependencies = [ "zeroize", ] +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -1516,6 +1759,16 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "walkdir" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" @@ -1530,9 +1783,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1540,9 +1793,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" dependencies = [ "bumpalo", "log", @@ -1555,9 +1808,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1565,9 +1818,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", @@ -1578,9 +1831,19 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" + +[[package]] +name = "web-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" +dependencies = [ + "js-sys", + "wasm-bindgen", +] [[package]] name = "winapi" @@ -1598,6 +1861,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/Cargo.toml b/Cargo.toml index 975927a49a..f9f280c5ea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,7 @@ [workspace] members = [ + "benchmarks", "ironfish-mpc", "ironfish-phase2", "ironfish-rust", diff --git a/README.md b/README.md index c648761989..044a3cae74 100644 --- a/README.md +++ b/README.md @@ -19,9 +19,10 @@ The following steps should only be used to install if you are planning on contri 1. Install [Rust](https://www.rust-lang.org/learn/get-started). 1. Install [Yarn](https://classic.yarnpkg.com/en/docs/install). 1. Windows: + 1. Install the current version of Python from the [Microsoft Store package](https://www.microsoft.com/en-us/p/python-310/9pjpw5ldxlz5). 1. Install Visual C++ Build Environment: [Visual Studio Build Tools](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=BuildTools) - (using "Visual C++ build tools" or "Desktop development with C++" workload) + (using "Visual C++ build tools" or "Desktop development with C++" workload) If the above steps didn't work for you, please visit [Microsoft's Node.js Guidelines for Windows](https://github.com/Microsoft/nodejs-guidelines/blob/master/windows-environment.md#compiling-native-addon-modules) for additional tips. @@ -60,6 +61,16 @@ Once your environment is set up - you can run the CLI by following [these direct 1. Run `yarn test:watch` in ./ironfish or ./ironfish-cli if you want the tests to run on change 1. Run `yarn test:coverage:html` if you want to export the coverage in an easy-to-use format (open the index.html file in the coverage folder of the project) +## Running Benchmarks and Performance Tests + +1. Rust benchmarks: + - `cargo benchmark` is a cargo alias, defined in `./.cargo/config.toml` + 1. `cargo benchmark` to run all benchmark tests + 1. `cargo benchmark -- simple` to run only benchmarks containing the text 'simple' in the name +1. Typescript benchmarks: + 1. `cd ironfish` + 1. `yarn test:perf` + ## Structure of the repository - [ironfish](./ironfish/README.md): The library that contains the IronfishSDK and all Ironfish code written in TypeScript. diff --git a/benchmarks/Cargo.toml b/benchmarks/Cargo.toml new file mode 100644 index 0000000000..95fc91941d --- /dev/null +++ b/benchmarks/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "benchmarks" +version = "0.1.0" +license = "MPL-2.0" + +[package.authors] +workspace = true + +[package.edition] +workspace = true + +[dependencies] +criterion = "0.4" +ironfish_rust = { path = "../ironfish-rust", features = ["benchmark"] } + +[[bench]] +name = "asset" +harness = false + +[[bench]] +name = "merkle_note" +harness = false + +[[bench]] +name = "sapling_key" +harness = false + +[[bench]] +name = "transaction" +harness = false diff --git a/benchmarks/README.md b/benchmarks/README.md new file mode 100644 index 0000000000..8a54f3b2a5 --- /dev/null +++ b/benchmarks/README.md @@ -0,0 +1,11 @@ +# benchmarks + +A collection of benchmarks and other related performance tests. + +These are for development purposes only and do not get shipped with the Node. As such, changes in this package do not require a version bump for releases. + +## Usage + +`cargo benchmark` - run all benchmarks + +`cargo benchmark -- simple` - run benchmarks with "simple" in the name. diff --git a/benchmarks/benches/asset.rs b/benchmarks/benches/asset.rs new file mode 100644 index 0000000000..5afe86a60e --- /dev/null +++ b/benchmarks/benches/asset.rs @@ -0,0 +1,47 @@ +use criterion::{black_box, criterion_group, criterion_main, BatchSize, Criterion}; +use ironfish_rust::{ + assets::asset::{Asset, METADATA_LENGTH, NAME_LENGTH}, + SaplingKey, +}; + +pub fn new(c: &mut Criterion) { + c.bench_function("asset::new", |b| { + b.iter_batched( + // Setup + || { + let key = SaplingKey::generate_key(); + key.public_address() + }, + // Benchmark + |addr| { + Asset::new(addr, black_box("asset"), black_box("metadata")).unwrap(); + }, + BatchSize::SmallInput, + ); + }); +} + +pub fn new_with_nonce(c: &mut Criterion) { + c.bench_function("asset::new_with_nonce", |b| { + b.iter_batched( + // Setup + || { + let key = SaplingKey::generate_key(); + key.public_address() + }, + // Benchmark + |addr| { + let _ = Asset::new_with_nonce( + addr, + black_box([b'a'; NAME_LENGTH]), + black_box([b'b'; METADATA_LENGTH]), + 0, + ); + }, + BatchSize::SmallInput, + ); + }); +} + +criterion_group!(benches, new, new_with_nonce); +criterion_main!(benches); diff --git a/benchmarks/benches/merkle_note.rs b/benchmarks/benches/merkle_note.rs new file mode 100644 index 0000000000..5ad7a33f5d --- /dev/null +++ b/benchmarks/benches/merkle_note.rs @@ -0,0 +1,70 @@ +use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; +use ironfish_rust::{ + assets::asset_identifier::NATIVE_ASSET, keys::EphemeralKeyPair, MerkleNote, Note, SaplingKey, + ValueCommitment, +}; + +pub fn decrypt_note_for_spender(c: &mut Criterion) { + c.bench_function("merkle_note::decrypt_note_for_spender", |b| { + b.iter_batched( + // Setup + || { + let spender_key = SaplingKey::generate_key(); + let receiver_key = SaplingKey::generate_key(); + + let note = Note::new( + receiver_key.public_address(), + 42, + "", + NATIVE_ASSET, + spender_key.public_address(), + ); + + let ekp = EphemeralKeyPair::new(); + let value_commitment = ValueCommitment::new(note.value(), note.asset_generator()); + let merkle_note = MerkleNote::new(&spender_key, ¬e, &value_commitment, &ekp); + + return (spender_key.outgoing_view_key().clone(), merkle_note); + }, + // Benchmark + |(ovk, merkle_note)| { + merkle_note.decrypt_note_for_spender(&ovk).unwrap(); + }, + BatchSize::SmallInput, + ); + }); +} + +pub fn decrypt_note_for_owner(c: &mut Criterion) { + c.bench_function("merkle_note::decrypt_note_for_owner", |b| { + b.iter_batched( + // Setup + || { + let spender_key = SaplingKey::generate_key(); + let receiver_key = SaplingKey::generate_key(); + + let note = Note::new( + receiver_key.public_address(), + 42, + "", + NATIVE_ASSET, + spender_key.public_address(), + ); + + let ekp = EphemeralKeyPair::new(); + let value_commitment = ValueCommitment::new(note.value(), note.asset_generator()); + let merkle_note = MerkleNote::new(&spender_key, ¬e, &value_commitment, &ekp); + + return (receiver_key.incoming_view_key().clone(), merkle_note); + }, + // Benchmark + |(ivk, merkle_note)| { + merkle_note.decrypt_note_for_owner(&ivk).unwrap(); + }, + BatchSize::SmallInput, + ); + }); +} + +criterion_group!(benches, decrypt_note_for_spender, decrypt_note_for_owner); +criterion_main!(benches); diff --git a/benchmarks/benches/sapling_key.rs b/benchmarks/benches/sapling_key.rs new file mode 100644 index 0000000000..0df95a8094 --- /dev/null +++ b/benchmarks/benches/sapling_key.rs @@ -0,0 +1,13 @@ +use criterion::{criterion_group, criterion_main, Criterion}; +use ironfish_rust::SaplingKey; + +pub fn generate_key(c: &mut Criterion) { + c.bench_function("sapling_key::generate_key", |b| { + b.iter(|| { + SaplingKey::generate_key(); + }); + }); +} + +criterion_group!(benches, generate_key); +criterion_main!(benches); diff --git a/benchmarks/benches/transaction.rs b/benchmarks/benches/transaction.rs new file mode 100644 index 0000000000..66ebbc028c --- /dev/null +++ b/benchmarks/benches/transaction.rs @@ -0,0 +1,69 @@ +use benchmarks::slow_config; +use criterion::{criterion_group, criterion_main, Criterion}; +use ironfish_rust::{ + assets::{asset::Asset, asset_identifier::NATIVE_ASSET}, + test_util::make_fake_witness, + Note, ProposedTransaction, SaplingKey, +}; + +pub fn simple(c: &mut Criterion) { + let key = SaplingKey::generate_key(); + let public_address = key.public_address(); + + let spend_note = Note::new(public_address, 42, "", NATIVE_ASSET, public_address); + let witness = make_fake_witness(&spend_note); + + let out_note = Note::new(public_address, 41, "", NATIVE_ASSET, public_address); + + c.bench_function("transaction::simple", |b| { + b.iter(|| { + let mut proposed = ProposedTransaction::new(key.clone()); + + proposed.add_spend(spend_note.clone(), &witness).unwrap(); + proposed.add_output(out_note.clone()).unwrap(); + + let tx = proposed.post(None, 1).unwrap(); + + assert_eq!(tx.spends().len(), 1); + assert_eq!(tx.outputs().len(), 1); + }) + }); +} + +pub fn all_descriptions(c: &mut Criterion) { + let key = SaplingKey::generate_key(); + let public_address = key.public_address(); + + let spend_note = Note::new(public_address, 42, "", NATIVE_ASSET, public_address); + let witness = make_fake_witness(&spend_note); + + let out_note = Note::new(public_address, 41, "", NATIVE_ASSET, public_address); + + let asset = Asset::new(public_address, "Testcoin", "A really cool coin").unwrap(); + let asset_value = 10; + + c.bench_function("transaction::all_descriptions", |b| { + b.iter(|| { + let mut proposed = ProposedTransaction::new(key.clone()); + + proposed.add_spend(spend_note.clone(), &witness).unwrap(); + proposed.add_output(out_note.clone()).unwrap(); + proposed.add_mint(asset, asset_value).unwrap(); + proposed.add_burn(*asset.id(), asset_value).unwrap(); + + let tx = proposed.post(None, 1).unwrap(); + + assert_eq!(tx.spends().len(), 1); + assert_eq!(tx.outputs().len(), 1); + assert_eq!(tx.mints().len(), 1); + assert_eq!(tx.burns().len(), 1); + }) + }); +} + +criterion_group! { + name = slow_benches; + config = slow_config(); + targets = simple, all_descriptions +} +criterion_main!(slow_benches); diff --git a/benchmarks/src/lib.rs b/benchmarks/src/lib.rs new file mode 100644 index 0000000000..c25e86264f --- /dev/null +++ b/benchmarks/src/lib.rs @@ -0,0 +1,12 @@ +use std::time::Duration; + +use criterion::Criterion; + +pub const LONG_BENCH_DURATION: Duration = Duration::from_secs(60); +pub const LONG_BENCH_SAMPLE_SIZE: usize = 50; + +pub fn slow_config() -> Criterion { + Criterion::default() + .measurement_time(LONG_BENCH_DURATION) + .sample_size(LONG_BENCH_SAMPLE_SIZE) +} diff --git a/ironfish-rust/Cargo.toml b/ironfish-rust/Cargo.toml index aac84444aa..62c6498a06 100644 --- a/ironfish-rust/Cargo.toml +++ b/ironfish-rust/Cargo.toml @@ -9,6 +9,9 @@ workspace = true [package.edition] workspace = true +[features] +benchmark = [] + [lib] name = "ironfish_rust" path = "src/lib.rs" diff --git a/ironfish-rust/src/lib.rs b/ironfish-rust/src/lib.rs index a32b9ab661..9852c64242 100644 --- a/ironfish-rust/src/lib.rs +++ b/ironfish-rust/src/lib.rs @@ -30,8 +30,11 @@ pub use { }, }; -#[cfg(test)] -pub(crate) mod test_util; // I'm not sure if this is the right way to publish the utility library. +#[cfg(any(test, feature = "benchmark"))] +pub mod test_util; + +#[cfg(feature = "benchmark")] +pub use ironfish_zkp::primitives::ValueCommitment; // The main entry-point to the sapling API. Construct this with loaded parameters, and then call // methods on it to do the actual work. diff --git a/ironfish-rust/src/test_util.rs b/ironfish-rust/src/test_util.rs index ca8283d478..47254864b8 100644 --- a/ironfish-rust/src/test_util.rs +++ b/ironfish-rust/src/test_util.rs @@ -7,13 +7,13 @@ use super::{ witness::{Witness, WitnessNode}, MerkleNoteHash, }; +use bls12_381::Scalar; use ironfish_zkp::constants::TREE_DEPTH; use rand::{thread_rng, Rng}; /// Given a note, construct a Witness with a valid root_hash and authentication /// path placing that note at a random location in a Merkle tree. -#[cfg(test)] -pub(crate) fn make_fake_witness(note: &Note) -> Witness { +pub fn make_fake_witness(note: &Note) -> Witness { let mut rng = thread_rng(); let mut buffer = [0u8; 64]; thread_rng().fill(&mut buffer[..]); @@ -39,8 +39,6 @@ pub(crate) fn make_fake_witness(note: &Note) -> Witness { /// Currently marked for test-only compilation, /// but it may be useful to publish /// something like this in the future. -#[cfg(test)] -use bls12_381::Scalar; pub(crate) fn auth_path_to_root_hash( auth_path: &[WitnessNode], diff --git a/ironfish-rust/src/transaction/mod.rs b/ironfish-rust/src/transaction/mod.rs index 4a6f7959e4..691d413d8f 100644 --- a/ironfish-rust/src/transaction/mod.rs +++ b/ironfish-rust/src/transaction/mod.rs @@ -642,6 +642,14 @@ impl Transaction { &self.outputs } + pub fn mints(&self) -> &Vec { + &self.mints + } + + pub fn burns(&self) -> &Vec { + &self.burns + } + /// Get the transaction fee for this transaction. Miners should generally /// expect this to be positive (or they would lose money mining it!). /// The miners_fee transaction would be a special case.