diff --git a/Cargo.lock b/Cargo.lock index 02deb3e7a..2ca104e60 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3370,6 +3370,8 @@ dependencies = [ "prost", "prost-build", "prost-types", + "risc0-zkvm", + "risc0-zkvm-platform", "serde", "serde_json", "sha2 0.10.7", @@ -3380,6 +3382,7 @@ dependencies = [ "tokio", "tracing", "wiremock", + "zk-cycle-macros", ] [[package]] @@ -5554,11 +5557,16 @@ version = "0.1.0" dependencies = [ "anyhow", "bincode", + "bytemuck", + "once_cell", + "parking_lot 0.11.2", "risc0-circuit-rv32im", "risc0-zkp", "risc0-zkvm", + "risc0-zkvm-platform", "serde", "sov-rollup-interface", + "zk-cycle-utils", ] [[package]] @@ -6715,6 +6723,8 @@ dependencies = [ "hex", "jsonrpsee 0.18.2", "rand 0.7.3", + "risc0-zkvm", + "risc0-zkvm-platform", "schemars", "serde", "serde_json", @@ -6723,6 +6733,7 @@ dependencies = [ "sov-rollup-interface", "sov-state", "thiserror", + "zk-cycle-macros", ] [[package]] @@ -6754,12 +6765,16 @@ dependencies = [ "borsh", "hex", "jmt", + "risc0-zkvm", + "risc0-zkvm-platform", "serde", "sov-modules-api", "sov-rollup-interface", "sov-state", "thiserror", "tracing", + "zk-cycle-macros", + "zk-cycle-utils", ] [[package]] @@ -6834,6 +6849,8 @@ dependencies = [ "borsh", "clap", "jsonrpsee 0.18.2", + "risc0-zkvm", + "risc0-zkvm-platform", "schemars", "serde", "serde_json", @@ -6842,6 +6859,8 @@ dependencies = [ "sov-rollup-interface", "sov-state", "tempfile", + "zk-cycle-macros", + "zk-cycle-utils", ] [[package]] @@ -6852,6 +6871,8 @@ dependencies = [ "borsh", "hex", "jmt", + "risc0-zkvm", + "risc0-zkvm-platform", "serde", "sha2 0.10.7", "sov-db", @@ -6859,6 +6880,7 @@ dependencies = [ "sov-rollup-interface", "tempfile", "thiserror", + "zk-cycle-macros", ] [[package]] @@ -8244,6 +8266,30 @@ dependencies = [ "zstd 0.11.2+zstd.1.5.2", ] +[[package]] +name = "zk-cycle-macros" +version = "0.1.0" +dependencies = [ + "anyhow", + "borsh", + "proc-macro2 1.0.66", + "quote 1.0.32", + "risc0-zkvm", + "risc0-zkvm-platform", + "syn 1.0.109", + "trybuild", + "zk-cycle-macros", + "zk-cycle-utils", +] + +[[package]] +name = "zk-cycle-utils" +version = "0.1.0" +dependencies = [ + "risc0-zkvm", + "risc0-zkvm-platform", +] + [[package]] name = "zstd" version = "0.11.2+zstd.1.5.2" diff --git a/Cargo.toml b/Cargo.toml index df89c0944..202a13699 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,10 @@ members = [ "examples/demo-nft-module", "full-node/db/sov-db", "full-node/sov-sequencer", + "utils/zk-cycle-macros", + "utils/zk-cycle-utils", "full-node/sov-ethereum", + "full-node/sov-stf-runner", "module-system/sov-cli", diff --git a/adapters/celestia/Cargo.toml b/adapters/celestia/Cargo.toml index afdb440a4..f7f55a47b 100644 --- a/adapters/celestia/Cargo.toml +++ b/adapters/celestia/Cargo.toml @@ -27,19 +27,25 @@ serde_json = { workspace = true } tokio = { workspace = true, optional = true } thiserror = { workspace = true } tracing = { workspace = true } +zk-cycle-macros = {path = "../../utils/zk-cycle-macros", optional=true} +risc0-zkvm = { version = "0.16", default-features = false, features = ["std"], optional=true} +risc0-zkvm-platform = { version = "0.16", optional=true} sov-rollup-interface = { path = "../../rollup-interface" } nmt-rs = { git = "https://github.com/Sovereign-Labs/nmt-rs.git", rev = "dd37588444fca72825d11fe4a46838f66525c49f", features = ["serde", "borsh"] } + [dev-dependencies] postcard = { version = "1", features = ["use-std"] } proptest = { version = "1.2" } wiremock = "0.5" + [build-dependencies] prost-build = { version = "0.11" } [features] default = ["native"] native = ["dep:tokio", "dep:jsonrpsee"] +bench = ["zk-cycle-macros/bench","risc0-zkvm","risc0-zkvm-platform"] verifier = [] diff --git a/adapters/celestia/src/verifier/mod.rs b/adapters/celestia/src/verifier/mod.rs index 843f0fa76..ece876879 100644 --- a/adapters/celestia/src/verifier/mod.rs +++ b/adapters/celestia/src/verifier/mod.rs @@ -13,6 +13,8 @@ pub mod address; pub mod proofs; use proofs::*; +#[cfg(all(target_os = "zkvm", feature = "bench"))] +use zk_cycle_macros::cycle_tracker; use self::address::CelestiaAddress; use crate::share_commit::recreate_commitment; @@ -151,6 +153,7 @@ impl da::DaVerifier for CelestiaVerifier { } } + #[cfg_attr(all(target_os = "zkvm", feature = "bench"), cycle_tracker)] fn verify_relevant_tx_list( &self, block_header: &::BlockHeader, @@ -248,6 +251,7 @@ impl da::DaVerifier for CelestiaVerifier { let mut blob_iter = blob_ref.data(); let mut blob_data = vec![0; blob_iter.remaining()]; blob_iter.copy_to_slice(blob_data.as_mut_slice()); + let tx_data = tx.data().accumulator(); match tx_data { diff --git a/adapters/risc0/Cargo.toml b/adapters/risc0/Cargo.toml index e30c457e2..95812f9f1 100644 --- a/adapters/risc0/Cargo.toml +++ b/adapters/risc0/Cargo.toml @@ -15,13 +15,17 @@ readme = "README.md" anyhow = { workspace = true } bincode = { workspace = true } risc0-zkvm = { version = "0.16", default-features = false, features = ['std'] } +risc0-zkvm-platform = { version = "0.16" } risc0-zkp = { version = "0.16", optional = true } risc0-circuit-rv32im = { version = "0.16", optional = true } serde = { workspace = true } - +bytemuck = "1.13.1" +once_cell = { version = "1.7.2", optional = true} +parking_lot = { version = "0.11.1", optional = true} +zk-cycle-utils = { path = "../../utils/zk-cycle-utils"} sov-rollup-interface = { path = "../../rollup-interface" } - [features] default = ["native"] native = ["risc0-zkvm/prove", "dep:risc0-zkp", "dep:risc0-circuit-rv32im"] +bench = ["once_cell","parking_lot"] diff --git a/adapters/risc0/src/host.rs b/adapters/risc0/src/host.rs index 56f91d672..9969dbd1c 100644 --- a/adapters/risc0/src/host.rs +++ b/adapters/risc0/src/host.rs @@ -7,7 +7,11 @@ use risc0_zkvm::{ }; use sov_rollup_interface::zk::{Zkvm, ZkvmHost}; use sov_rollup_interface::AddressTrait; +#[cfg(feature = "bench")] +use zk_cycle_utils::{cycle_count_callback, get_syscall_name, get_syscall_name_cycles}; +#[cfg(feature = "bench")] +use crate::metrics::metrics_callback; use crate::Risc0MethodId; pub struct Risc0Host<'a> { @@ -16,9 +20,28 @@ pub struct Risc0Host<'a> { } impl<'a> Risc0Host<'a> { + #[cfg(not(feature = "bench"))] pub fn new(elf: &'a [u8]) -> Self { + let default_env = ExecutorEnvBuilder::default(); + + Self { + env: RefCell::new(default_env), + elf, + } + } + + #[cfg(feature = "bench")] + pub fn new(elf: &'a [u8]) -> Self { + let mut default_env = ExecutorEnvBuilder::default(); + + let metrics_syscall_name = get_syscall_name(); + default_env.io_callback(metrics_syscall_name, metrics_callback); + + let cycles_syscall_name = get_syscall_name_cycles(); + default_env.io_callback(cycles_syscall_name, cycle_count_callback); + Self { - env: RefCell::new(ExecutorEnvBuilder::default()), + env: RefCell::new(default_env), elf, } } diff --git a/adapters/risc0/src/lib.rs b/adapters/risc0/src/lib.rs index ee3d48bdc..76c694a2c 100644 --- a/adapters/risc0/src/lib.rs +++ b/adapters/risc0/src/lib.rs @@ -6,6 +6,9 @@ pub mod guest; #[cfg(feature = "native")] pub mod host; +#[cfg(feature = "bench")] +pub mod metrics; + #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct Risc0MethodId([u32; 8]); diff --git a/adapters/risc0/src/metrics.rs b/adapters/risc0/src/metrics.rs new file mode 100644 index 000000000..6dd56b0e5 --- /dev/null +++ b/adapters/risc0/src/metrics.rs @@ -0,0 +1,33 @@ +use std::collections::HashMap; + +use once_cell::sync::Lazy; +use parking_lot::Mutex; + +pub static GLOBAL_HASHMAP: Lazy>> = + Lazy::new(|| Mutex::new(HashMap::new())); + +pub fn add_value(metric: String, value: u64) { + let mut hashmap = GLOBAL_HASHMAP.lock(); + hashmap + .entry(metric) + .and_modify(|(sum, count)| { + *sum += value; + *count += 1; + }) + .or_insert((value, 1)); +} + +pub fn deserialize_custom(serialized: &[u8]) -> (String, u64) { + let null_pos = serialized.iter().position(|&b| b == 0).unwrap(); + let (string_bytes, size_bytes_with_null) = serialized.split_at(null_pos); + let size_bytes = &size_bytes_with_null[1..]; // Skip the null terminator + let string = String::from_utf8(string_bytes.to_vec()).unwrap(); + let size = u64::from_ne_bytes(size_bytes.try_into().unwrap()); // Convert bytes back into usize + (string, size) +} + +pub fn metrics_callback(input: &[u8]) -> Vec { + let met_tuple = deserialize_custom(input); + add_value(met_tuple.0, met_tuple.1); + vec![] +} diff --git a/examples/demo-prover/Cargo.lock b/examples/demo-prover/Cargo.lock index e501f8a5b..271eeea6b 100644 --- a/examples/demo-prover/Cargo.lock +++ b/examples/demo-prover/Cargo.lock @@ -59,6 +59,21 @@ dependencies = [ "memchr", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anstream" version = "0.3.2" @@ -114,6 +129,12 @@ version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" +[[package]] +name = "arc-swap" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" + [[package]] name = "arrayvec" version = "0.7.4" @@ -452,6 +473,21 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "time 0.1.45", + "wasm-bindgen", + "winapi", +] + [[package]] name = "cipher" version = "0.4.4" @@ -639,6 +675,27 @@ dependencies = [ "typenum", ] +[[package]] +name = "csv" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "626ae34994d3d8d668f4269922248239db4ae42d538b14c398b74a52208e8086" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" +dependencies = [ + "memchr", +] + [[package]] name = "curve25519-dalek" version = "3.2.0" @@ -704,6 +761,17 @@ dependencies = [ "zeroize", ] +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -717,6 +785,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "destructure_traitobject" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c877555693c14d2f84191cfd3ad8582790fc52b5e2274b40b59cf5f5cea25c7" + [[package]] name = "digest" version = "0.9.0" @@ -746,6 +820,16 @@ dependencies = [ "dirs-sys", ] +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + [[package]] name = "dirs-sys" version = "0.4.1" @@ -758,6 +842,17 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "downcast-rs" version = "1.2.0" @@ -860,6 +955,12 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2b183d6ce6ca4cf30e3db37abf5b52568b5f9015c97d9fbdd7026aa5dcdd758" +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + [[package]] name = "encoding_rs" version = "0.8.32" @@ -869,6 +970,19 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "env_logger" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -1271,6 +1385,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + [[package]] name = "hyper" version = "0.14.27" @@ -1340,6 +1460,29 @@ dependencies = [ "tokio-native-tls", ] +[[package]] +name = "iana-time-zone" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "ics23" version = "0.10.1" @@ -1540,7 +1683,7 @@ dependencies = [ "globset", "hyper", "jsonrpsee-types 0.16.2", - "parking_lot", + "parking_lot 0.12.1", "rand 0.8.5", "rustc-hash", "serde", @@ -1564,7 +1707,7 @@ dependencies = [ "globset", "hyper", "jsonrpsee-types 0.18.2", - "parking_lot", + "parking_lot 0.12.1", "rand 0.8.5", "rustc-hash", "serde", @@ -1712,6 +1855,8 @@ dependencies = [ "prost", "prost-build", "prost-types", + "risc0-zkvm", + "risc0-zkvm-platform", "serde", "serde_json", "sha2 0.10.7", @@ -1721,6 +1866,7 @@ dependencies = [ "thiserror", "tokio", "tracing", + "zk-cycle-macros", ] [[package]] @@ -1816,6 +1962,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + [[package]] name = "linux-raw-sys" version = "0.3.8" @@ -1843,6 +1995,41 @@ name = "log" version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +dependencies = [ + "serde", +] + +[[package]] +name = "log-mdc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a94d21414c1f4a51209ad204c1776a3d0765002c76c6abcb602a6f09f1e881c7" + +[[package]] +name = "log4rs" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d36ca1786d9e79b8193a68d480a0907b612f109537115c6ff655a3a1967533fd" +dependencies = [ + "anyhow", + "arc-swap", + "chrono", + "derivative", + "fnv", + "humantime", + "libc", + "log", + "log-mdc", + "parking_lot 0.12.1", + "serde", + "serde-value", + "serde_json", + "serde_yaml", + "thiserror", + "thread-id", + "typemap-ors", + "winapi", +] [[package]] name = "lz4-sys" @@ -2135,12 +2322,32 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "ordered-float" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87" +dependencies = [ + "num-traits", +] + [[package]] name = "overload" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core 0.8.6", +] + [[package]] name = "parking_lot" version = "0.12.1" @@ -2148,7 +2355,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core", + "parking_lot_core 0.9.8", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall 0.2.16", + "smallvec", + "winapi", ] [[package]] @@ -2299,6 +2520,20 @@ dependencies = [ "syn 2.0.26", ] +[[package]] +name = "prettytable-rs" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eea25e07510aa6ab6547308ebe3c036016d162b8da920dbb079e3ba8acf3d95a" +dependencies = [ + "csv", + "encode_unicode", + "is-terminal", + "lazy_static", + "term", + "unicode-width", +] + [[package]] name = "proc-macro-crate" version = "0.1.5" @@ -2337,7 +2572,7 @@ dependencies = [ "fnv", "lazy_static", "memchr", - "parking_lot", + "parking_lot 0.12.1", "thiserror", ] @@ -2634,11 +2869,16 @@ version = "0.1.0" dependencies = [ "anyhow", "bincode", + "bytemuck", + "once_cell", + "parking_lot 0.11.2", "risc0-circuit-rv32im", "risc0-zkp", "risc0-zkvm", + "risc0-zkvm-platform", "serde", "sov-rollup-interface", + "zk-cycle-utils", ] [[package]] @@ -2918,6 +3158,12 @@ dependencies = [ "untrusted", ] +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + [[package]] name = "ryu" version = "1.0.15" @@ -3014,6 +3260,16 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-value" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" +dependencies = [ + "ordered-float", + "serde", +] + [[package]] name = "serde_bytes" version = "0.11.12" @@ -3088,6 +3344,18 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_yaml" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" +dependencies = [ + "indexmap 1.9.3", + "ryu", + "serde", + "yaml-rust", +] + [[package]] name = "sha-1" version = "0.9.8" @@ -3297,22 +3565,66 @@ name = "sov-demo-prover-host" version = "0.1.0" dependencies = [ "anyhow", + "bincode", "borsh", "const-rollup-config", "demo-stf", + "env_logger", "hex", "jsonrpsee 0.16.2", "jupiter", + "log", + "log4rs", "methods", + "once_cell", + "parking_lot 0.11.2", + "prettytable-rs", + "regex", "risc0-adapter", "risc0-zkvm", "serde", "serde_json", "sha2 0.10.7", + "sov-demo-rollup", + "sov-modules-api", + "sov-rollup-interface", + "sov-state", + "sov-stf-runner", + "tempfile", + "tokio", + "tracing", + "tracing-subscriber", + "zk-cycle-macros", +] + +[[package]] +name = "sov-demo-rollup" +version = "0.1.0" +dependencies = [ + "anyhow", + "async-trait", + "borsh", + "bytes", + "const-rollup-config", + "demo-stf", + "futures", + "hex", + "jmt", + "jsonrpsee 0.18.2", + "jupiter", + "risc0-adapter", + "serde", + "serde_json", + "sov-bank", + "sov-db", + "sov-election", "sov-modules-api", + "sov-modules-stf-template", "sov-rollup-interface", + "sov-sequencer", "sov-state", "sov-stf-runner", + "sov-value-setter", "tokio", "tracing", "tracing-subscriber", @@ -3616,7 +3928,7 @@ dependencies = [ "subtle", "subtle-encoding", "tendermint-proto", - "time", + "time 0.3.23", "zeroize", ] @@ -3635,7 +3947,27 @@ dependencies = [ "serde", "serde_bytes", "subtle-encoding", - "time", + "time 0.3.23", +] + +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi", +] + +[[package]] +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +dependencies = [ + "winapi-util", ] [[package]] @@ -3658,6 +3990,17 @@ dependencies = [ "syn 2.0.26", ] +[[package]] +name = "thread-id" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ee93aa2b8331c0fec9091548843f2c90019571814057da3b783f9de09349d73" +dependencies = [ + "libc", + "redox_syscall 0.2.16", + "winapi", +] + [[package]] name = "thread_local" version = "1.1.7" @@ -3668,6 +4011,17 @@ dependencies = [ "once_cell", ] +[[package]] +name = "time" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi", +] + [[package]] name = "time" version = "0.3.23" @@ -3721,7 +4075,7 @@ dependencies = [ "libc", "mio", "num_cpus", - "parking_lot", + "parking_lot 0.12.1", "pin-project-lite", "signal-hook-registry", "socket2", @@ -3932,6 +4286,15 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +[[package]] +name = "typemap-ors" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a68c24b707f02dd18f1e4ccceb9d49f2058c2fb86384ef9972592904d7a28867" +dependencies = [ + "unsafe-any-ors", +] + [[package]] name = "typenum" version = "1.16.0" @@ -3983,6 +4346,21 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + +[[package]] +name = "unsafe-any-ors" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a303d30665362d9680d7d91d78b23f5f899504d4f08b3c4cf08d055d87c0ad" +dependencies = [ + "destructure_traitobject", +] + [[package]] name = "untrusted" version = "0.7.1" @@ -4039,6 +4417,12 @@ version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -4167,12 +4551,30 @@ 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" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -4266,6 +4668,15 @@ dependencies = [ "tap", ] +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] + [[package]] name = "zeroize" version = "1.6.0" @@ -4302,10 +4713,29 @@ dependencies = [ "hmac", "pbkdf2", "sha1", - "time", + "time 0.3.23", "zstd", ] +[[package]] +name = "zk-cycle-macros" +version = "0.1.0" +dependencies = [ + "anyhow", + "borsh", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "zk-cycle-utils" +version = "0.1.0" +dependencies = [ + "risc0-zkvm", + "risc0-zkvm-platform", +] + [[package]] name = "zstd" version = "0.11.2+zstd.1.5.2" diff --git a/examples/demo-prover/Cargo.toml b/examples/demo-prover/Cargo.toml index bd4544d1c..a9998ca01 100644 --- a/examples/demo-prover/Cargo.toml +++ b/examples/demo-prover/Cargo.toml @@ -8,6 +8,7 @@ resolver = "2" [workspace.dependencies] anyhow = "1.0.68" borsh = { version = "0.10.3", features = ["rc", "bytes"] } +bincode = "1.3.3" hex = "0.4.3" jsonrpsee = "0.16.2" serde = { version = "1.0.137", features = ["derive", "rc"] } @@ -16,6 +17,7 @@ sha2 = "0.10.6" risc0-zkvm = { version = "0.16" } risc0-build = { version = "0.16" } tokio = { version = "1", features = ["full"] } +tempfile = "3.6.0" # Always optimize; building and running the guest takes much longer without optimization. [profile.dev] diff --git a/examples/demo-prover/host/Cargo.toml b/examples/demo-prover/host/Cargo.toml index 756610af4..eff32b335 100644 --- a/examples/demo-prover/host/Cargo.toml +++ b/examples/demo-prover/host/Cargo.toml @@ -8,6 +8,7 @@ resolver = "2" [dependencies] anyhow = { workspace = true } borsh = { workspace = true } +bincode = {workspace = true} hex = { workspace = true } jsonrpsee = { workspace = true, features = ["http-client", "server"] } risc0-zkvm = { workspace = true } @@ -18,13 +19,34 @@ tokio = { workspace = true } tracing = "0.1.37" tracing-subscriber = "0.3.16" -jupiter = { path = "../../../adapters/celestia", features = ["native"] } +jupiter = { path = "../../../adapters/celestia", features = ["native","bench"] } demo-stf = { path = "../../demo-stf" } sov-rollup-interface = { path = "../../../rollup-interface" } risc0-adapter = { path = "../../../adapters/risc0" } const-rollup-config = { path = "../../const-rollup-config" } sov-modules-api = { path = "../../../module-system/sov-modules-api", features = ["native"] } sov-state = { path = "../../../module-system/sov-state", features = ["native"] } +zk-cycle-macros = { path = "../../../utils/zk-cycle-macros", optional=true } sov-stf-runner = { path = "../../../full-node/sov-stf-runner" } methods = { path = "../methods" } + + +[dev-dependencies] +sov-demo-rollup = {path = "../../demo-rollup"} +tempfile = { workspace = true } +once_cell = "1.7.2" +parking_lot = "0.11.1" +prettytable-rs = "^0.10" +env_logger = "0.10.0" +log = "0.4" +log4rs = "1.0" +regex = "1.5" + +[[bench]] +name = "prover_bench" +harness = false + +[features] +bench = ["risc0-adapter/bench", "zk-cycle-macros/bench", "methods/bench"] + diff --git a/examples/demo-prover/host/benches/README.md b/examples/demo-prover/host/benches/README.md new file mode 100644 index 000000000..617438032 --- /dev/null +++ b/examples/demo-prover/host/benches/README.md @@ -0,0 +1,174 @@ +# Prover Benchmarks +* For benchmarking the prover, we measure the number of risc0 vm cycles for each of the major functions. +* The reason for using the cycles is the assumption that proving works off a cycles/second (KHz, MHz) based on the hardware used + +## Running the bench +* From sovereign-sdk +``` +$ cd examples/demo-prover/host/benches +$ cargo bench --features bench --bench prover_bench +``` + +## Methodology +* We have `cycle_tracker` macro defined which can be used to annotate a function in zk that we want to measure the cycles for +* The `cycle_tracker` macro is defined at `sovereign-sdk/zk-cycle-util` +```rust + #[cfg_attr(all(target_os = "zkvm", feature="bench"), cycle_tracker)] + fn begin_slot(&mut self, witness: Self::Witness) { + self.checkpoint = Some(StateCheckpoint::with_witness( + self.current_storage.clone(), + witness, + )); + } +``` +* The method we use to track metrics is by registering the `io_callback` syscall when creating the risc0 host. +``` +pub fn get_syscall_name_handler() -> (SyscallName, fn(&[u8]) -> Vec) { + let cycle_string = "cycle_metrics\0"; + let bytes = cycle_string.as_bytes(); + let metrics_syscall_name = unsafe { + SyscallName::from_bytes_with_nul(bytes.as_ptr()) + }; + + let metrics_callback = |input: &[u8]| -> Vec { + { + let met_tuple = deserialize_custom(input); + add_value(met_tuple.0, met_tuple.1); + } + vec![] + }; + + (metrics_syscall_name, metrics_callback) + +} + +#[cfg(feature = "bench")] +{ + let (metrics_syscall_name, metrics_callback) = get_syscall_name_handler(); + default_env.io_callback(metrics_syscall_name, metrics_callback); +} +``` +* The above allows us to use `risc0_zkvm::guest::env::send_recv_slice` which lets the guest pass a slice of raw bytes to host and get back a vector of bytes +* We use it to pass cycle metrics to the host +* Cycles are tracked by the macro which gets a cycle count at the beginning and end of the function +```rust +let before = risc0_zkvm::guest::env::get_cycle_count(); +let result = (|| #block)(); +let after = risc0_zkvm::guest::env::get_cycle_count(); +``` +* We feature gate the application of the macro `cycle_tracker` with both the target_os set to `zkvm` and the feature flag `bench` +* The reason for using both is that we need conditional compilation to work in all cases +* For the purpose of this profiling we run the prover without generating the proof + +## Input set +* Unlike demo-prover it's harder to generate fake data since all the proofs and checks need to succeed. +* This means the DA samples, hashes, signatures etc need to succeed +* To make this easier we use a static input set consisting of 3 blocks + * we avoid using empty blocks because they skew average metrics + * we have 3 blocks + * block 1 -> 1 blob containing 1 create token transaction + * block 2 -> 1 blob containing 1 transfer transaction + * block 3 -> 1 blob containing 2 transfer transactions +* This dataset is stored at `demo-prover/benches/blocks.hex` +* The dataset can be substituted with another valid dataset as well from Celestia (TBD: automate parametrized generation of blocks.hex) +* We can run this on different kinds of workloads to gauge the efficiency of different parts of the code + +## Result +* Standard hash function patched with risc0/rust_crypto +* Signature verification currently NOT patched (TBD) +* Signature verification takes about 60% of the total cycles +``` +Block stats + ++------------------------------------------+---+ +| Total blocks | 3 | ++------------------------------------------+---+ +| Blocks with transactions | 3 | ++------------------------------------------+---+ +| Number of blobs | 3 | ++------------------------------------------+---+ +| Total number of transactions | 4 | ++------------------------------------------+---+ +| Average number of transactions per block | 1 | ++------------------------------------------+---+ + +Cycle Metrics + ++-------------------------+----------------+-----------+ +| Function | Average Cycles | Num Calls | ++-------------------------+----------------+-----------+ +| Cycles per block | 6935250 | 3 | ++-------------------------+----------------+-----------+ +| apply_slot | 6433166 | 3 | ++-------------------------+----------------+-----------+ +| verify | 3965858 | 4 | ++-------------------------+----------------+-----------+ +| end_slot | 514929 | 3 | ++-------------------------+----------------+-----------+ +| validate_and_commit | 496189 | 3 | ++-------------------------+----------------+-----------+ +| verify_relevant_tx_list | 277438 | 3 | ++-------------------------+----------------+-----------+ +| begin_slot | 4683 | 3 | ++-------------------------+----------------+-----------+ +``` + +## Custom annotations +* We can also get finer grained information by annotating low level functions, but the process for this isn't straightforward. +* For code that we control, it's as simple as adding the `cycle_tracker` annotation to our function and then feature gating it (not feature gating it causes compilation errors) +* For external dependencies, we need to fork and include a path dependency locally after annotating +* We did this for the `jmt` jellyfish merkle tree library to measure cycle gains when we use the risc0 accelerated sha function vs without +* We apply the risc0 patch in the following way in demo-prover/methods/guest/Cargo.toml +```yaml +[patch.crates-io] +sha2 = { git = "https://github.com/risc0/RustCrypto-hashes", tag = "sha2/v0.10.6-risc0" } +``` +* Note that the specific tag needs to be pointed to, since master and other branches don't contain acceleration + +## Accelerated vs Non-accelerated libs +* Accelerated and risc0 optimized crypto libraries give a significant (nearly 10x) cycle gain +* With sha2 acceleration +``` +=====> hash: 1781 +=====> hash: 1781 +=====> hash: 1781 +=====> hash: 1781 +=====> hash: 1781 +``` +* Without sha2 acceleration +``` +=====> hash: 13901 +=====> hash: 13901 +=====> hash: 13901 +=====> hash: 13901 +=====> hash: 13901 +``` +* Overall performance difference when using sha acceleration vs without for the same dataset (3 blocks, 4 transactions) as described above +* With sha acceleration +``` ++-------------------------+----------------+-----------+ +| Function | Average Cycles | Num Calls | ++-------------------------+----------------+-----------+ +| Cycles per block | 6944938 | 3 | ++-------------------------+----------------+-----------+ +| validate_and_commit | 503468 | 3 | ++-------------------------+----------------+-----------+ +| verify_relevant_tx_list | 277092 | 3 | ++-------------------------+----------------+-----------+ +Total cycles consumed for test: 20834815 +``` +* Without sha acceleration +``` ++-------------------------+----------------+-----------+ +| Function | Average Cycles | Num Calls | ++-------------------------+----------------+-----------+ +| Cycles per block | 8717567 | 3 | ++-------------------------+----------------+-----------+ +| validate_and_commit | 1432461 | 3 | ++-------------------------+----------------+-----------+ +| verify_relevant_tx_list | 966893 | 3 | ++-------------------------+----------------+-----------+ +Total cycles consumed for test: 26152702 +``` +* There's an overall efficiency of 6 million cycles in total for 3 blocks. +* Keep in mind that the above table shows average number of cycles per call, so they give an efficiency per call, but the "Total cycles consumed for test" metric at the bottom shows total for 3 blocks \ No newline at end of file diff --git a/examples/demo-prover/host/benches/blocks.hex b/examples/demo-prover/host/benches/blocks.hex new file mode 100644 index 000000000..37f044279 --- /dev/null +++ b/examples/demo-prover/host/benches/blocks.hex @@ -0,0 +1,5 @@ +0200000000000000fffffffffffffffefffffffffffffffea97efd516627c3d613d05c8eb4c32eb63f87355e19dcc50a97c48625c35d99adffffffffffffffffffffffffffffffff31de1a752d3c99fc4323e978f498978a9156b714bc6d9fc29b72a00f393328a40200000000000000fffffffffffffffefffffffffffffffea97efd516627c3d613d05c8eb4c32eb63f87355e19dcc50a97c48625c35d99adffffffffffffffffffffffffffffffff31de1a752d3c99fc4323e978f498978a9156b714bc6d9fc29b72a00f393328a40200000000000000080b06000000000000000a0474657374020000000000000008010b0000000000000008d6ccf6a30610a1b88b550200000000000000120022000000000000000a20e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b85501257760461993f8f197b421ec7435f3c36c3734923e3da9a42dc73b05f07b3d0822000000000000000a20313b46aa6296ad96730c290aa9bf4b7f5366cec34ac6d50386b2466ff9d70d6e22000000000000000a20313b46aa6296ad96730c290aa9bf4b7f5366cec34ac6d50386b2466ff9d70d6e22000000000000000a20048091bc7ddc283f77bfbf91d73c44da58c3df8a9cbc867405d8b7f3daada22f22000000000000000a20e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b85522000000000000000a20e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b85522000000000000000a20e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b85516000000000000000a1449e43321ff82ae3aea23f2443100e84a93ad7922010000000000000000000000000000000000000000000000000000000000000000000000 +0200000000000000fffffffffffffffefffffffffffffffea97efd516627c3d613d05c8eb4c32eb63f87355e19dcc50a97c48625c35d99adffffffffffffffffffffffffffffffff31de1a752d3c99fc4323e978f498978a9156b714bc6d9fc29b72a00f393328a40200000000000000fffffffffffffffefffffffffffffffea97efd516627c3d613d05c8eb4c32eb63f87355e19dcc50a97c48625c35d99adffffffffffffffffffffffffffffffff31de1a752d3c99fc4323e978f498978a9156b714bc6d9fc29b72a00f393328a40200000000000000080b06000000000000000a0474657374020000000000000008020b0000000000000008f5c4e8a60610c4e5f11448000000000000000a202430df06922a2f18631d4dc84644ea4b24abc6d903825be10ab278fc0cd8bb27122408011220d728ed4a03505212b5b16cfba570a184b5e5f463719f3fe548bd430691d5ad7622000000000000000a2047837b9a731aca002a6e1ed9b74641e98f3f441cc2e1c69d03ff7431ba0e70c901257760461993f8f197b421ec7435f3c36c3734923e3da9a42dc73b05f07b3d0822000000000000000a20313b46aa6296ad96730c290aa9bf4b7f5366cec34ac6d50386b2466ff9d70d6e22000000000000000a20313b46aa6296ad96730c290aa9bf4b7f5366cec34ac6d50386b2466ff9d70d6e22000000000000000a20048091bc7ddc283f77bfbf91d73c44da58c3df8a9cbc867405d8b7f3daada22f22000000000000000a20a577a3590441b53e05dbbbefb913b5edd5124648d341a04b718713329d85b32e22000000000000000a20e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b85522000000000000000a20e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b85516000000000000000a1449e43321ff82ae3aea23f2443100e84a93ad7922010000000000000000000000000000000000000000000000000000000000000000000000 +04000000000000000000000000000004736f762d74657374490362a480c46eb54dd64154699cbb6c283fafdae0b9f4b4ad4c4369a4100ba9fffffffffffffffefffffffffffffffe2d8bdc0adb36c2b1355ecf54794ad62ee314a19aa1ceb2c6d041d712a192fe35fffffffffffffffffffffffffffffffff45d40d82fc4d79fafef36758409f80eeda1437590bf48f89679e99930058f0bffffffffffffffffffffffffffffffff2a320b741a128353cbb2def387a080acee5b87ed9918944396683b595fa6c6c904000000000000000000000000000004fffffffffffffffe60a51b35f75755b7a9aff56f2cd7dd7f2cfad901addffc4100b4258a213854fc736f762d74657374fffffffffffffffe3c63f2b45c89baec6a2f14654c5788d90c86bcbad20feb539d16561835129ba7ffffffffffffffffffffffffffffffffe8016ad36f4a7b3bc3b8da4601928f5c8f0976735624ac43938b70abbaabd561ffffffffffffffffffffffffffffffffb3207581c5bcef70e70e29bbb7f8a957bd6b98af7c1d3d7339c4d69360a670c00200000000000000080b06000000000000000a0474657374020000000000000008030b0000000000000008ffc4e8a60610c0a1dd3348000000000000000a204af71f283e5f977b94e5c8af31576ae80742408b232ce731c51022113bc8d998122408011220ce1c73e3825809c57be5ef90bf3ba4ac376467c74a4441d94749e1b0fcf5386022000000000000000a20b342c7d34aae5de87f96dffe7c7bd639827c8ecc353d24c13152222d883c49c9010140036afedcdd88646ba9fee3e5bd28a47a9774bf6aa0701e9186cdd11bd01822000000000000000a20313b46aa6296ad96730c290aa9bf4b7f5366cec34ac6d50386b2466ff9d70d6e22000000000000000a20313b46aa6296ad96730c290aa9bf4b7f5366cec34ac6d50386b2466ff9d70d6e22000000000000000a20048091bc7ddc283f77bfbf91d73c44da58c3df8a9cbc867405d8b7f3daada22f22000000000000000a20879128e81db8a6e35aed8d1501f2d319f03b6060e751c6df2a3f04cfa6b49ff722000000000000000a20e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b85522000000000000000a20e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b85516000000000000000a1449e43321ff82ae3aea23f2443100e84a93ad79220100000001000000000000000002000000000000736f762d7465737401000000fc01000000f4000000ee49083c046aa5f4bb54f088f08497a77fb21398ee3185464e33ee99b21a1ff1e5bed3b2f7a14ccba47c8b51661d75f2c287d5fd47f190c6f989859eff68ee0ff8ad2437a279e1c8932c07358c91dc4fe34864a98c6c25f298e2a0199c1509ff8800000000000b000000000000000e000000736f762d746573742d746f6b656ee803000000000000a3201954f70ad62230dc3d840a5bf767702c04869e85ab3eee0b962857ba759802000000fea6ac5b8751120fb62fff67b54d2eac66aef307c7dde1d394dea1e09e43dd44a3201954f70ad62230dc3d840a5bf767702c04869e85ab3eee0b962857ba75980000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000200000000000000026a92c27d3e9ea75532dbb8b5093508eb1c67b4d4fc4208be305bacdb57f0dae2f0000000000000063656c6573746961317737776375706b356773776a323563306b686e6b65793566776d6c6e64783674356161726d6b01000000000000000800000000000000736f762d746573740100000000000000fc0000000100000000000000200000000000000026a92c27d3e9ea75532dbb8b5093508eb1c67b4d4fc4208be305bacdb57f0dae0100000000000000000000000000000000000000010000000000000000000000000000000100000000000000040000000000000000020000000000000000000000000004010000014500000011c3020ab7020a8b010a88010a202f63656c65737469612e626c6f622e76312e4d7367506179466f72426c6f627312640a2f63656c6573746961317737776375706b356773776a323563306b686e6b65793566776d6c6e64783674356161726d6b1208736f762d746573741a02fc01222026a92c27d3e9ea75532dbb8b5093508eb1c67b4d4fc4208be305bacdb57f0dae42010012650a500a460a1f2f636f736d6f732e63727970746f2e736563703235366b312e5075624b657912230a21027edd627fe580221f17003db181040d019ed834c911e1daa32c922870f7ebc3b812040a020801180112110a0b0a0475746961120333303010d0e80c1a4058fe4cf99f9b8384cd489608c5f06a9e26a37eff7e46ac57000569151050a4c11ff1c798e8792a657466cb2fba1bc95a5320b7432e189c582bc9e4b7e88e49961201011a04494e445800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000736f762d7465737401000000fc01000000f4000000ee49083c046aa5f4bb54f088f08497a77fb21398ee3185464e33ee99b21a1ff1e5bed3b2f7a14ccba47c8b51661d75f2c287d5fd47f190c6f989859eff68ee0ff8ad2437a279e1c8932c07358c91dc4fe34864a98c6c25f298e2a0199c1509ff8800000000000b000000000000000e000000736f762d746573742d746f6b656ee803000000000000a3201954f70ad62230dc3d840a5bf767702c04869e85ab3eee0b962857ba759802000000fea6ac5b8751120fb62fff67b54d2eac66aef307c7dde1d394dea1e09e43dd44a3201954f70ad62230dc3d840a5bf767702c04869e85ab3eee0b962857ba75980000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000b79abf31bc94b7b2010000038502000039d601047348a35b1a0ec6ee69d795992d902a34264a33350bbee924bf6532571408d4fe9a852ca70b85105a882b8a2f8488d14f938b1e93985c483152a22012399ab2b9c2a01811361897b48d0cc8fad6f50a9e5abb536429f7531f9b098911dec727cb94151cc8f1c4c832019c0315141b431b1881ab1e516f2dc4c265d5e3e7e6265578a1b61456af0d7bb196fb2dc7850d5a0cef50c9dfe98a5f8a48c6ce2c0a1df7e48ecc34f17cdf7a07fdc62f234217cf90084bd4e937f25a81c3ba312e1e1ca9ab23437c64f1719b1ff1a155c362149ab1c2891d287445dd40a43516acb8370bddfce6ea217008f53d870a760cff3b022c2e2e3a83a80b3ee8d79de391626c535fb1ed6405b497f8611b47cc9ecce74ede000dfa373ad24bba3394b56ea8c010f1c8f3be1d7b3dbfd6d01473ea1e3f60d713bfa373a85bee643b03033e0eeee2e6d700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000c4f5c91cc8f1c4c2010000023c03000028e1030ec4a4e0d82700244a974cee0ac00ccbd0f55ce008f13cb7c3d75d3097c0c9a9b10a19d41bcb30dd7921fce4c0dfc1af5f0d2cea320c7a88d6a32ccae2d70eef30be2fdf0734d9de3e2df18f989a4cfd3578347564f84d4b0f08f019dcac493ab104eb31bc94b7bc2303600237343dea393f5242874b4a2d0b2c46329e1d388b4b5b067134dd4c08c17c80a4393d30068c3cba86a451a5dbb7c25b85b9c7fbeb72b912bed2ad444b7cfa9cb61d168ada52e5df6fa4ade4a4b7c57cd61dfca5d0254964bc82a065928b7e6bef891919004af4d4596826d6b1903345ad59d9cc110d53637b400d8f09681fd4c577fd9e29011f1e1e2a53400724a88f63af68fdf7d0db7ca5f20d716792ff3de4b261b2a1e289000893222a82ef7b2c6572f640b93a94bc957532c126768c8334c4a93027fc8f387647c440d5a7f2290202240aa7aca28f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004736f762d74657374490362a480c46eb54dd64154699cbb6c283fafdae0b9f4b4ad4c4369a4100ba90100000000000000040000000000000000020000000000000000000000000004010000014500000011c3020ab7020a8b010a88010a202f63656c65737469612e626c6f622e76312e4d7367506179466f72426c6f627312640a2f63656c6573746961317737776375706b356773776a323563306b686e6b65793566776d6c6e64783674356161726d6b1208736f762d746573741a02fc01222026a92c27d3e9ea75532dbb8b5093508eb1c67b4d4fc4208be305bacdb57f0dae42010012650a500a460a1f2f636f736d6f732e63727970746f2e736563703235366b312e5075624b657912230a21027edd627fe580221f17003db181040d019ed834c911e1daa32c922870f7ebc3b812040a020801180112110a0b0a0475746961120333303010d0e80c1a4058fe4cf99f9b8384cd489608c5f06a9e26a37eff7e46ac57000569151050a4c11ff1c798e8792a657466cb2fba1bc95a5320b7432e189c582bc9e4b7e88e49961201011a04494e445800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000736f762d7465737401000000fc01000000f4000000ee49083c046aa5f4bb54f088f08497a77fb21398ee3185464e33ee99b21a1ff1e5bed3b2f7a14ccba47c8b51661d75f2c287d5fd47f190c6f989859eff68ee0ff8ad2437a279e1c8932c07358c91dc4fe34864a98c6c25f298e2a0199c1509ff8800000000000b000000000000000e000000736f762d746573742d746f6b656ee803000000000000a3201954f70ad62230dc3d840a5bf767702c04869e85ab3eee0b962857ba759802000000fea6ac5b8751120fb62fff67b54d2eac66aef307c7dde1d394dea1e09e43dd44a3201954f70ad62230dc3d840a5bf767702c04869e85ab3eee0b962857ba75980000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000b79abf31bc94b7b2010000038502000039d601047348a35b1a0ec6ee69d795992d902a34264a33350bbee924bf6532571408d4fe9a852ca70b85105a882b8a2f8488d14f938b1e93985c483152a22012399ab2b9c2a01811361897b48d0cc8fad6f50a9e5abb536429f7531f9b098911dec727cb94151cc8f1c4c832019c0315141b431b1881ab1e516f2dc4c265d5e3e7e6265578a1b61456af0d7bb196fb2dc7850d5a0cef50c9dfe98a5f8a48c6ce2c0a1df7e48ecc34f17cdf7a07fdc62f234217cf90084bd4e937f25a81c3ba312e1e1ca9ab23437c64f1719b1ff1a155c362149ab1c2891d287445dd40a43516acb8370bddfce6ea217008f53d870a760cff3b022c2e2e3a83a80b3ee8d79de391626c535fb1ed6405b497f8611b47cc9ecce74ede000dfa373ad24bba3394b56ea8c010f1c8f3be1d7b3dbfd6d01473ea1e3f60d713bfa373a85bee643b03033e0eeee2e6d700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000c4f5c91cc8f1c4c2010000023c03000028e1030ec4a4e0d82700244a974cee0ac00ccbd0f55ce008f13cb7c3d75d3097c0c9a9b10a19d41bcb30dd7921fce4c0dfc1af5f0d2cea320c7a88d6a32ccae2d70eef30be2fdf0734d9de3e2df18f989a4cfd3578347564f84d4b0f08f019dcac493ab104eb31bc94b7bc2303600237343dea393f5242874b4a2d0b2c46329e1d388b4b5b067134dd4c08c17c80a4393d30068c3cba86a451a5dbb7c25b85b9c7fbeb72b912bed2ad444b7cfa9cb61d168ada52e5df6fa4ade4a4b7c57cd61dfca5d0254964bc82a065928b7e6bef891919004af4d4596826d6b1903345ad59d9cc110d53637b400d8f09681fd4c577fd9e29011f1e1e2a53400724a88f63af68fdf7d0db7ca5f20d716792ff3de4b261b2a1e289000893222a82ef7b2c6572f640b93a94bc957532c126768c8334c4a93027fc8f387647c440d5a7f2290202240aa7aca28f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004736f762d74657374490362a480c46eb54dd64154699cbb6c283fafdae0b9f4b4ad4c4369a4100ba9 +04000000000000000000000000000004736f762d74657374ac50b9d0223ddbb3be915d3e137e398954d178c230872c2129ac2b47e102b2cdfffffffffffffffefffffffffffffffe2d8bdc0adb36c2b1355ecf54794ad62ee314a19aa1ceb2c6d041d712a192fe35fffffffffffffffffffffffffffffffff71c654cd09a61036e01ed33ae918d18b0e5ba0794fbe47a2c741d20f2063910ffffffffffffffffffffffffffffffff4fa49d42a64106676832e1d9de1a11cdfa534202413d54f651474c42dfc17e6204000000000000000000000000000004fffffffffffffffebfd734204f10a51792e6702d6cf01aa26ff3fd7c9fd509165398ac17d86c4bdf736f762d74657374fffffffffffffffe23a22c3f7104f73c472215a5b3521b19e10794db1eb67eb7ca35b0d8852f0dfeffffffffffffffffffffffffffffffff64c37eed9469411345b6b40ba3364add2d173da14a55704d2cac9a041fcdd7b5ffffffffffffffffffffffffffffffffc57a236559368b2ce48ab92e3a182b7d64e4bfc3e167f7f7662f763c915cbc750200000000000000080b06000000000000000a0474657374020000000000000008040b000000000000000889c5e8a606108889d84948000000000000000a20b42b38b26398e4103db7a728dc19f01ae6ab2b3099fd1060baac22c6d3908c1e122408011220feb6598f634155981d4fad9e1c320eada5617d06952c2c7334f5c4cf7c5e584a22000000000000000a208b25e01aa7e4cdb22dad91f964ecb6f00327ff5b01820a806c3adacb2bc2749701f1556b39c2b6938f77830a6edad386a91ce74cf2cda7bb20fb3d59ec0607c23322000000000000000a20313b46aa6296ad96730c290aa9bf4b7f5366cec34ac6d50386b2466ff9d70d6e22000000000000000a20313b46aa6296ad96730c290aa9bf4b7f5366cec34ac6d50386b2466ff9d70d6e22000000000000000a20048091bc7ddc283f77bfbf91d73c44da58c3df8a9cbc867405d8b7f3daada22f22000000000000000a20cc1af9ec6ee03cdb31089286da64e71428a0af62c0b8e47b4e0c1d972642b25a22000000000000000a20ebb716b3f3d18b55ea0b304786d0ece8b4d3b51539364c7fd80e39cc90bc170322000000000000000a20e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b85516000000000000000a1449e43321ff82ae3aea23f2443100e84a93ad79220100000001000000000000000002000000000000736f762d7465737401000000be01000000b60000002adbd76606f2bd4125080e6f44df7ba2d728409955c80b8438eb1828ddf23e3c12188eeac7ecf6323be0ed5668e21cc354fca90d8bca513d6c0a240c26afa7007b758bf2e7670fafaf6bf0015ce0ff5aa802306fc7e3f45762853ffc37180fe64a0000000001fea6ac5b8751120fb62fff67b54d2eac66aef307c7dde1d394dea1e09e43dd44c800000000000000135d23aee8cb15c890831ff36db170157acaac31df9bba6cd40e7329e608eabd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000200000000000000011a9b433a5ad7385e47bb072888d971f3776f1ccfc2bf1904435f66f245127572f0000000000000063656c6573746961317737776375706b356773776a323563306b686e6b65793566776d6c6e64783674356161726d6b01000000000000000800000000000000736f762d746573740100000000000000be0000000100000000000000200000000000000011a9b433a5ad7385e47bb072888d971f3776f1ccfc2bf1904435f66f245127570100000000000000000000000000000000000000010000000000000000000000000000000100000000000000040000000000000000020000000000000000000000000004010000014500000011c3020ab7020a8b010a88010a202f63656c65737469612e626c6f622e76312e4d7367506179466f72426c6f627312640a2f63656c6573746961317737776375706b356773776a323563306b686e6b65793566776d6c6e64783674356161726d6b1208736f762d746573741a02be01222011a9b433a5ad7385e47bb072888d971f3776f1ccfc2bf1904435f66f2451275742010012650a500a460a1f2f636f736d6f732e63727970746f2e736563703235366b312e5075624b657912230a21027edd627fe580221f17003db181040d019ed834c911e1daa32c922870f7ebc3b812040a020801180212110a0b0a0475746961120333303010d0e80c1a4016bcae791b5af02b9907a7c315c1d4fa6bf1b2e7e3dc017c1cbe02057e5025d0428ec7b5d3a713dfa95a6d3efd0b4e3ce80d7ed46d732284244c2594f4f9d6e01201011a04494e445800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000736f762d7465737401000000be01000000b60000002adbd76606f2bd4125080e6f44df7ba2d728409955c80b8438eb1828ddf23e3c12188eeac7ecf6323be0ed5668e21cc354fca90d8bca513d6c0a240c26afa7007b758bf2e7670fafaf6bf0015ce0ff5aa802306fc7e3f45762853ffc37180fe64a0000000001fea6ac5b8751120fb62fff67b54d2eac66aef307c7dde1d394dea1e09e43dd44c800000000000000135d23aee8cb15c890831ff36db170157acaac31df9bba6cd40e7329e608eabd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000b79abf31bc94b7b2010000032e020000397d0104733b5b0e960d30c9ae2810fa6b55a47e2ea2c6b6097d81f1c5da6c39d99294c8e6e9c020849bbd9be0d676ba8f8cb0dc8f79a422ff225a4a3951f0f5c1c6c01ec47046f247b8b9fd1a156b96c2a6beab781ff5ec5953844e76601eec9b2e22c2b16f1cc8f1c4ca5ded978dcf941045b71e29da03f19323ea26325215656d9b65e57b5e6bc2b081ecf51ad118dee9032bbcc4e59271c570c8cdd2935d3943e6a68925dc933f34859df549fd6b2e62312d1ed2cbfdeff1c03b16041701cc8bfdcfa05115333600267c520e0803618620bf39ae87471f6a11c69baabb7a3b0e040105033f013b390407040ecbc8faff3b022c2e2e3a83a80b3ee835744fc03dd697136d0c49bb37ba8d93fb947ea1af8803cd3175010dccd21983e95bb5728149388a43d6f4249f07e225a808cc8df4c4155f1ae3196599918cad3b03033e0eeee2e6d700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000c4f5c91cc8f1c4c201000002d50300002808030ec4138a52f1014a75e52d3797617d1e76f81c8fd8f24426986f94b60fbc3c01a6bb829ec11c1e3d02b09e8433d3cb31a520482bff9bc8a16c334a99a4bd8b5adeb77c594b803cee99ddd46b03bacf38234fdb99b84ea2138f4063e9be0c0b32be385331bc94b7bfb94985d76ae513e3b5027310c53959f43cfa49d845a7bb3e00f72695041129f0d29a3e803f89ab0238f382412ab096b24761ae0f43e55c80f220fb943cd0e1c73a9e59a4bf13bee71c3082be9fa494b929350e3603b2569fb045d1372c21001bcdd30a0502ff5e1476284f5de433f839b66c4178c2290a0e030d02270329280e0c0e0abebc939e29011f1e1e2a53400724a823c8e1b9268c6738f40bee78227b59699065cc464c5402b12dcb0308b2823c53abd572c752ee2b55ea8c991a620cac194005b25999b737db3eaf3cf16d685a4d290202240aa7aca28f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004736f762d74657374ac50b9d0223ddbb3be915d3e137e398954d178c230872c2129ac2b47e102b2cd0100000000000000040000000000000000020000000000000000000000000004010000014500000011c3020ab7020a8b010a88010a202f63656c65737469612e626c6f622e76312e4d7367506179466f72426c6f627312640a2f63656c6573746961317737776375706b356773776a323563306b686e6b65793566776d6c6e64783674356161726d6b1208736f762d746573741a02be01222011a9b433a5ad7385e47bb072888d971f3776f1ccfc2bf1904435f66f2451275742010012650a500a460a1f2f636f736d6f732e63727970746f2e736563703235366b312e5075624b657912230a21027edd627fe580221f17003db181040d019ed834c911e1daa32c922870f7ebc3b812040a020801180212110a0b0a0475746961120333303010d0e80c1a4016bcae791b5af02b9907a7c315c1d4fa6bf1b2e7e3dc017c1cbe02057e5025d0428ec7b5d3a713dfa95a6d3efd0b4e3ce80d7ed46d732284244c2594f4f9d6e01201011a04494e445800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000736f762d7465737401000000be01000000b60000002adbd76606f2bd4125080e6f44df7ba2d728409955c80b8438eb1828ddf23e3c12188eeac7ecf6323be0ed5668e21cc354fca90d8bca513d6c0a240c26afa7007b758bf2e7670fafaf6bf0015ce0ff5aa802306fc7e3f45762853ffc37180fe64a0000000001fea6ac5b8751120fb62fff67b54d2eac66aef307c7dde1d394dea1e09e43dd44c800000000000000135d23aee8cb15c890831ff36db170157acaac31df9bba6cd40e7329e608eabd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000b79abf31bc94b7b2010000032e020000397d0104733b5b0e960d30c9ae2810fa6b55a47e2ea2c6b6097d81f1c5da6c39d99294c8e6e9c020849bbd9be0d676ba8f8cb0dc8f79a422ff225a4a3951f0f5c1c6c01ec47046f247b8b9fd1a156b96c2a6beab781ff5ec5953844e76601eec9b2e22c2b16f1cc8f1c4ca5ded978dcf941045b71e29da03f19323ea26325215656d9b65e57b5e6bc2b081ecf51ad118dee9032bbcc4e59271c570c8cdd2935d3943e6a68925dc933f34859df549fd6b2e62312d1ed2cbfdeff1c03b16041701cc8bfdcfa05115333600267c520e0803618620bf39ae87471f6a11c69baabb7a3b0e040105033f013b390407040ecbc8faff3b022c2e2e3a83a80b3ee835744fc03dd697136d0c49bb37ba8d93fb947ea1af8803cd3175010dccd21983e95bb5728149388a43d6f4249f07e225a808cc8df4c4155f1ae3196599918cad3b03033e0eeee2e6d700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000c4f5c91cc8f1c4c201000002d50300002808030ec4138a52f1014a75e52d3797617d1e76f81c8fd8f24426986f94b60fbc3c01a6bb829ec11c1e3d02b09e8433d3cb31a520482bff9bc8a16c334a99a4bd8b5adeb77c594b803cee99ddd46b03bacf38234fdb99b84ea2138f4063e9be0c0b32be385331bc94b7bfb94985d76ae513e3b5027310c53959f43cfa49d845a7bb3e00f72695041129f0d29a3e803f89ab0238f382412ab096b24761ae0f43e55c80f220fb943cd0e1c73a9e59a4bf13bee71c3082be9fa494b929350e3603b2569fb045d1372c21001bcdd30a0502ff5e1476284f5de433f839b66c4178c2290a0e030d02270329280e0c0e0abebc939e29011f1e1e2a53400724a823c8e1b9268c6738f40bee78227b59699065cc464c5402b12dcb0308b2823c53abd572c752ee2b55ea8c991a620cac194005b25999b737db3eaf3cf16d685a4d290202240aa7aca28f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004736f762d74657374ac50b9d0223ddbb3be915d3e137e398954d178c230872c2129ac2b47e102b2cd +04000000000000000000000000000004736f762d74657374f0e19f70a9b8230eb4b6c2763def30872bcc268ecb782a709f63dc3b4064d290fffffffffffffffefffffffffffffffe2d8bdc0adb36c2b1355ecf54794ad62ee314a19aa1ceb2c6d041d712a192fe35ffffffffffffffffffffffffffffffff85332fe79fddb4e46da26cfda92a16a4847904073c8d7b9569939693ce2500c7fffffffffffffffffffffffffffffffffabf7945694d0c30d100b7f2cd9bdffc637de9037c20172723476d7ee5d37fd804000000000000000000000000000004fffffffffffffffece46ab5e2f606bb91bf550801dd58eb7c4e0af35930260438e8283b5baeb2dde736f762d74657374fffffffffffffffe2ec8952e1551fa2146d6a9929ceffb75f2b0beb1ce21b64e172233c058092a41ffffffffffffffffffffffffffffffff5430d61857c9817fe0488a8d45d035ccf2eded4cd99ec7b71c2dc2f1b5af93e6ffffffffffffffffffffffffffffffff3c9c890a387f94b1fcfe6692363fc7e1d39b29b56444adf950aa89d5d143d2180200000000000000080b06000000000000000a0474657374020000000000000008050b000000000000000893c5e8a60610b587895f48000000000000000a2002d54033f21bd236ca93380a387d63196d40b4e5f90da1e83a93ebecfe832ce9122408011220b4c8233a71d14f37d63a512dc7ed646d0b1dac7296869e5edbd50b0b76a8c6a722000000000000000a20677d12b53874733888e0b57b2100907f98c76716cfe54ebac333815963dc8e1201c282ddeb5eb9167f5d46ca71af830dd3d3b4d3cf041a3f68c7208d0813a8ba5022000000000000000a20313b46aa6296ad96730c290aa9bf4b7f5366cec34ac6d50386b2466ff9d70d6e22000000000000000a20313b46aa6296ad96730c290aa9bf4b7f5366cec34ac6d50386b2466ff9d70d6e22000000000000000a20048091bc7ddc283f77bfbf91d73c44da58c3df8a9cbc867405d8b7f3daada22f22000000000000000a205e5e89f09e0aacf2d4708e8fad2e4befcc3689122ac6ef9c44d6c25f523385e722000000000000000a20ebb716b3f3d18b55ea0b304786d0ece8b4d3b51539364c7fd80e39cc90bc170322000000000000000a20e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b85516000000000000000a1449e43321ff82ae3aea23f2443100e84a93ad79220100000001000000000000000002000000000000736f762d74657374010000017802000000b600000009c241181dbfc2cf20083e3651da58c7cf6bf8b70182b70062d4ae713a5161ca0c87fde160667857e83ecfcbfe2b9c87d93f1295527561e466a5ef70c80661007b758bf2e7670fafaf6bf0015ce0ff5aa802306fc7e3f45762853ffc37180fe64a0000000001e39febaf77ef923eb6b4c86d7e0c11a528e303a46b9e8f1c382493e799b4dc27c700000000000000135d23aee8cb15c890831ff36db170157acaac31df9bba6cd40e7329e608eabd0100000000000000b600000017896f9627db1799c59c6006bdfb5297e67bc4ea6e931a9a91946726295bd880e6bce7758326c33c89c4623da515654d8ce52d61a47619bb297ca524c6f74e017b758bf2e7670fafaf6bf0015ce0ff5aa802306fc7e3f45762853ffc37180fe64a00000000012e727adc7e69ba5ff2a216385651b4fff4059a25880214d947abbed193d8b6b8c600000000000000135d23aee8cb15c890831ff36db170157acaac31df9bba6cd40e7329e608eabd0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000020000000000000003193d8b98c9a83cb2314953cc18d41d044028e23576bfed024252562e6894a362f0000000000000063656c6573746961317737776375706b356773776a323563306b686e6b65793566776d6c6e64783674356161726d6b01000000000000000800000000000000736f762d74657374010000000000000078010000010000000000000020000000000000003193d8b98c9a83cb2314953cc18d41d044028e23576bfed024252562e6894a360100000000000000000000000000000000000000010000000000000000000000000000000100000000000000040000000000000000020000000000000000000000000004010000014500000011c3020ab7020a8b010a88010a202f63656c65737469612e626c6f622e76312e4d7367506179466f72426c6f627312640a2f63656c6573746961317737776375706b356773776a323563306b686e6b65793566776d6c6e64783674356161726d6b1208736f762d746573741a02f80222203193d8b98c9a83cb2314953cc18d41d044028e23576bfed024252562e6894a3642010012650a500a460a1f2f636f736d6f732e63727970746f2e736563703235366b312e5075624b657912230a21027edd627fe580221f17003db181040d019ed834c911e1daa32c922870f7ebc3b812040a020801180312110a0b0a0475746961120333303010d0e80c1a40d6f5c12c2d16c327304b590b2fca5afe4aae7c292e396aed2a273205d4ce5fa746c265f9d3b54006198c4979a82a942f9df2b5940ae0aa110df14393089a69ba1201011a04494e445800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000736f762d74657374010000017802000000b600000009c241181dbfc2cf20083e3651da58c7cf6bf8b70182b70062d4ae713a5161ca0c87fde160667857e83ecfcbfe2b9c87d93f1295527561e466a5ef70c80661007b758bf2e7670fafaf6bf0015ce0ff5aa802306fc7e3f45762853ffc37180fe64a0000000001e39febaf77ef923eb6b4c86d7e0c11a528e303a46b9e8f1c382493e799b4dc27c700000000000000135d23aee8cb15c890831ff36db170157acaac31df9bba6cd40e7329e608eabd0100000000000000b600000017896f9627db1799c59c6006bdfb5297e67bc4ea6e931a9a91946726295bd880e6bce7758326c33c89c4623da515654d8ce52d61a47619bb297ca524c6f74e017b758bf2e7670fafaf6bf0015ce0ff5aa802306fc7e3f45762853ffc37180fe64a00000000012e727adc7e69ba5ff2a216385651b4fff4059a25880214d947abbed193d8b6b8c600000000000000135d23aee8cb15c890831ff36db170157acaac31df9bba6cd40e7329e608eabd02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000b79abf31bc94b7b2010000015e030000397d0104730e7efc242b9d797b2010e4e677ac4bba856f7439f527391e5674ff54d4704c88c73d978875624e7484218d717ec60d2daddce1097e9354655f1380708f2a6ec47046f247b8b9fd1a156b96c2a6beab781ff5ec5953844e76601eec9b2e22c2b16f1cc8f1c4ca72fcd3e2a85fd57340bc2ef6e1b93ed95f69bbb67b7c312c482824bd69464e266bfda257ec21e9032bbcc4e59271c570c8cdd2935d3943e6a68925dc933f34859df549fd6b2e62312f1ed2cbfdeff1c0fd1604172012110ff0ff70e142ca9c2fb6398ff847dbf56327c38a72beeefd2cfd15f46a3ef348bad1387b26dc48a61fea269a661ebfcea5ed930bed013245354e84209800a1c151fd8f280c37977abf53d08dc3251100b28ae97d91b0d495d3ce6ee1fc57918172e80d0cef5694f283a499077051768f2d8458659c1f55d96cda2798eac86ff4b02424a7000000000000002b8735e140752274fbd02c6699cdb622b877e21c55f7c19b5904b73b440d43ca03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000c4f5c91cc8f1c4c201000001630100002808030ec405b6363d3caababe2037b9b54a1360092365a2ec98caec3042917f689d467d23b2fc051b576859411f0d26b0af8ef4c6119087f54dd742b64ed51a702c1968b77c594b803cee99ddd46b03bacf38234fdb99b84ea2138f4063e9be0c0b32be385331bc94b7bf8b61c04ffd9076de2eb16a011c7e0c68e2b6799f5132fa32fe2fe0310e22b624899f44dea617ab0238f382412ab096b24761ae0f43e55c80f220fb943cd0e1c73a9e59a4bf13bee71f3082be9fa494b959350e3635e5a3fba8c1e75a9841fc14ba43d962a03ee9bd804171328c560822a4b9c729605dabc55016b902569ed5284439fb5ee63382d64ad62266389e081d9233b86cbaf867b5d9cf17e8c1f7a57455ce3837f13a1ee427e7a3e1e0547ee1a6d1a8d8786852c7a80a3b11653124c08ae96820f2dad39c9ab69c68c6e359f4a744cd4077a46321dcd8390000000000000038da164fa8be37bc6b533395f47cc637c2bd4e2d8a6c7bf78d0ac412a205a97701000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004736f762d74657374f0e19f70a9b8230eb4b6c2763def30872bcc268ecb782a709f63dc3b4064d2900100000000000000040000000000000000020000000000000000000000000004010000014500000011c3020ab7020a8b010a88010a202f63656c65737469612e626c6f622e76312e4d7367506179466f72426c6f627312640a2f63656c6573746961317737776375706b356773776a323563306b686e6b65793566776d6c6e64783674356161726d6b1208736f762d746573741a02f80222203193d8b98c9a83cb2314953cc18d41d044028e23576bfed024252562e6894a3642010012650a500a460a1f2f636f736d6f732e63727970746f2e736563703235366b312e5075624b657912230a21027edd627fe580221f17003db181040d019ed834c911e1daa32c922870f7ebc3b812040a020801180312110a0b0a0475746961120333303010d0e80c1a40d6f5c12c2d16c327304b590b2fca5afe4aae7c292e396aed2a273205d4ce5fa746c265f9d3b54006198c4979a82a942f9df2b5940ae0aa110df14393089a69ba1201011a04494e445800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000736f762d74657374010000017802000000b600000009c241181dbfc2cf20083e3651da58c7cf6bf8b70182b70062d4ae713a5161ca0c87fde160667857e83ecfcbfe2b9c87d93f1295527561e466a5ef70c80661007b758bf2e7670fafaf6bf0015ce0ff5aa802306fc7e3f45762853ffc37180fe64a0000000001e39febaf77ef923eb6b4c86d7e0c11a528e303a46b9e8f1c382493e799b4dc27c700000000000000135d23aee8cb15c890831ff36db170157acaac31df9bba6cd40e7329e608eabd0100000000000000b600000017896f9627db1799c59c6006bdfb5297e67bc4ea6e931a9a91946726295bd880e6bce7758326c33c89c4623da515654d8ce52d61a47619bb297ca524c6f74e017b758bf2e7670fafaf6bf0015ce0ff5aa802306fc7e3f45762853ffc37180fe64a00000000012e727adc7e69ba5ff2a216385651b4fff4059a25880214d947abbed193d8b6b8c600000000000000135d23aee8cb15c890831ff36db170157acaac31df9bba6cd40e7329e608eabd02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000b79abf31bc94b7b2010000015e030000397d0104730e7efc242b9d797b2010e4e677ac4bba856f7439f527391e5674ff54d4704c88c73d978875624e7484218d717ec60d2daddce1097e9354655f1380708f2a6ec47046f247b8b9fd1a156b96c2a6beab781ff5ec5953844e76601eec9b2e22c2b16f1cc8f1c4ca72fcd3e2a85fd57340bc2ef6e1b93ed95f69bbb67b7c312c482824bd69464e266bfda257ec21e9032bbcc4e59271c570c8cdd2935d3943e6a68925dc933f34859df549fd6b2e62312f1ed2cbfdeff1c0fd1604172012110ff0ff70e142ca9c2fb6398ff847dbf56327c38a72beeefd2cfd15f46a3ef348bad1387b26dc48a61fea269a661ebfcea5ed930bed013245354e84209800a1c151fd8f280c37977abf53d08dc3251100b28ae97d91b0d495d3ce6ee1fc57918172e80d0cef5694f283a499077051768f2d8458659c1f55d96cda2798eac86ff4b02424a7000000000000002b8735e140752274fbd02c6699cdb622b877e21c55f7c19b5904b73b440d43ca03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000c4f5c91cc8f1c4c201000001630100002808030ec405b6363d3caababe2037b9b54a1360092365a2ec98caec3042917f689d467d23b2fc051b576859411f0d26b0af8ef4c6119087f54dd742b64ed51a702c1968b77c594b803cee99ddd46b03bacf38234fdb99b84ea2138f4063e9be0c0b32be385331bc94b7bf8b61c04ffd9076de2eb16a011c7e0c68e2b6799f5132fa32fe2fe0310e22b624899f44dea617ab0238f382412ab096b24761ae0f43e55c80f220fb943cd0e1c73a9e59a4bf13bee71f3082be9fa494b959350e3635e5a3fba8c1e75a9841fc14ba43d962a03ee9bd804171328c560822a4b9c729605dabc55016b902569ed5284439fb5ee63382d64ad62266389e081d9233b86cbaf867b5d9cf17e8c1f7a57455ce3837f13a1ee427e7a3e1e0547ee1a6d1a8d8786852c7a80a3b11653124c08ae96820f2dad39c9ab69c68c6e359f4a744cd4077a46321dcd8390000000000000038da164fa8be37bc6b533395f47cc637c2bd4e2d8a6c7bf78d0ac412a205a97701000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004736f762d74657374f0e19f70a9b8230eb4b6c2763def30872bcc268ecb782a709f63dc3b4064d290 \ No newline at end of file diff --git a/examples/demo-prover/host/benches/prover_bench.rs b/examples/demo-prover/host/benches/prover_bench.rs new file mode 100644 index 000000000..4d7e80d24 --- /dev/null +++ b/examples/demo-prover/host/benches/prover_bench.rs @@ -0,0 +1,260 @@ +use std::collections::HashMap; +use std::env; +use std::fs::{read_to_string, remove_file, File, OpenOptions}; +use std::io::Write; +use std::path::{Path, PathBuf}; +use std::str::FromStr; +use std::sync::{Arc, Mutex}; + +use anyhow::Context; +use const_rollup_config::{ROLLUP_NAMESPACE_RAW, SEQUENCER_DA_ADDRESS}; +use demo_stf::app::{App, DefaultPrivateKey}; +use demo_stf::genesis_config::create_demo_genesis_config; +use jupiter::da_service::CelestiaService; +use jupiter::types::{FilteredCelestiaBlock, NamespaceId}; +use jupiter::verifier::address::CelestiaAddress; +use jupiter::verifier::{ChainValidityCondition, RollupParams}; +use jupiter::BlobWithSender; +use log4rs::config::{Appender, Config, Root}; +use methods::ROLLUP_ELF; +use regex::Regex; +use risc0_adapter::host::Risc0Host; +use sov_modules_api::PrivateKey; +use sov_rollup_interface::services::da::DaService; +use sov_rollup_interface::stf::StateTransitionFunction; +use sov_rollup_interface::zk::ZkvmHost; +use sov_state::storage::Storage; +use sov_stf_runner::{from_toml_path, RollupConfig}; +use tempfile::TempDir; + +#[derive(Debug)] +struct RegexAppender { + regex: Regex, + file: Arc>, +} + +impl RegexAppender { + fn new(pattern: &str, file_path: &str) -> Self { + if Path::new(file_path).exists() { + remove_file(file_path).expect("Failed to remove existing file"); + } + let file = Arc::new(Mutex::new( + OpenOptions::new() + .create(true) + .append(true) + .open(file_path) + .unwrap(), + )); + let regex = Regex::new(pattern).unwrap(); + RegexAppender { regex, file } + } +} + +impl log::Log for RegexAppender { + fn log(&self, record: &log::Record) { + if let Some(captures) = self.regex.captures(record.args().to_string().as_str()) { + if let Some(matched_pc) = captures.get(1) { + let pc_value_num = u64::from_str_radix(&matched_pc.as_str()[2..], 16).unwrap(); + let pc_value = format!("{}\n", pc_value_num); + let mut file_guard = self.file.lock().unwrap(); + file_guard.write_all(pc_value.as_bytes()).unwrap(); + } + } + } + + fn enabled(&self, _metadata: &log::Metadata) -> bool { + true + } + + fn flush(&self) {} +} + +fn get_config(rollup_trace: &str) -> Config { + let regex_pattern = r".*?pc: (0x[0-9a-fA-F]+), insn.*"; + // let log_file = "/Users/dubbelosix/sovereign/examples/demo-prover/matched_pattern.log"; + + let custom_appender = RegexAppender::new(regex_pattern, rollup_trace); + + Config::builder() + .appender(Appender::builder().build("custom_appender", Box::new(custom_appender))) + .build( + Root::builder() + .appender("custom_appender") + .build(log::LevelFilter::Trace), + ) + .unwrap() +} + +#[cfg(feature = "bench")] +use risc0_adapter::metrics::GLOBAL_HASHMAP; + +// The rollup stores its data in the namespace b"sov-test" on Celestia +const ROLLUP_NAMESPACE: NamespaceId = NamespaceId(ROLLUP_NAMESPACE_RAW); + +#[macro_use] +extern crate prettytable; + +use prettytable::Table; + +fn print_cycle_averages(metric_map: HashMap) { + let mut metrics_vec: Vec<(String, (u64, u64))> = metric_map + .iter() + .map(|(k, (sum, count))| { + ( + k.clone(), + ( + ((*sum as f64) / (*count as f64)).round() as u64, + count.clone(), + ), + ) + }) + .collect(); + + metrics_vec.sort_by(|a, b| b.1.cmp(&a.1)); + + let mut table = Table::new(); + table.add_row(row!["Function", "Average Cycles", "Num Calls"]); + for (k, (avg, count)) in metrics_vec { + table.add_row(row![k, format!("{}", avg), format!("{}", count)]); + } + table.printstd(); +} + +fn chain_stats(num_blocks: usize, num_blocks_with_txns: usize, num_txns: usize, num_blobs: usize) { + let mut table = Table::new(); + table.add_row(row!["Total blocks", num_blocks]); + table.add_row(row!["Blocks with transactions", num_blocks_with_txns]); + table.add_row(row!["Number of blobs", num_blobs]); + table.add_row(row!["Total number of transactions", num_txns]); + table.add_row(row![ + "Average number of transactions per block", + ((num_txns as f64) / (num_blocks_with_txns as f64)) as u64 + ]); + table.printstd(); +} + +#[tokio::main] +async fn main() -> Result<(), anyhow::Error> { + if let Some(rollup_trace) = env::var("ROLLUP_TRACE").ok() { + if let Err(e) = log4rs::init_config(get_config(&rollup_trace)) { + eprintln!("Error initializing logger: {:?}", e); + } + } + + let rollup_config_path = "benches/rollup_config.toml".to_string(); + let mut rollup_config: RollupConfig = from_toml_path(&rollup_config_path) + .context("Failed to read rollup configuration") + .unwrap(); + + let mut num_blocks = 0; + let mut num_blobs = 0; + let mut num_blocks_with_txns = 0; + let mut num_total_transactions = 0; + + let temp_dir = TempDir::new().expect("Unable to create temporary directory"); + rollup_config.runner.storage.path = PathBuf::from(temp_dir.path()); + + let da_service = CelestiaService::new( + rollup_config.da.clone(), + RollupParams { + namespace: ROLLUP_NAMESPACE, + }, + ) + .await; + + let sequencer_private_key = DefaultPrivateKey::generate(); + + let mut app: App = + App::new(rollup_config.runner.storage.clone()); + + let sequencer_da_address = CelestiaAddress::from_str(SEQUENCER_DA_ADDRESS).unwrap(); + + let genesis_config = create_demo_genesis_config( + 100000000, + sequencer_private_key.default_address(), + sequencer_da_address.as_ref().to_vec(), + &sequencer_private_key, + &sequencer_private_key, + ); + println!("Starting from empty storage, initialization chain"); + app.stf.init_chain(genesis_config); + + let mut prev_state_root = app + .get_storage() + .get_state_root(&Default::default()) + .expect("The storage needs to have a state root"); + + let mut demo = app.stf; + + let hex_data = read_to_string("benches/blocks.hex").expect("Failed to read data"); + let bincoded_blocks: Vec = hex_data + .lines() + .map(|line| { + let bytes = hex::decode(line).expect("Failed to decode hex data"); + bincode::deserialize(&bytes).expect("Failed to deserialize data") + }) + .collect(); + + for height in 2..(bincoded_blocks.len() as u64) { + num_blocks += 1; + let mut host = Risc0Host::new(ROLLUP_ELF); + host.write_to_guest(prev_state_root); + println!( + "Requesting data for height {} and prev_state_root 0x{}", + height, + hex::encode(prev_state_root) + ); + let filtered_block = &bincoded_blocks[height as usize]; + let _header_hash = hex::encode(filtered_block.header.header.hash()); + host.write_to_guest(&filtered_block.header); + let (mut blob_txs, inclusion_proof, completeness_proof) = da_service + .extract_relevant_txs_with_proof(&filtered_block) + .await; + + host.write_to_guest(&inclusion_proof); + host.write_to_guest(&completeness_proof); + host.write_to_guest(&blob_txs); + + if !blob_txs.is_empty() { + num_blobs += blob_txs.len(); + } + + let result = demo.apply_slot(Default::default(), filtered_block, &mut blob_txs); + for r in result.batch_receipts { + let num_tx = r.tx_receipts.len(); + num_total_transactions += num_tx; + if num_tx > 0 { + num_blocks_with_txns += 1; + } + } + // println!("{:?}",result.batch_receipts); + + host.write_to_guest(&result.witness); + + println!("Skipping prover at block {height} to capture cycle counts\n"); + let _receipt = host + .run_without_proving() + .expect("Prover should run successfully"); + println!("==================================================\n"); + prev_state_root = result.state_root.0; + } + + #[cfg(feature = "bench")] + { + let hashmap_guard = GLOBAL_HASHMAP.lock(); + let metric_map = hashmap_guard.clone(); + let total_cycles = metric_map.get("Cycles per block").unwrap().0; + println!("\nBlock stats\n"); + chain_stats( + num_blocks, + num_blocks_with_txns, + num_total_transactions, + num_blobs, + ); + println!("\nCycle Metrics\n"); + print_cycle_averages(metric_map); + println!("\nTotal cycles consumed for test: {}\n", total_cycles); + } + + Ok(()) +} diff --git a/examples/demo-prover/host/benches/rollup_config.toml b/examples/demo-prover/host/benches/rollup_config.toml new file mode 100644 index 000000000..d89540e7e --- /dev/null +++ b/examples/demo-prover/host/benches/rollup_config.toml @@ -0,0 +1,20 @@ +# We define the rollup's genesis to occur at Celestia block number `start_height`. The rollup will ignore +# any Celestia blocks before this height +start_height = 1 + +[da] +# The JWT used to authenticate with the celestia light client. Instructions for generating this token can be found in the README +celestia_rpc_auth_token = "MY.SECRET.TOKEN" +# The address of the *trusted* Celestia light client to interact with +celestia_rpc_address = "http://localhost:11111/" +# The largest response the rollup will accept from the Celestia node. Defaults to 100 MB +max_celestia_response_body_size = 104_857_600 + +[runner.storage] +# The path to the rollup's data directory. Paths that do not begin with `/` are interpreted as relative paths. +path = "benches/demo_data" + +[rpc_config] +# the host and port to bind the rpc server for +bind_host = "127.0.0.1" +bind_port = 12345 diff --git a/examples/demo-prover/host/src/main.rs b/examples/demo-prover/host/src/main.rs index d5a4cdaf8..3087df823 100644 --- a/examples/demo-prover/host/src/main.rs +++ b/examples/demo-prover/host/src/main.rs @@ -32,6 +32,7 @@ const ROLLUP_NAMESPACE: NamespaceId = NamespaceId(ROLLUP_NAMESPACE_RAW); #[tokio::main] async fn main() -> Result<(), anyhow::Error> { + let skip_prover = env::var("SKIP_PROVER").is_ok(); // Initializing logging let subscriber = tracing_subscriber::fmt() .with_max_level(Level::INFO) @@ -111,10 +112,16 @@ async fn main() -> Result<(), anyhow::Error> { host.write_to_guest(&result.witness); - info!("Starting proving..."); - let receipt = host.run().expect("Prover should run successfully"); - info!("Start verifying.."); - receipt.verify(ROLLUP_ID).expect("Receipt should be valid"); + if !skip_prover { + info!("Starting proving..."); + let receipt = host.run().expect("Prover should run successfully"); + info!("Start verifying.."); + receipt.verify(ROLLUP_ID).expect("Receipt should be valid"); + } else { + let _receipt = host + .run_without_proving() + .expect("Prover should run successfully"); + } prev_state_root = result.state_root.0; info!("Completed proving and verifying block {height}"); diff --git a/examples/demo-prover/methods/Cargo.toml b/examples/demo-prover/methods/Cargo.toml index 348782fbb..8147581d2 100644 --- a/examples/demo-prover/methods/Cargo.toml +++ b/examples/demo-prover/methods/Cargo.toml @@ -9,3 +9,6 @@ risc0-build = { workspace = true } [package.metadata.risc0] methods = ["guest"] + +[features] +bench = [] diff --git a/examples/demo-prover/methods/build.rs b/examples/demo-prover/methods/build.rs index 08a8a4eb7..b4b99cdf8 100644 --- a/examples/demo-prover/methods/build.rs +++ b/examples/demo-prover/methods/build.rs @@ -1,3 +1,24 @@ +use std::collections::HashMap; + fn main() { - risc0_build::embed_methods(); + let guest_pkg_to_options = get_guest_options(); + risc0_build::embed_methods_with_options(guest_pkg_to_options); +} + +#[cfg(not(feature = "bench"))] +fn get_guest_options() -> HashMap<&'static str, risc0_build::GuestOptions> { + HashMap::new() +} + +#[cfg(feature = "bench")] +fn get_guest_options() -> HashMap<&'static str, risc0_build::GuestOptions> { + let mut guest_pkg_to_options = HashMap::new(); + guest_pkg_to_options.insert( + "sov-demo-prover-guest", + risc0_build::GuestOptions { + features: vec!["bench".to_string()], + std: true, + }, + ); + guest_pkg_to_options } diff --git a/examples/demo-prover/methods/guest/Cargo.lock b/examples/demo-prover/methods/guest/Cargo.lock index 38d712368..3b2641dc1 100644 --- a/examples/demo-prover/methods/guest/Cargo.lock +++ b/examples/demo-prover/methods/guest/Cargo.lock @@ -41,9 +41,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +checksum = "86b8f9420f797f2d9e935edf629310eb938a0d839f984e25327f3c7eed22300c" dependencies = [ "memchr", ] @@ -56,13 +56,13 @@ checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" [[package]] name = "async-trait" -version = "0.1.71" +version = "0.1.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a564d521dd56509c4c47480d00b80ee55f7e385ae48db5744c67ad50c92d2ebf" +checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.28", ] [[package]] @@ -125,6 +125,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" + [[package]] name = "blake2" version = "0.10.6" @@ -221,7 +227,7 @@ checksum = "fdde5c9cd29ebd706ce1b35600920a33550e402fc998a2e53ad3b42c3c47a192" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.28", ] [[package]] @@ -286,9 +292,9 @@ dependencies = [ [[package]] name = "const-oid" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "795bc6e66a8e340f075fcf6227e417a2dc976b92b91f3cdc778bb858778b6747" +checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" [[package]] name = "const-rollup-config" @@ -409,14 +415,20 @@ dependencies = [ [[package]] name = "der" -version = "0.7.7" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7ed52955ce76b1554f509074bb357d3fb8ac9b51288a65a3fd480d1dfba946" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" dependencies = [ "const-oid", "zeroize", ] +[[package]] +name = "deranged" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7684a49fb1af197853ef7b2ee694bc1f5b4179556f1e5710e1760c5db6f5e929" + [[package]] name = "derive_more" version = "0.99.17" @@ -556,9 +568,9 @@ dependencies = [ [[package]] name = "either" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "encoding_rs" @@ -580,9 +592,9 @@ dependencies = [ [[package]] name = "errno" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" dependencies = [ "errno-dragonfly", "libc", @@ -611,12 +623,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "1.9.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] +checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" [[package]] name = "fixedbitset" @@ -730,7 +739,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.28", ] [[package]] @@ -911,7 +920,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2", + "socket2 0.4.9", "tokio", "tower-service", "tracing", @@ -944,7 +953,7 @@ dependencies = [ "prost", "ripemd", "serde", - "sha2 0.10.7", + "sha2 0.10.6", "sha3", ] @@ -983,31 +992,11 @@ dependencies = [ "generic-array", ] -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - [[package]] name = "inventory" -version = "0.3.9" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25b1d6b4b9fb75fc419bdef998b689df5080a32931cb3395b86202046b56a9ea" - -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi", - "libc", - "windows-sys", -] +checksum = "a53088c87cf71c9d4f3372a2cb9eea1e7b8a0b1bf8b7f7d23fe5b76dbb07e63b" [[package]] name = "ipnet" @@ -1046,7 +1035,7 @@ dependencies = [ "num-derive 0.3.3", "num-traits", "serde", - "sha2 0.10.7", + "sha2 0.10.6", "thiserror", "tracing", ] @@ -1084,14 +1073,17 @@ dependencies = [ "prost", "prost-build", "prost-types", + "risc0-zkvm", + "risc0-zkvm-platform", "serde", "serde_json", - "sha2 0.10.7", + "sha2 0.10.6", "sov-rollup-interface", "tendermint", "tendermint-proto", "thiserror", "tracing", + "zk-cycle-macros", ] [[package]] @@ -1123,9 +1115,9 @@ checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" [[package]] name = "linux-raw-sys" -version = "0.3.8" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" [[package]] name = "log" @@ -1203,7 +1195,7 @@ dependencies = [ "borsh", "bytes", "serde", - "sha2 0.10.7", + "sha2 0.10.6", ] [[package]] @@ -1225,14 +1217,14 @@ checksum = "9e6a0fd4f737c707bd9086cc16c925f294943eb62eb71499e9fd4cf71f8b9f4e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.28", ] [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" dependencies = [ "autocfg", ] @@ -1270,11 +1262,11 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.55" +version = "0.10.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d" +checksum = "729b745ad4a5575dd06a3e1af1414bd330ee561c01b3899eb584baeaa8def17e" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if", "foreign-types", "libc", @@ -1291,7 +1283,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.28", ] [[package]] @@ -1302,9 +1294,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.90" +version = "0.9.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6" +checksum = "866b5f16f90776b9bb8dc1e1802ac6f0513de3a7a7465867bfbc563dc737faac" dependencies = [ "cc", "libc", @@ -1354,7 +1346,7 @@ dependencies = [ "digest 0.10.7", "hmac", "password-hash", - "sha2 0.10.7", + "sha2 0.10.6", ] [[package]] @@ -1375,9 +1367,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.10" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" +checksum = "12cc1b0bf1727a77a54b6654e7b5f1af8604923edc8b81885f8ec92f9e3f0a05" [[package]] name = "pin-utils" @@ -1491,9 +1483,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.31" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fe8a65d69dd0808184ebb5f836ab526bb259db23c657efa38711b1072ee47f0" +checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" dependencies = [ "proc-macro2", ] @@ -1570,7 +1562,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -1579,7 +1571,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -1595,9 +1587,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.9.1" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" +checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" dependencies = [ "aho-corasick", "memchr", @@ -1607,9 +1599,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.3" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" +checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" dependencies = [ "aho-corasick", "memchr", @@ -1674,9 +1666,12 @@ version = "0.1.0" dependencies = [ "anyhow", "bincode", + "bytemuck", "risc0-zkvm", + "risc0-zkvm-platform", "serde", "sov-rollup-interface", + "zk-cycle-utils", ] [[package]] @@ -1720,7 +1715,7 @@ dependencies = [ "risc0-core", "risc0-zkvm-platform", "serde", - "sha2 0.10.7", + "sha2 0.10.6", "thiserror", "tracing", ] @@ -1774,13 +1769,12 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.23" +version = "0.38.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" +checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f" dependencies = [ - "bitflags", + "bitflags 2.3.3", "errno", - "io-lifetimes", "libc", "linux-raw-sys", "windows-sys", @@ -1827,11 +1821,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.1" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "core-foundation-sys", "libc", @@ -1840,9 +1834,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" dependencies = [ "core-foundation-sys", "libc", @@ -1856,9 +1850,9 @@ checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" [[package]] name = "serde" -version = "1.0.173" +version = "1.0.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91f70896d6720bc714a4a57d22fc91f1db634680e65c8efe13323f1fa38d53f" +checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c" dependencies = [ "serde_derive", ] @@ -1874,13 +1868,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.173" +version = "1.0.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6250dde8342e0232232be9ca3db7aa40aceb5a3e5dd9bddbc00d99a007cde49" +checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.28", ] [[package]] @@ -1896,9 +1890,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.103" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d03b412469450d4404fe8499a268edd7f8b79fecb074b0d812ad64ca21f4031b" +checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c" dependencies = [ "itoa", "ryu", @@ -1907,13 +1901,13 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d89a8107374290037607734c0b73a85db7ed80cae314b3c5791f192a496e731" +checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.28", ] [[package]] @@ -1954,9 +1948,8 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +version = "0.10.6" +source = "git+https://github.com/risc0/RustCrypto-hashes?tag=sha2/v0.10.6-risc0#e75cafd9f55da196061f6fadf8bc8a86778192b7" dependencies = [ "cfg-if", "cpufeatures", @@ -2004,6 +1997,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "socket2" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" +dependencies = [ + "libc", + "windows-sys", +] + [[package]] name = "sov-accounts" version = "0.1.0" @@ -2058,10 +2061,16 @@ dependencies = [ "log", "risc0-adapter", "risc0-zkvm", + "risc0-zkvm-platform", "serde", "serde_json", - "sha2 0.10.7", + "sha2 0.10.6", + "sha3", + "sov-modules-api", + "sov-modules-stf-template", "sov-rollup-interface", + "sov-sequencer-registry", + "sov-state", "tempfile", "tracing", "zip", @@ -2095,13 +2104,16 @@ dependencies = [ "borsh", "derive_more", "ed25519-dalek", + "risc0-zkvm", + "risc0-zkvm-platform", "serde", "serde_json", - "sha2 0.10.7", + "sha2 0.10.6", "sov-modules-macros", "sov-rollup-interface", "sov-state", "thiserror", + "zk-cycle-macros", ] [[package]] @@ -2124,12 +2136,16 @@ dependencies = [ "borsh", "hex", "jmt", + "risc0-zkvm", + "risc0-zkvm-platform", "serde", "sov-modules-api", "sov-rollup-interface", "sov-state", "thiserror", "tracing", + "zk-cycle-macros", + "zk-cycle-utils", ] [[package]] @@ -2151,10 +2167,14 @@ version = "0.1.0" dependencies = [ "anyhow", "borsh", + "risc0-zkvm", + "risc0-zkvm-platform", "sov-bank", "sov-modules-api", "sov-rollup-interface", "sov-state", + "zk-cycle-macros", + "zk-cycle-utils", ] [[package]] @@ -2165,11 +2185,14 @@ dependencies = [ "borsh", "hex", "jmt", + "risc0-zkvm", + "risc0-zkvm-platform", "serde", - "sha2 0.10.7", + "sha2 0.10.6", "sov-first-read-last-write-cache", "sov-rollup-interface", "thiserror", + "zk-cycle-macros", ] [[package]] @@ -2228,9 +2251,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.26" +version = "2.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45c3457aacde3c65315de5031ec191ce46604304d2446e803d71ade03308d970" +checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" dependencies = [ "proc-macro2", "quote", @@ -2239,11 +2262,10 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.6.0" +version = "3.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" +checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651" dependencies = [ - "autocfg", "cfg-if", "fastrand", "redox_syscall 0.3.5", @@ -2271,7 +2293,7 @@ dependencies = [ "serde_bytes", "serde_json", "serde_repr", - "sha2 0.10.7", + "sha2 0.10.6", "signature 2.1.0", "subtle", "subtle-encoding", @@ -2300,30 +2322,31 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.43" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42" +checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.43" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f" +checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.28", ] [[package]] name = "time" -version = "0.3.23" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59e399c068f43a5d116fedaf73b203fa4f9c519f17e2b34f63221d3792f81446" +checksum = "b0fdd63d58b18d663fbdf70e049f00a22c8e42be082203be7f26589213cd75ea" dependencies = [ + "deranged", "serde", "time-core", "time-macros", @@ -2337,9 +2360,9 @@ checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" [[package]] name = "time-macros" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96ba15a897f3c86766b757e5ac7221554c6750054d74d5b28844fce5fb36a6c4" +checksum = "eb71511c991639bb078fd5bf97757e03914361c48100d52878b8e52b46fb92cd" dependencies = [ "time-core", ] @@ -2361,18 +2384,17 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.29.1" +version = "1.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" +checksum = "2d3ce25f50619af8b0aec2eb23deebe84249e19e2ddd393a6e16e3300a6dadfd" dependencies = [ - "autocfg", "backtrace", "bytes", "libc", "mio", "num_cpus", "pin-project-lite", - "socket2", + "socket2 0.5.3", "windows-sys", ] @@ -2435,7 +2457,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.28", ] [[package]] @@ -2461,9 +2483,9 @@ checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "typetag" -version = "0.2.10" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66aafcfb982bf1f9a28755ac6bcbdcd4631ff516cb038fa61299201ebb4364" +checksum = "aec6850cc671cd0cfb3ab285465e48a3b927d9de155051c35797446b32f9169f" dependencies = [ "erased-serde", "inventory", @@ -2474,13 +2496,13 @@ dependencies = [ [[package]] name = "typetag-impl" -version = "0.2.10" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d836cd032f71d90cbaa3c1f85ce84266af23659766d8c0b1c4c6524a0fb4c36f" +checksum = "30c49a6815b4f8379c36f06618bc1b80ca77aaf8a3fd4d8549dca6fdb016000f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.28", ] [[package]] @@ -2563,7 +2585,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.28", "wasm-bindgen-shared", ] @@ -2597,7 +2619,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.28", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2743,7 +2765,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.28", ] [[package]] @@ -2766,6 +2788,25 @@ dependencies = [ "zstd", ] +[[package]] +name = "zk-cycle-macros" +version = "0.1.0" +dependencies = [ + "anyhow", + "borsh", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "zk-cycle-utils" +version = "0.1.0" +dependencies = [ + "risc0-zkvm", + "risc0-zkvm-platform", +] + [[package]] name = "zstd" version = "0.11.2+zstd.1.5.2" diff --git a/examples/demo-prover/methods/guest/Cargo.toml b/examples/demo-prover/methods/guest/Cargo.toml index c67d73d1e..cc69e5dde 100644 --- a/examples/demo-prover/methods/guest/Cargo.toml +++ b/examples/demo-prover/methods/guest/Cargo.toml @@ -9,12 +9,17 @@ resolver = "2" [dependencies] anyhow = "1.0.68" risc0-zkvm = { version = "0.16", default-features = false, features = ["std"] } +risc0-zkvm-platform = "0.16" borsh = { version = "0.10.3", features = ["bytes"] } jupiter = { path = "../../../../adapters/celestia", default-features = false } demo-stf = { path = "../../../demo-stf", default-features = false } -sov-rollup-interface = { path = "../../../../rollup-interface" } +sov-rollup-interface = { path = "../../../../rollup-interface", default-features = false} risc0-adapter = { path = "../../../../adapters/risc0", default-features = false } const-rollup-config = { path = "../../../const-rollup-config" } +sov-modules-stf-template = {path = "../../../../module-system/sov-modules-stf-template", optional=true} +sov-state = {path = "../../../../module-system/sov-state", default-features = false, optional=true} +sov-modules-api = {path = "../../../../module-system/sov-modules-api", default-features = false, optional=true} +sov-sequencer-registry = {path = "../../../../module-system/module-implementations/sov-sequencer-registry", default-features = false, optional=true} # TODO: Just for test tracing = "0.1.37" @@ -26,9 +31,13 @@ downloader = "0.2" serde = { version = "1.0", default-features = false, features = ["derive"] } serde_json = "1.0" sha2 = "0.10.6" +sha3 = "0.10.8" tempfile = "3.5" zip = "0.6" +[patch.crates-io] +sha2 = { git = "https://github.com/risc0/RustCrypto-hashes", tag = "sha2/v0.10.6-risc0" } + [profile.dev] opt-level = 3 @@ -41,3 +50,6 @@ lto = true [profile.release.build-override] opt-level = 3 + +[features] +bench=["jupiter/bench", "sov-modules-stf-template/bench", "sov-state/bench", "sov-modules-api/bench", "sov-sequencer-registry/bench"] diff --git a/examples/demo-prover/methods/guest/src/bin/rollup.rs b/examples/demo-prover/methods/guest/src/bin/rollup.rs index 1232ec9c9..63040448c 100644 --- a/examples/demo-prover/methods/guest/src/bin/rollup.rs +++ b/examples/demo-prover/methods/guest/src/bin/rollup.rs @@ -19,6 +19,7 @@ use sov_rollup_interface::services::da::SlotData; use sov_rollup_interface::stf::StateTransitionFunction; use sov_rollup_interface::zk::{StateTransition, ZkvmGuest}; + // The rollup stores its data in the namespace b"sov-test" on Celestia const ROLLUP_NAMESPACE: NamespaceId = NamespaceId(ROLLUP_NAMESPACE_RAW); @@ -32,9 +33,12 @@ risc0_zkvm::guest::entry!(main); // 5. Call end_slot // 6. Output (Da hash, start_root, end_root, event_root) pub fn main() { + env::write(&"Start guest\n"); let guest = Risc0Guest; + #[cfg(feature = "bench")] + let start_cycles = env::get_cycle_count(); let prev_state_root_hash: [u8; 32] = guest.read_from_host(); env::write(&"Prev root hash read\n"); // Step 1: read tx list @@ -55,11 +59,13 @@ pub fn main() { let witness: ArrayWitness = guest.read_from_host(); env::write(&"Witness have been read\n"); + env::write(&"Applying slot...\n"); let result = app.apply_slot(witness, &header, &mut blobs); env::write(&"Slot has been applied\n"); + // Step 3: Verify tx list let verifier = CelestiaVerifier::new(jupiter::verifier::RollupParams { namespace: ROLLUP_NAMESPACE, @@ -80,5 +86,27 @@ pub fn main() { slot_hash: header.hash(), }; env::commit(&output); + env::write(&"new state root committed\n"); + + #[cfg(feature = "bench")] + let end_cycles = env::get_cycle_count(); + + #[cfg(feature = "bench")] + { + let tuple = ("Cycles per block".to_string(), (end_cycles - start_cycles) as u64); + let mut serialized = Vec::new(); + serialized.extend(tuple.0.as_bytes()); + serialized.push(0); + let size_bytes = tuple.1.to_ne_bytes(); + serialized.extend(&size_bytes); + + // calculate the syscall name. + let cycle_string = String::from("cycle_metrics\0"); + let metrics_syscall_name = unsafe { + risc0_zkvm_platform::syscall::SyscallName::from_bytes_with_nul(cycle_string.as_ptr()) + }; + + risc0_zkvm::guest::env::send_recv_slice::(metrics_syscall_name, &serialized); + } } diff --git a/examples/demo-simple-stf/Cargo.toml b/examples/demo-simple-stf/Cargo.toml index fbd146cad..40f86de59 100644 --- a/examples/demo-simple-stf/Cargo.toml +++ b/examples/demo-simple-stf/Cargo.toml @@ -16,6 +16,5 @@ hex = { workspace = true } sov-rollup-interface = { path = "../../rollup-interface" } - [dev-dependencies] sov-rollup-interface = { path = "../../rollup-interface", features = ["mocks"] } diff --git a/examples/demo-stf/Cargo.toml b/examples/demo-stf/Cargo.toml index c77e1ddf8..ff317b5ad 100644 --- a/examples/demo-stf/Cargo.toml +++ b/examples/demo-stf/Cargo.toml @@ -32,7 +32,7 @@ sov-election = { path = "../../module-system/module-implementations/examples/sov sov-sequencer-registry = { path = "../../module-system/module-implementations/sov-sequencer-registry", default-features = false } sov-blob-storage = { path = "../../module-system/module-implementations/sov-blob-storage", default-features = false } sov-bank = { path = "../../module-system/module-implementations/sov-bank", default-features = false } -sov-modules-stf-template = { path = "../../module-system/sov-modules-stf-template" } # no features available +sov-modules-stf-template = { path = "../../module-system/sov-modules-stf-template", default-features = false } sov-value-setter = { path = "../../module-system/module-implementations/examples/sov-value-setter", default-features = false } sov-accounts = { path = "../../module-system/module-implementations/sov-accounts", default-features = false } sov-state = { path = "../../module-system/sov-state", default-features = false } diff --git a/module-system/module-implementations/sov-sequencer-registry/Cargo.toml b/module-system/module-implementations/sov-sequencer-registry/Cargo.toml index b0e111f4e..7af60e973 100644 --- a/module-system/module-implementations/sov-sequencer-registry/Cargo.toml +++ b/module-system/module-implementations/sov-sequencer-registry/Cargo.toml @@ -29,8 +29,13 @@ serde = { workspace = true, optional = true } serde_json = { workspace = true, optional = true } borsh = { workspace = true, features = ["rc"] } jsonrpsee = { workspace = true, features = ["macros", "client-core", "server"], optional = true } +zk-cycle-macros = {path = "../../../utils/zk-cycle-macros", optional=true} +risc0-zkvm = { version = "0.16", default-features = false, features = ["std"], optional=true} +risc0-zkvm-platform = { version = "0.16", optional=true} +zk-cycle-utils = {path = "../../../utils/zk-cycle-utils", optional=true} [features] +bench = ["zk-cycle-macros/bench", "risc0-zkvm","risc0-zkvm-platform","zk-cycle-utils"] default = ["native"] serde = ["dep:serde", "dep:serde_json"] native = ["serde", "sov-modules-api/native", "sov-state/native", "sov-bank/native", "dep:jsonrpsee", "dep:schemars", "dep:clap"] diff --git a/module-system/module-implementations/sov-sequencer-registry/src/hooks.rs b/module-system/module-implementations/sov-sequencer-registry/src/hooks.rs index e0d72567e..cef202eae 100644 --- a/module-system/module-implementations/sov-sequencer-registry/src/hooks.rs +++ b/module-system/module-implementations/sov-sequencer-registry/src/hooks.rs @@ -2,6 +2,10 @@ use sov_modules_api::hooks::ApplyBlobHooks; use sov_modules_api::Context; use sov_rollup_interface::da::BlobReaderTrait; use sov_state::WorkingSet; +#[cfg(all(target_os = "zkvm", feature = "bench"))] +use zk_cycle_macros::cycle_tracker; +#[cfg(all(target_os = "zkvm", feature = "bench"))] +use zk_cycle_utils::print_cycle_count; use crate::{SequencerOutcome, SequencerRegistry}; @@ -9,14 +13,19 @@ impl ApplyBlobHooks for SequencerRegistry type Context = C; type BlobResult = SequencerOutcome; + #[cfg_attr(all(target_os = "zkvm", feature = "bench"), cycle_tracker)] fn begin_blob_hook( &self, blob: &mut B, working_set: &mut WorkingSet<::Storage>, ) -> anyhow::Result<()> { + #[cfg(all(target_os = "zkvm", feature = "bench"))] + print_cycle_count(); if !self.is_sender_allowed(&blob.sender(), working_set) { anyhow::bail!("sender {} is not allowed to submit blobs", blob.sender()); } + #[cfg(all(target_os = "zkvm", feature = "bench"))] + print_cycle_count(); Ok(()) } diff --git a/module-system/sov-modules-api/Cargo.toml b/module-system/sov-modules-api/Cargo.toml index 3484e8af7..75e128c18 100644 --- a/module-system/sov-modules-api/Cargo.toml +++ b/module-system/sov-modules-api/Cargo.toml @@ -31,12 +31,16 @@ schemars = { workspace = true, optional = true, features = [] } ed25519-dalek = { version = "1.0.1", default-features = false, features = ["alloc", "u64_backend"] } rand = { version = "0.7", optional = true } +zk-cycle-macros = {path = "../../utils/zk-cycle-macros", optional=true } +risc0-zkvm = { version = "0.16", default-features = false, features = ["std"],optional=true } +risc0-zkvm-platform = { version = "0.16",optional=true} [dev-dependencies] serde_json = { workspace = true } bincode = { workspace = true } [features] +bench = ["zk-cycle-macros","risc0-zkvm","risc0-zkvm-platform"] default = ["native", "macros"] native = ["sov-state/native", "rand", "hex", "schemars", "ed25519-dalek/default", "clap", "jsonrpsee", "macros", "sov-modules-macros/native"] macros = ["sov-modules-macros"] diff --git a/module-system/sov-modules-api/src/transaction.rs b/module-system/sov-modules-api/src/transaction.rs index d94b8cdd0..859cc1863 100644 --- a/module-system/sov-modules-api/src/transaction.rs +++ b/module-system/sov-modules-api/src/transaction.rs @@ -1,3 +1,6 @@ +#[cfg(all(target_os = "zkvm", feature = "bench"))] +use zk_cycle_macros::cycle_tracker; + #[cfg(feature = "native")] use crate::PrivateKey; use crate::{Context, Signature}; @@ -29,6 +32,7 @@ impl Transaction { } /// Check whether the transaction has been signed correctly. + #[cfg_attr(all(target_os = "zkvm", feature = "bench"), cycle_tracker)] pub fn verify(&self) -> anyhow::Result<()> { let mut serialized_tx = Vec::with_capacity(self.runtime_msg().len() + std::mem::size_of::()); diff --git a/module-system/sov-modules-stf-template/Cargo.toml b/module-system/sov-modules-stf-template/Cargo.toml index 7b8697c64..e01bd2064 100644 --- a/module-system/sov-modules-stf-template/Cargo.toml +++ b/module-system/sov-modules-stf-template/Cargo.toml @@ -23,3 +23,12 @@ hex = { workspace = true } sov-rollup-interface = { path = "../../rollup-interface", version = "0.1" } sov-state = { path = "../sov-state", version = "0.1", default-features = false } sov-modules-api = { path = "../sov-modules-api", version = "0.1", default-features = false } +zk-cycle-macros = {path = "../../utils/zk-cycle-macros", optional=true} +risc0-zkvm = { version = "0.16", default-features = false, features = ["std"], optional=true} +risc0-zkvm-platform = { version = "0.16", optional=true} +zk-cycle-utils = {path = "../../utils/zk-cycle-utils", optional=true} + +[features] +bench = ["zk-cycle-macros/bench","zk-cycle-utils", "risc0-zkvm","risc0-zkvm-platform"] +default = ["native"] +native = [] diff --git a/module-system/sov-modules-stf-template/src/app_template.rs b/module-system/sov-modules-stf-template/src/app_template.rs index f11a9be2a..36eac05d9 100644 --- a/module-system/sov-modules-stf-template/src/app_template.rs +++ b/module-system/sov-modules-stf-template/src/app_template.rs @@ -14,6 +14,9 @@ use crate::{Batch, Runtime, SequencerOutcome, SlashingReason, TxEffect}; type ApplyBatchResult = Result>; +#[cfg(all(target_os = "zkvm", feature = "bench"))] +use zk_cycle_macros::cycle_tracker; + /// An implementation of the /// [`StateTransitionFunction`](sov_rollup_interface::stf::StateTransitionFunction) /// that is specifically designed to work with the module-system. @@ -88,6 +91,7 @@ where } } + #[cfg_attr(all(target_os = "zkvm", feature = "bench"), cycle_tracker)] pub(crate) fn apply_blob( &mut self, blob: &mut B, @@ -234,6 +238,7 @@ where }; self.checkpoint = Some(batch_workspace.checkpoint()); + Ok(BatchReceipt { batch_hash: blob.hash(), tx_receipts, diff --git a/module-system/sov-modules-stf-template/src/lib.rs b/module-system/sov-modules-stf-template/src/lib.rs index 399dea1ee..8ba4ec9e8 100644 --- a/module-system/sov-modules-stf-template/src/lib.rs +++ b/module-system/sov-modules-stf-template/src/lib.rs @@ -17,6 +17,8 @@ use sov_rollup_interface::AddressTrait; use sov_state::{StateCheckpoint, Storage, WorkingSet}; use tracing::info; pub use tx_verifier::RawTx; +#[cfg(all(target_os = "zkvm", feature = "bench"))] +use zk_cycle_macros::cycle_tracker; /// This trait has to be implemented by a runtime in order to be used in `AppTemplate`. pub trait Runtime: @@ -74,6 +76,7 @@ where B: BlobReaderTrait, RT: Runtime, { + #[cfg_attr(all(target_os = "zkvm", feature = "bench"), cycle_tracker)] fn begin_slot( &mut self, slot_data: &impl SlotData, @@ -88,6 +91,7 @@ where self.checkpoint = Some(working_set.checkpoint()); } + #[cfg_attr(all(target_os = "zkvm", feature = "bench"), cycle_tracker)] fn end_slot(&mut self) -> (jmt::RootHash, <::Storage as Storage>::Witness) { let (cache_log, witness) = self.checkpoint.take().unwrap().freeze(); let root_hash = self @@ -191,11 +195,10 @@ where tx_receipt.receipt ); } - batch_receipts.push(batch_receipt); + batch_receipts.push(batch_receipt.clone()); } let (state_root, witness) = self.end_slot(); - SlotResult { state_root, batch_receipts, diff --git a/module-system/sov-state/Cargo.toml b/module-system/sov-state/Cargo.toml index 5d2d181af..03b629e53 100644 --- a/module-system/sov-state/Cargo.toml +++ b/module-system/sov-state/Cargo.toml @@ -16,16 +16,21 @@ anyhow = { workspace = true } borsh = { workspace = true } serde = { workspace = true } thiserror = { workspace = true } -sov-rollup-interface = { path = "../../rollup-interface", version = "0.1" } +sov-rollup-interface = { path = "../../rollup-interface", version = "0.1"} sov-db = { path = "../../full-node/db/sov-db", version = "0.1", optional = true } sov-first-read-last-write-cache = { path = "../utils/sov-first-read-last-write-cache", version = "0.1" } jmt = { workspace = true } hex = { workspace = true } sha2 = { workspace = true } +zk-cycle-macros = {path = "../../utils/zk-cycle-macros", optional=true } +risc0-zkvm = { version = "0.16", default-features = false, features = ["std"], optional=true } +risc0-zkvm-platform = { version = "0.16", optional=true} + [dev-dependencies] tempfile = { workspace = true } [features] +bench = ["zk-cycle-macros","risc0-zkvm","risc0-zkvm-platform"] default = ["native"] native = ["sov-db"] diff --git a/module-system/sov-state/src/zk_storage.rs b/module-system/sov-state/src/zk_storage.rs index 216ab5408..9e4ba55ba 100644 --- a/module-system/sov-state/src/zk_storage.rs +++ b/module-system/sov-state/src/zk_storage.rs @@ -2,12 +2,17 @@ use std::marker::PhantomData; use std::sync::Arc; use jmt::{JellyfishMerkleTree, KeyHash, Version}; +#[cfg(all(target_os = "zkvm", feature = "bench"))] +use zk_cycle_macros::cycle_tracker; use crate::internal_cache::OrderedReadsAndWrites; use crate::storage::{StorageKey, StorageProof, StorageValue}; use crate::witness::{TreeWitnessReader, Witness}; use crate::{MerkleProofSpec, Storage}; +#[cfg(all(target_os = "zkvm", feature = "bench"))] +extern crate risc0_zkvm; + pub struct ZkStorage { prev_state_root: [u8; 32], _phantom_hasher: PhantomData, @@ -50,6 +55,7 @@ impl Storage for ZkStorage { Ok(witness.get_hint()) } + #[cfg_attr(all(target_os = "zkvm", feature = "bench"), cycle_tracker)] fn validate_and_commit( &self, state_accesses: OrderedReadsAndWrites, @@ -93,7 +99,6 @@ impl Storage for ZkStorage { let (new_root, _tree_update) = jmt .put_value_set(batch, next_version) .expect("JMT update must succeed"); - Ok(new_root.0) } diff --git a/utils/README.md b/utils/README.md new file mode 100644 index 000000000..2ff10d9a2 --- /dev/null +++ b/utils/README.md @@ -0,0 +1,4 @@ +## Utils +This folder contains a general set of utils that are used as helpers for the SDK. +* Non-SDK macros (eg: macro for wrapping a function to track the number of risc0 cycles) +* Binary to perform stack analysis on the risc0 ELF and count the number of instruction cyles \ No newline at end of file diff --git a/utils/zk-cycle-macros/Cargo.toml b/utils/zk-cycle-macros/Cargo.toml new file mode 100644 index 000000000..6539e9e7a --- /dev/null +++ b/utils/zk-cycle-macros/Cargo.toml @@ -0,0 +1,37 @@ +[package] +name = "zk-cycle-macros" +description = "cycle counting utils" +authors = { workspace = true } +edition = { workspace = true } +homepage = { workspace = true } +license = { workspace = true } +repository = { workspace = true } +rust-version = { workspace = true } +version = { workspace = true } +readme = "README.md" +resolver = "2" +autotests = false + +[lib] +proc-macro = true + +[[test]] +name = "tests" +path = "tests/all_tests.rs" + +[dependencies] +anyhow = { workspace = true } +syn = { version = "1.0", features = ["full"] } +quote = "1.0" +proc-macro2 = "1.0" +borsh = { workspace = true } + +[dev-dependencies] +trybuild = "1.0" +zk-cycle-macros = {path = "../../utils/zk-cycle-macros"} +risc0-zkvm = { version = "0.16", default-features = false, features = ["std"]} +risc0-zkvm-platform = { version = "0.16"} +zk-cycle-utils = {path = "../../utils/zk-cycle-utils"} + +[features] +bench=[] \ No newline at end of file diff --git a/utils/zk-cycle-macros/README.md b/utils/zk-cycle-macros/README.md new file mode 100644 index 000000000..b2e4323f4 --- /dev/null +++ b/utils/zk-cycle-macros/README.md @@ -0,0 +1,39 @@ +## Zk-cycle-macros +* Contains the `cycle-tracker` macro which can be used to annotate functions that run inside the risc0 vm +* In order to use the macro, the following changes need to be made +* Cargo.toml +```toml +[dependencies] +zk-cycle-macros = {path = "../../utils/zk-cycle-macros", optional=true} +risc0-zkvm = { version = "0.16", default-features = false, features = ["std"], optional=true} +risc0-zkvm-platform = { version = "0.16", optional=true} +zk-cycle-utils = {path = "../../utils/zk-cycle-utils", optional=true} + +[features] +bench = ["zk-cycle-macros/bench","zk-cycle-utils", "risc0-zkvm","risc0-zkvm-platform"] +``` +* The feature gating is needed because we don't want the cycle tracker scaffolding to be used unless the `bench` feature is enabled +* If the `bench` feature is not enabled, the risc0 host will not be built with the necessary syscalls to support tracking cycles +* The additional imports are necessary because the macro wraps the user function with the necessary code for tracking the number of cycles before and after the function execution +* The rust code that needs to use the `cycle_tracker` macro needs to import it and then annotate the function with it +```rust,ignore +// +#[cfg(all(target_os = "zkvm", feature = "bench"))] +use zk_cycle_macros::cycle_tracker; +// +// +#[cfg_attr(all(target_os = "zkvm", feature = "bench"), cycle_tracker)] +fn begin_slot( + &mut self, + slot_data: &impl SlotData, + witness: >::Witness, +) { + let state_checkpoint = StateCheckpoint::with_witness(self.current_storage.clone(), witness); + + let mut working_set = state_checkpoint.to_revertable(); + + self.runtime.begin_slot_hook(slot_data, &mut working_set); + + self.checkpoint = Some(working_set.checkpoint()); +} +``` \ No newline at end of file diff --git a/utils/zk-cycle-macros/src/lib.rs b/utils/zk-cycle-macros/src/lib.rs new file mode 100644 index 000000000..3b9fa72f0 --- /dev/null +++ b/utils/zk-cycle-macros/src/lib.rs @@ -0,0 +1,68 @@ +#![deny(missing_docs)] +#![doc = include_str!("../README.md")] +extern crate proc_macro; + +use proc_macro::TokenStream; +use quote::quote; +use syn::{parse_macro_input, ItemFn}; + +/// This macro is used to annotate functions that we want to track the number of riscV cycles being +/// generated inside the VM. The purpose of the this macro is to measure how many cycles a rust +/// function takes because prover time is directly proportional to the number of riscv cycles +/// generated. It does this by making use of a risc0 provided function +/// ```rust,ignore +/// risc0_zkvm::guest::env::get_cycle_count +/// ``` +/// The macro essentially generates new function with the same name by wrapping the body with a get_cycle_count +/// at the beginning and end of the function, subtracting it and then emitting it out using the +/// a custom syscall that is generated when the prover is run with the `bench` feature. +/// `send_recv_slice` is used to communicate and pass a slice to the syscall that we defined. +/// The handler for the syscall can be seen in adapters/risc0/src/host.rs and adapters/risc0/src/metrics.rs +#[proc_macro_attribute] +pub fn cycle_tracker(_attr: TokenStream, item: TokenStream) -> TokenStream { + let input = parse_macro_input!(item as ItemFn); + + match wrap_function(input) { + Ok(ok) => ok, + Err(err) => err.to_compile_error().into(), + } +} + +fn wrap_function(input: ItemFn) -> Result { + let visibility = &input.vis; + let name = &input.sig.ident; + let inputs = &input.sig.inputs; + let output = &input.sig.output; + let block = &input.block; + let generics = &input.sig.generics; + let where_clause = &input.sig.generics.where_clause; + let risc0_zkvm = syn::Ident::new("risc0_zkvm", proc_macro2::Span::call_site()); + let risc0_zkvm_platform = + syn::Ident::new("risc0_zkvm_platform", proc_macro2::Span::call_site()); + + let result = quote! { + #visibility fn #name #generics (#inputs) #output #where_clause { + let before = #risc0_zkvm::guest::env::get_cycle_count(); + let result = (|| #block)(); + let after = #risc0_zkvm::guest::env::get_cycle_count(); + + // simple serialization to avoid pulling in bincode or other libs + let tuple = (stringify!(#name).to_string(), (after - before) as u64); + let mut serialized = Vec::new(); + serialized.extend(tuple.0.as_bytes()); + serialized.push(0); + let size_bytes = tuple.1.to_ne_bytes(); + serialized.extend(&size_bytes); + + // calculate the syscall name. + let cycle_string = String::from("cycle_metrics\0"); + let metrics_syscall_name = unsafe { + #risc0_zkvm_platform::syscall::SyscallName::from_bytes_with_nul(cycle_string.as_ptr()) + }; + + #risc0_zkvm::guest::env::send_recv_slice::(metrics_syscall_name, &serialized); + result + } + }; + Ok(result.into()) +} diff --git a/utils/zk-cycle-macros/tests/all_tests.rs b/utils/zk-cycle-macros/tests/all_tests.rs new file mode 100644 index 000000000..b46f71d6c --- /dev/null +++ b/utils/zk-cycle-macros/tests/all_tests.rs @@ -0,0 +1,5 @@ +#[test] +fn cycle_macro_tests() { + let t = trybuild::TestCases::new(); + t.pass("tests/cycle_macro.rs"); +} diff --git a/utils/zk-cycle-macros/tests/cycle_macro.rs b/utils/zk-cycle-macros/tests/cycle_macro.rs new file mode 100644 index 000000000..5248fbe09 --- /dev/null +++ b/utils/zk-cycle-macros/tests/cycle_macro.rs @@ -0,0 +1,74 @@ +use zk_cycle_macros::cycle_tracker; +use std::marker::PhantomData; + +struct TestStruct; + +impl TestStruct { + #[cycle_tracker] + fn _struct_method() {} + + #[cycle_tracker] + fn _struct_method_with_self(&self) {} +} + +struct TestStructGeneric { + _phantom_t: PhantomData, + _phantom_u: PhantomData, +} + +impl TestStructGeneric { + #[cycle_tracker] + fn _generic_method(&self, _t: T, _u: U) {} +} + +#[cycle_tracker] +fn _generic_function(_t: T, _u: U) {} + +#[cycle_tracker] +fn _lifetime_function<'a>(s: &'a str) -> &'a str { + s +} + +struct TestStructLifetime<'a> { + s: &'a str, +} + +impl<'a> TestStructLifetime<'a> { + #[cycle_tracker] + fn _lifetime_method(&self) -> &'a str { + self.s + } +} + +struct TestStructAssociated; + +impl TestStructAssociated { + #[cycle_tracker] + fn _associated_function_no_self(_value: T) {} +} + +#[cycle_tracker] +fn _type_param_clause_function(_t: T) {} + +#[cycle_tracker] +fn _where_clause_function(value: T) + where T: Clone + std::fmt::Debug { + println!("{:?}", value.clone()); +} + + +#[cycle_tracker] +fn _function_without_params() { +} + +#[cycle_tracker] +fn _function_with_params(_a: u32, _b: usize) { +} + +#[cycle_tracker] +pub fn _function_with_access_specifier(_a: u32, _b: usize) { +} + +fn main() { + +} \ No newline at end of file diff --git a/utils/zk-cycle-utils/Cargo.toml b/utils/zk-cycle-utils/Cargo.toml new file mode 100644 index 000000000..17cd6f00b --- /dev/null +++ b/utils/zk-cycle-utils/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "zk-cycle-utils" +authors = { workspace = true } +edition = { workspace = true } +homepage = { workspace = true } +license = { workspace = true } +repository = { workspace = true } +rust-version = { workspace = true } +version = { workspace = true } +readme = "README.md" +resolver = "2" +autotests = false + +[dependencies] +risc0-zkvm = { version = "0.16", default-features = false, features = ['std'] } +risc0-zkvm-platform = { version = "0.16" } diff --git a/utils/zk-cycle-utils/README.md b/utils/zk-cycle-utils/README.md new file mode 100644 index 000000000..8a426efdc --- /dev/null +++ b/utils/zk-cycle-utils/README.md @@ -0,0 +1,64 @@ +## Tracer +* The tracer binary makes use of goblin, capstone and rustc-demangle to disassemble the riscV ELF and build a symbol table +* The execution trace for the rollup ELF is generated by running the `demo-prover` with the `ROLLUP_TRACE` environment variable set to the desired path +```bash +cd examples/demo-prover/host +ROLLUP_TRACE=rollup.trace cargo bench --bench prover_bench --features bench +``` +* `rollup.trace` now contains the program counter values for the run of the demo-prover (how many ever blocks, blobs and transactions we configured it for) +* The corresponding ELF used for the trace is found at +```bash +$ file target/riscv-guest/riscv32im-risc0-zkvm-elf/release/rollup +target/riscv-guest/riscv32im-risc0-zkvm-elf/release/rollup: ELF 32-bit LSB executable, UCB RISC-V, soft-float ABI, version 1 (SYSV), statically linked, with debug_info, not stripped +``` +* Both the above files are passed as input to the tracer +```bash +% cargo run -- --rollup-elf ../../../examples/demo-prover/target/riscv-guest/riscv32im-risc0-zkvm-elf/release/rollup --rollup-trace ../../../examples/demo-prover/host/rollup.trace + Finished dev [unoptimized + debuginfo] target(s) in 0.11s + Running `target/debug/tracer --rollup-elf ../../../examples/demo-prover/target/riscv-guest/riscv32im-risc0-zkvm-elf/release/rollup --rollup-trace ../../../examples/demo-prover/rollup.trace` + [00:01:04] [########################################] 16154861/16154861 (0s) + +Total instructions in trace: 16154861 + + + Instruction counts considering call graph ++--------------------------------------------------------------------------------------------+-------------------+ +| Function Name | Instruction Count | ++============================================================================================+===================+ +| __start | 16154854 | ++--------------------------------------------------------------------------------------------+-------------------+ +| main | 16153565 | ++--------------------------------------------------------------------------------------------+-------------------+ +| rollup::main::h089e03181dac539a | 16153559 | ++--------------------------------------------------------------------------------------------+-------------------+ +| sov_modules_stf_template:: for | | +| sov_modules_stf_template::app_template::AppTemplate>::apply_slot::h820293d | | +| c8d744201 | | ++--------------------------------------------------------------------------------------------+-------------------+ +| ed25519_dalek::public::PublicKey::verify_strict::hfad17f99efbd2cd0 | 13528566 | ++--------------------------------------------------------------------------------------------+-------------------+ +| <&curve25519_dalek::backend::serial::u64::field::FieldElement51 as | 8295218 | +| core::ops::arith::Mul<&curve25519_dalek::backend::serial::u64::field::FieldElement51>>::mu | | +| l::h39351372a97422dd | | +. +. +. ++--------------------------------------------------------------------------------------------+-------------------+ +``` +* The tracer also generates a pure count of instructions without considering the stack +* There are other options that can be passed which are self documented in the cli +```bash +Usage: tracer [OPTIONS] --rollup-elf --rollup-trace + +Options: + -t, --top Include the "top" number of functions [default: 30] + --no-stack-counts Don't print stack aware instruction counts + --no-raw-counts Don't print raw (stack un-aware) instruction counts + --rollup-elf Path to the riscv32 elf + --rollup-trace Path to the rollup trace. File must be one u64 program counter per line + -s, --strip-hashes Strip the hashes from the function name while printing + -h, --help Print help + -V, --version Print version + +``` \ No newline at end of file diff --git a/utils/zk-cycle-utils/src/lib.rs b/utils/zk-cycle-utils/src/lib.rs new file mode 100644 index 000000000..4837645c9 --- /dev/null +++ b/utils/zk-cycle-utils/src/lib.rs @@ -0,0 +1,30 @@ +use risc0_zkvm_platform::syscall::SyscallName; + +pub fn get_syscall_name() -> SyscallName { + let cycle_string = "cycle_metrics\0"; + let bytes = cycle_string.as_bytes(); + unsafe { SyscallName::from_bytes_with_nul(bytes.as_ptr()) } +} + +pub fn cycle_count_callback(input: &[u8]) -> Vec { + if input.len() == std::mem::size_of::() { + let mut array = [0u8; std::mem::size_of::()]; + array.copy_from_slice(input); + println!("== syscall ==> {}", usize::from_le_bytes(array)); + } else { + println!("NONE"); + } + vec![] +} + +pub fn get_syscall_name_cycles() -> SyscallName { + let cycle_string = "cycle_count\0"; + let bytes = cycle_string.as_bytes(); + unsafe { SyscallName::from_bytes_with_nul(bytes.as_ptr()) } +} + +pub fn print_cycle_count() { + let metrics_syscall_name = get_syscall_name_cycles(); + let serialized = (risc0_zkvm::guest::env::get_cycle_count() as u64).to_le_bytes(); + risc0_zkvm::guest::env::send_recv_slice::(metrics_syscall_name, &serialized); +} diff --git a/utils/zk-cycle-utils/tracer/Cargo.lock b/utils/zk-cycle-utils/tracer/Cargo.lock new file mode 100644 index 000000000..0969d930a --- /dev/null +++ b/utils/zk-cycle-utils/tracer/Cargo.lock @@ -0,0 +1,782 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8f9420f797f2d9e935edf629310eb938a0d839f984e25327f3c7eed22300c" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is-terminal", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" + +[[package]] +name = "anstyle-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "anstyle-wincon" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c677ab05e09154296dd37acecd46420c17b9713e8366facafa8fc0885167cf4c" +dependencies = [ + "anstyle", + "windows-sys 0.48.0", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" + +[[package]] +name = "capstone" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1097e608594dad3bad608295567f757742b883606fe150faf7a9740b849730d8" +dependencies = [ + "capstone-sys", + "libc", +] + +[[package]] +name = "capstone-sys" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e7f651d5ec4c2a2e6c508f2c8032655003cd728ec85663e9796616990e25b5a" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "cc" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01" +dependencies = [ + "libc", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clap" +version = "4.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c27cdf28c0f604ba3f512b0c9a409f8de8513e4816705deb0498b627e7c3a3fd" +dependencies = [ + "clap_builder", + "clap_derive", + "once_cell", +] + +[[package]] +name = "clap_builder" +version = "4.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08a9f1ab5e9f01a9b81f202e8562eb9a10de70abf9eaeac1be465c28b75aa4aa" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.28", +] + +[[package]] +name = "clap_lex" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "console" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" +dependencies = [ + "encode_unicode 0.3.6", + "lazy_static", + "libc", + "unicode-width", + "windows-sys 0.45.0", +] + +[[package]] +name = "csv" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "626ae34994d3d8d668f4269922248239db4ae42d538b14c398b74a52208e8086" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" +dependencies = [ + "memchr", +] + +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + +[[package]] +name = "errno" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "goblin" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d20fd25aa456527ce4f544271ae4fea65d2eda4a6561ea56f39fb3ee4f7e3884" +dependencies = [ + "log", + "plain", + "scroll", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" + +[[package]] +name = "indicatif" +version = "0.17.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b297dc40733f23a0e52728a58fa9489a5b7638a324932de16b41adc3ef80730" +dependencies = [ + "console", + "instant", + "number_prefix", + "portable-atomic", + "unicode-width", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "is-terminal" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +dependencies = [ + "hermit-abi", + "rustix", + "windows-sys 0.48.0", +] + +[[package]] +name = "itoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.147" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + +[[package]] +name = "linux-raw-sys" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" + +[[package]] +name = "log" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" + +[[package]] +name = "portable-atomic" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f32154ba0af3a075eefa1eda8bb414ee928f62303a54ea85b8d6638ff1a6ee9e" + +[[package]] +name = "prettytable-rs" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eea25e07510aa6ab6547308ebe3c036016d162b8da920dbb079e3ba8acf3d95a" +dependencies = [ + "csv", + "encode_unicode 1.0.0", + "is-terminal", + "lazy_static", + "term", + "unicode-width", +] + +[[package]] +name = "proc-macro2" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom", + "redox_syscall", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustix" +version = "0.38.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "172891ebdceb05aa0005f533a6cbfca599ddd7d966f6f5d4d9b2e70478e70399" +dependencies = [ + "bitflags 2.3.3", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + +[[package]] +name = "ryu" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + +[[package]] +name = "scroll" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fda28d4b4830b807a8b43f7b0e6b5df875311b3e7621d84577188c175b6ec1ec" +dependencies = [ + "scroll_derive", +] + +[[package]] +name = "scroll_derive" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aaaae8f38bb311444cfb7f1979af0bc9240d95795f75f9ceddf6a59b79ceffa0" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "serde" +version = "1.0.183" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c" + +[[package]] +name = "smawk" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f67ad224767faa3c7d8b6d91985b78e70a1324408abcb1cfcc2be4c06bc06043" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi", +] + +[[package]] +name = "textwrap" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" +dependencies = [ + "smawk", + "unicode-linebreak", + "unicode-width", +] + +[[package]] +name = "thiserror" +version = "1.0.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + +[[package]] +name = "tracer" +version = "0.1.0" +dependencies = [ + "capstone", + "clap", + "goblin", + "indicatif", + "prettytable-rs", + "regex", + "rustc-demangle", + "textwrap", +] + +[[package]] +name = "unicode-ident" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" + +[[package]] +name = "unicode-linebreak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" + +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.1", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +dependencies = [ + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" diff --git a/utils/zk-cycle-utils/tracer/Cargo.toml b/utils/zk-cycle-utils/tracer/Cargo.toml new file mode 100644 index 000000000..82aa8d505 --- /dev/null +++ b/utils/zk-cycle-utils/tracer/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "tracer" +version = "0.1.0" +edition = "2018" + +[workspace] + +[dependencies] +rustc-demangle = "0.1.18" +goblin = "0.2" +capstone = "0.11.0" +regex = "1.5.4" +prettytable-rs = "^0.10" +textwrap = "0.16.0" +indicatif = "0.17.6" +clap = {version = "4.3.21", features = ['derive']} \ No newline at end of file diff --git a/utils/zk-cycle-utils/tracer/src/main.rs b/utils/zk-cycle-utils/tracer/src/main.rs new file mode 100644 index 000000000..4feb167db --- /dev/null +++ b/utils/zk-cycle-utils/tracer/src/main.rs @@ -0,0 +1,269 @@ +use std::process::Command; +use std::str; +use std::cmp::Ordering; +use std::collections::HashMap; +use std::fs::read_to_string; +use prettytable::{Table, Row, Cell, format}; +use textwrap::wrap; +use indicatif::{ProgressBar, ProgressStyle}; +use goblin::elf::{Elf, sym::STT_FUNC}; +use rustc_demangle::demangle; +use regex::Regex; +use clap::Parser; + +#[derive(Parser, Debug)] +#[command(author, version, about, long_about = None)] +struct Args { + #[arg(short, long, default_value_t = 30)] + /// Include the "top" number of functions + top: usize, + + #[arg(long)] + /// Don't print stack aware instruction counts + no_stack_counts: bool, + + #[arg(long)] + /// Don't print raw (stack un-aware) instruction counts + no_raw_counts: bool, + + #[arg(long, required=true)] + /// Path to the riscv32 elf + rollup_elf: String, + + #[arg(long, required=true)] + /// Path to the rollup trace. + /// File must be one u64 program counter per line + rollup_trace: String, + + #[arg(short, long)] + /// Strip the hashes from the function name while printing + strip_hashes: bool, +} + +fn strip_hash(name_with_hash: &str) -> String { + let re = Regex::new(r"::h[0-9a-fA-F]+$").unwrap(); + re.replace(name_with_hash, "").to_string() +} + +fn print_intruction_counts(count_vec: Vec<(&String, &usize)>, top_n: usize, strip_hashes: bool) { + let mut table = Table::new(); + table.set_format(*format::consts::FORMAT_DEFAULT); + table.set_titles(Row::new(vec![ + Cell::new("Function Name"), + Cell::new("Instruction Count"), + ])); + + let wrap_width = 90; + let mut row_count = 0; + for (key, value) in count_vec { + let mut stripped_key = key.clone(); + if strip_hashes { + stripped_key = strip_hash(&key); + } + row_count+=1; + if row_count > top_n { + break; + } + let wrapped_key = wrap(&stripped_key, wrap_width); + let key_cell_content = wrapped_key.join("\n"); + table.add_row(Row::new(vec![ + Cell::new(&key_cell_content), + Cell::new(&value.to_string()), + ])); + } + + table.printstd(); +} + +fn _build_lookups_radare_2( + start_lookup: &mut HashMap, + end_lookup: &mut HashMap, + func_range_lookup: &mut HashMap, + elf_name: &str +) -> std::io::Result<()> { + let output = Command::new("r2") + .arg("-q") + .arg("-c") + .arg("aa;afl") + .arg(elf_name) + .output()?; + + if output.status.success() { + let result_str = str::from_utf8(&output.stdout).unwrap(); + for line in result_str.lines() { + let parts: Vec<&str> = line.split_whitespace().collect(); + let address = u64::from_str_radix(&parts[0][2..], 16).unwrap(); + let size = parts[2].parse::().unwrap(); + let end_address = address + size - 4; + let function_name = parts[3]; + start_lookup.insert(address, function_name.to_string()); + end_lookup.insert(end_address, function_name.to_string()); + func_range_lookup.insert(function_name.to_string(), (address,end_address)); + } + } else { + eprintln!("Error executing command: {}", str::from_utf8(&output.stderr).unwrap()); + } + Ok(()) +} + +fn build_goblin_lookups( + start_lookup: &mut HashMap, + end_lookup: &mut HashMap, + func_range_lookup: &mut HashMap, + elf_name: &str +) -> std::io::Result<()> { + let buffer = std::fs::read(elf_name).unwrap(); + let elf = Elf::parse(&buffer).unwrap(); + + for sym in &elf.syms { + if sym.st_type() == STT_FUNC { + let name = elf.strtab.get(sym.st_name).unwrap_or(Ok("")).unwrap_or(""); + let demangled_name = demangle(name); + let size = sym.st_size; + let start_address = sym.st_value; + let end_address = start_address + size - 4; + start_lookup.insert(start_address, demangled_name.to_string()); + end_lookup.insert(end_address, demangled_name.to_string()); + func_range_lookup.insert(demangled_name.to_string(), (start_address,end_address)); + } + } + Ok(()) +} + +fn increment_stack_counts(instruction_counts: &mut HashMap, function_stack: &[String]) { + for function_name in function_stack { + *instruction_counts.entry(function_name.clone()).or_insert(0) += 1; + } +} + +fn main() -> std::io::Result<()> { + + let args = Args::parse(); + let top_n = args.top; + let rollup_elf_path = args.rollup_elf; + let rollup_trace_path = args.rollup_trace; + let no_stack_counts = args.no_stack_counts; + let no_raw_counts = args.no_raw_counts; + let strip_hashes = args.strip_hashes; + + let mut start_lookup = HashMap::new(); + let mut end_lookup = HashMap::new(); + let mut func_range_lookup = HashMap::new(); + build_goblin_lookups(&mut start_lookup, &mut end_lookup, &mut func_range_lookup, &rollup_elf_path).unwrap(); + + let mut function_ranges: Vec<(u64, u64, String)> = func_range_lookup + .iter() + .map(|(function_name, &(start, end))| (start, end, function_name.clone())) + .collect(); + + function_ranges.sort_by_key(|&(start, _, _)| start); + + let file_content = read_to_string(&rollup_trace_path).unwrap(); + let mut function_stack: Vec = Vec::new(); + let mut instruction_counts: HashMap = HashMap::new(); + let mut counts_without_callgraph: HashMap = HashMap::new(); + let total_lines = file_content.lines().count() as u64; + let mut current_function_range : (u64,u64) = (0,0); + + let update_interval = 1000usize; + let pb = ProgressBar::new(total_lines); + pb.set_style(ProgressStyle::default_bar() + .template("{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {pos}/{len} ({eta})").unwrap() + .progress_chars("#>-")); + + + for (c,line) in file_content.lines().enumerate() { + if c % &update_interval == 0 { + pb.inc(update_interval as u64); + } + let pc = line.parse().unwrap(); + + // Raw counts without considering the callgraph at all + // we're just checking if the PC belongs to a function + // if so we're incrementing. This would ignore the call stack + // so for example "main" would only have a hundred instructions or so + if let Ok(index) = function_ranges.binary_search_by( + |&(start, end, _)| { + if pc < start { + Ordering::Greater + } else if pc > end { + Ordering::Less + } else { + Ordering::Equal + } }) + { + let (_, _, fname) = &function_ranges[index]; + *counts_without_callgraph.entry(fname.clone()).or_insert(0) += 1; + } else { + *counts_without_callgraph.entry("anonymous".to_string()).or_insert(0) += 1; + } + + // The next section considers the callstack + // We build a callstack and maintain it based on some rules + // Functions lower in the stack get their counts incremented + + // we are still in the current function + if pc > current_function_range.0 && pc <= current_function_range.1 { + increment_stack_counts(&mut instruction_counts, &function_stack); + continue; + } + + // jump to a new function (or the same one) + if let Some(function_name) = start_lookup.get(&pc) { + increment_stack_counts(&mut instruction_counts, &function_stack); + // jump to a new function (not recursive) + if !function_stack.contains(&function_name) { + function_stack.push(function_name.clone()); + current_function_range = *func_range_lookup.get(function_name).unwrap(); + } + } else { + // this means pc now points to an instruction that is + // 1. not in the current function's range + // 2. not a new function call + // we now account for a new possibility where we're returning to a function in the stack + // this need not be the immediate parent and can be any of the existing functions in the stack + // due to some optimizations that the compiler can make + let mut unwind_point = 0; + let mut unwind_found = false; + for (c,f) in function_stack.iter().enumerate() { + let (s, e) = func_range_lookup.get(f).unwrap(); + if pc > *s && pc <=*e { + unwind_point = c; + unwind_found = true; + break + } + } + // unwinding until the parent + if unwind_found { + + function_stack.truncate(unwind_point + 1); + increment_stack_counts(&mut instruction_counts, &function_stack); + continue; + } + + // if no unwind point has been found, that means we jumped to some random location + // so we'll just increment the counts for everything in the stack + increment_stack_counts(&mut instruction_counts, &function_stack); + } + + } + + pb.finish_with_message("done"); + + let mut raw_counts: Vec<(&String, &usize)> = instruction_counts.iter().collect(); + raw_counts.sort_by(|a, b| b.1.cmp(&a.1)); + + println!("\n\nTotal instructions in trace: {}", total_lines); + if !no_stack_counts { + println!("\n\n Instruction counts considering call graph"); + print_intruction_counts(raw_counts, top_n, strip_hashes); + } + + let mut raw_counts: Vec<(&String, &usize)> = counts_without_callgraph.iter().collect(); + raw_counts.sort_by(|a, b| b.1.cmp(&a.1)); + if !no_raw_counts { + println!("\n\n Instruction counts ignoring call graph"); + print_intruction_counts(raw_counts, top_n, strip_hashes); + } + Ok(()) +}